diff --git a/src/controls/Menu.qml b/src/controls/Menu.qml
index 9c76684605fa74ddaa68de85dc42e14a0ca28b00..d7aa4a0a1b628835039dfaa76ab62af6aaeaf725 100644
--- a/src/controls/Menu.qml
+++ b/src/controls/Menu.qml
@@ -129,9 +129,17 @@ MenuPrivate {
     /*! \internal */
     property Component __selfComponent: null
 
-    /*! \internal */
-    property Component style: Qt.createComponent(Settings.style + "/MenuStyle.qml", root)
+    property Component style
 
+    Component.onCompleted: {
+        if (!style) {
+            __usingDefaultStyle = true
+            style = Qt.binding(function() { return Qt.createComponent(Settings.style + "/MenuStyle.qml", root) })
+        }
+    }
+
+    /*! \internal */
+    property bool __usingDefaultStyle: false
     /*! \internal */
     property var __parentContentItem: __parentMenu.__contentItem
     /*! \internal */
@@ -142,7 +150,7 @@ MenuPrivate {
     /*! \internal */
     __contentItem: Loader {
         sourceComponent: MenuContentItem {
-            menu: root
+           __menu: root
         }
         active: !root.__isNative && root.__popupVisible
         focus: true
diff --git a/src/controls/MenuBar.qml b/src/controls/MenuBar.qml
index 42b3f39aad6dbb297adbc25ae1197a7b06aa95fb..f294d54eb1e80babbb3724ca5c9b8e4688057872 100644
--- a/src/controls/MenuBar.qml
+++ b/src/controls/MenuBar.qml
@@ -73,7 +73,6 @@ import QtQuick.Controls.Private 1.0
 MenuBarPrivate {
     id: root
 
-    /*! \internal */
     property Component style: Qt.createComponent(Settings.style + "/MenuBarStyle.qml", root)
 
     /*! \internal */
@@ -83,21 +82,18 @@ MenuBarPrivate {
         active: !root.__isNative
         focus: true
         Keys.forwardTo: [item]
-        property bool altPressed: item ? item.altPressed : false
+        property bool altPressed: item ? item.__altPressed : false
     }
 
     /*! \internal */
     property Component __menuBarComponent: Loader {
         id: menuBarLoader
 
-        property Style __style: styleLoader.item
-        property Component menuItemStyle: __style ? __style.menuItem : null
 
-        property var control: root
         onStatusChanged: if (status === Loader.Error) console.error("Failed to load panel for", root)
 
         visible: status === Loader.Ready
-        sourceComponent: __style ? __style.frame : undefined
+        sourceComponent: d.style ? d.style.background : undefined
 
         Loader {
             id: styleLoader
@@ -109,9 +105,8 @@ MenuBarPrivate {
             }
         }
 
-        property int openedMenuIndex: -1
-        property bool preselectMenuItem: false
-        property alias contentHeight: row.height
+        width: root.__contentItem.width
+        height: Math.max(row.height + d.heightPadding, item ? item.implicitHeight : 0)
 
         Binding {
             // Make sure the styled menu bar is in the background
@@ -120,63 +115,145 @@ MenuBarPrivate {
             value: menuMouseArea.z - 1
         }
 
-        focus: true
+        QtObject {
+            id: d
+
+            property Style style: styleLoader.item
+
+            property int openedMenuIndex: -1
+            property bool preselectMenuItem: false
+            property real heightPadding: style ? style.padding.top + style.padding.bottom : 0
+
+            property bool altPressed: false
+            property bool altPressedAgain: false
+            property var mnemonicsMap: ({})
+
+            function dismissActiveFocus(event, reason) {
+                if (reason) {
+                    altPressedAgain = false
+                    altPressed = false
+                    openedMenuIndex = -1
+                    root.__contentItem.parent.forceActiveFocus()
+                } else {
+                    event.accepted = false
+                }
+            }
+
+            function maybeOpenFirstMenu(event) {
+                if (altPressed && openedMenuIndex === -1) {
+                    preselectMenuItem = true
+                    openedMenuIndex = 0
+                } else {
+                    event.accepted = false
+                }
+            }
+        }
+        property alias __altPressed: d.altPressed // Needed for the menu contents
 
-        property bool altPressed: false
-        property bool altPressedAgain: false
-        property var mnemonicsMap: ({})
+        focus: true
 
         Keys.onPressed: {
             var action = null
             if (event.key === Qt.Key_Alt) {
-                if (!altPressed)
-                    altPressed = true
+                if (!d.altPressed)
+                    d.altPressed = true
                 else
-                    altPressedAgain = true
-            } else if (altPressed && (action = mnemonicsMap[event.text.toUpperCase()])) {
-                preselectMenuItem = true
+                    d.altPressedAgain = true
+            } else if (d.altPressed && (action = d.mnemonicsMap[event.text.toUpperCase()])) {
+                d.preselectMenuItem = true
                 action.trigger()
                 event.accepted = true
             }
         }
 
-        function dismissActiveFocus(event, reason) {
-            if (reason) {
-                altPressedAgain = false
-                altPressed = false
-                openedMenuIndex = -1
-                root.__contentItem.parent.forceActiveFocus()
-            } else {
-                event.accepted = false
-            }
-        }
+        Keys.onReleased: d.dismissActiveFocus(event, d.altPressedAgain && d.openedMenuIndex === -1)
+        Keys.onEscapePressed: d.dismissActiveFocus(event, d.openedMenuIndex === -1)
 
-        Keys.onReleased: dismissActiveFocus(event, altPressedAgain && openedMenuIndex === -1)
-        Keys.onEscapePressed: dismissActiveFocus(event, openedMenuIndex === -1)
+        Keys.onUpPressed: d.maybeOpenFirstMenu(event)
+        Keys.onDownPressed: d.maybeOpenFirstMenu(event)
 
-        function maybeOpenFirstMenu(event) {
-            if (altPressed && openedMenuIndex === -1) {
-                preselectMenuItem = true
-                openedMenuIndex = 0
-            } else {
-                event.accepted = false
+        Keys.onLeftPressed: {
+            if (d.openedMenuIndex > 0) {
+                d.preselectMenuItem = true
+                d.openedMenuIndex--
             }
         }
 
-        Keys.onUpPressed: maybeOpenFirstMenu(event)
-        Keys.onDownPressed: maybeOpenFirstMenu(event)
-
-        Keys.onLeftPressed: {
-            if (openedMenuIndex > 0) {
-                preselectMenuItem = true
-                openedMenuIndex--
+        Keys.onRightPressed: {
+            if (d.openedMenuIndex !== -1 && d.openedMenuIndex < root.menus.length - 1) {
+                d.preselectMenuItem = true
+                d.openedMenuIndex++
             }
         }
 
-        Keys.onRightPressed: {
-            if (openedMenuIndex !== -1 && openedMenuIndex < root.menus.length - 1) {
-                preselectMenuItem = true
-                openedMenuIndex++
+        Row {
+            id: row
+            x: d.style ? d.style.padding.left : 0
+            y: d.style ? d.style.padding.top : 0
+            width: parent.width - (d.style ? d.style.padding.left + d.style.padding.right : 0)
+            LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
+
+            Repeater {
+                id: itemsRepeater
+                model: root.menus
+                Loader {
+                    id: menuItemLoader
+
+                    property var styleData: QtObject {
+                        readonly property int index: __menuItemIndex
+                        readonly property string text: !!__menuItem && __menuItem.title
+                        readonly property bool enabled: !!__menuItem && __menuItem.enabled
+                        readonly property bool selected: menuMouseArea.hoveredItem === menuItemLoader
+                        readonly property bool open: !!__menuItem && __menuItem.__popupVisible || d.openedMenuIndex === index
+                        readonly property bool underlineMnemonic: d.altPressed
+                    }
+
+                    height: Math.max(menuBarLoader.height - d.heightPadding,
+                                     menuItemLoader.item ? menuItemLoader.item.implicitHeight : 0)
+
+                    readonly property var __menuItem: modelData
+                    readonly property int __menuItemIndex: index
+                    sourceComponent: d.style ? d.style.itemDelegate : null
+                    visible: __menuItem.visible
+
+                    Connections {
+                        target: d
+                        onOpenedMenuIndexChanged: {
+                            if (d.openedMenuIndex === index) {
+                                if (__menuItem.__usingDefaultStyle)
+                                    __menuItem.style = d.style.menuStyle
+                                __menuItem.__popup(row.LayoutMirroring.enabled ? menuItemLoader.width : 0,
+                                                   menuBarLoader.height - d.heightPadding, 0)
+                                if (d.preselectMenuItem)
+                                    __menuItem.__currentIndex = 0
+                            } else {
+                                __menuItem.__closeMenu()
+                            }
+                        }
+                    }
+
+                    Connections {
+                        target: __menuItem
+                        onPopupVisibleChanged: {
+                            if (!__menuItem.__popupVisible && d.openedMenuIndex === index)
+                                d.openedMenuIndex = -1
+                        }
+                    }
+
+                    Connections {
+                        target: __menuItem.__action
+                        onTriggered: d.openedMenuIndex = __menuItemIndex
+                    }
+
+                    Component.onCompleted: {
+                        __menuItem.__visualItem = menuItemLoader
+
+                        var title = __menuItem.title
+                        var ampersandPos = title.indexOf("&")
+                        if (ampersandPos !== -1)
+                            d.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = __menuItem.__action
+                    }
+                }
             }
         }
 
@@ -188,8 +265,8 @@ MenuBarPrivate {
             onPositionChanged: updateCurrentItem(mouse, false)
             onPressed: {
                 if (updateCurrentItem(mouse)) {
-                    menuBarLoader.preselectMenuItem = false
-                    menuBarLoader.openedMenuIndex = currentItem.menuItemIndex
+                    d.preselectMenuItem = false
+                    d.openedMenuIndex = currentItem.__menuItemIndex
                 }
             }
             onExited: hoveredItem = null
@@ -203,74 +280,13 @@ MenuBarPrivate {
                     if (!hoveredItem)
                         return false;
                     currentItem = hoveredItem
-                    if (menuBarLoader.openedMenuIndex !== -1) {
-                        menuBarLoader.preselectMenuItem = false
-                        menuBarLoader.openedMenuIndex = currentItem.menuItemIndex
+                    if (d.openedMenuIndex !== -1) {
+                        d.preselectMenuItem = false
+                        d.openedMenuIndex = currentItem.__menuItemIndex
                     }
                 }
                 return true;
             }
-
-            Row {
-                id: row
-                width: parent.width
-                LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
-
-                Repeater {
-                    id: itemsRepeater
-                    model: root.menus
-                    Loader {
-                        id: menuItemLoader
-
-                        property var menuItem: modelData
-                        property bool selected: menuMouseArea.hoveredItem === menuItemLoader
-                        property bool sunken: menuItem.__popupVisible || menuBarLoader.openedMenuIndex === index
-                        property bool showUnderlined: menuBarLoader.altPressed
-
-                        sourceComponent: menuBarLoader.menuItemStyle
-                        property int menuItemIndex: index
-                        visible: menuItem.visible
-
-                        Connections {
-                            target: menuBarLoader
-                            onOpenedMenuIndexChanged: {
-                                if (menuBarLoader.openedMenuIndex === index) {
-                                    if (row.LayoutMirroring.enabled)
-                                        menuItem.__popup(menuItemLoader.width, menuBarLoader.height, 0)
-                                    else
-                                        menuItem.__popup(0, menuBarLoader.height, 0)
-                                    if (menuBarLoader.preselectMenuItem)
-                                        menuItem.__currentIndex = 0
-                                } else {
-                                    menuItem.__closeMenu()
-                                }
-                            }
-                        }
-
-                        Connections {
-                            target: menuItem
-                            onPopupVisibleChanged: {
-                                if (!menuItem.__popupVisible && menuBarLoader.openedMenuIndex === index)
-                                    menuBarLoader.openedMenuIndex = -1
-                            }
-                        }
-
-                        Connections {
-                            target: menuItem.__action
-                            onTriggered: menuBarLoader.openedMenuIndex = menuItemIndex
-                        }
-
-                        Component.onCompleted: {
-                            menuItem.__visualItem = menuItemLoader
-
-                            var title = menuItem.title
-                            var ampersandPos = title.indexOf("&")
-                            if (ampersandPos !== -1)
-                                menuBarLoader.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = menuItem.__action
-                        }
-                    }
-                }
-            }
         }
     }
 }
diff --git a/src/controls/Private/ColumnMenuContent.qml b/src/controls/Private/ColumnMenuContent.qml
index bb21dcb9ce9b57187562a512fb6856d0eba9c459..5a56b007c167154bdcee9e992d595a4c22df0d27 100644
--- a/src/controls/Private/ColumnMenuContent.qml
+++ b/src/controls/Private/ColumnMenuContent.qml
@@ -45,11 +45,11 @@ Item {
     id: content
 
     property Component menuItemDelegate
+    property Component scrollIndicatorStyle
     property Component scrollerStyle
     property var itemsModel
     property int minWidth: 100
     property real maxHeight: 800
-    property int margin: 1
 
     signal triggered(var item)
 
@@ -59,43 +59,55 @@ Item {
     }
 
     width: Math.max(list.contentWidth, minWidth)
-    height: Math.min(list.contentHeight, fittedMaxHeight) + 2 * margin
+    height: Math.min(list.contentHeight, fittedMaxHeight)
 
-    readonly property int currentIndex: menu.__currentIndex
+    readonly property int currentIndex: __menu.__currentIndex
     property Item currentItem: null
     readonly property int itemHeight: (list.count > 0 && list.contentItem.children[0]) ? list.contentItem.children[0].height : 23
     readonly property int fittingItems: Math.floor((maxHeight - downScroller.height) / itemHeight)
     readonly property real fittedMaxHeight: itemHeight * fittingItems + downScroller.height
-    readonly property bool shouldUseScrollers: scrollView.__style.useScrollers && itemsModel.length > fittingItems
+    readonly property bool shouldUseScrollers: scrollView.style === emptyScrollerStyle && itemsModel.length > fittingItems
     readonly property real upScrollerHeight: upScroller.visible ? upScroller.height : 0
     readonly property real downScrollerHeight: downScroller.visible ? downScroller.height : 0
 
     function updateCurrentItem(mouse) {
         var pos = mapToItem(list.contentItem, mouse.x, mouse.y)
         if (!currentItem || !currentItem.contains(Qt.point(pos.x - currentItem.x, pos.y - currentItem.y))) {
-            if (currentItem && !hoverArea.pressed && currentItem.isSubmenu)
-                currentItem.closeSubMenu()
+            if (currentItem && !hoverArea.pressed
+                && currentItem.styleData.type === MenuItemType.Menu)
+                currentItem.__closeSubMenu()
             currentItem = list.itemAt(pos.x, pos.y)
             if (currentItem) {
-                menu.__currentIndex = currentItem.menuItemIndex
-                if (currentItem.isSubmenu && !currentItem.menuItem.__popupVisible)
-                    currentItem.showSubMenu(false)
+                __menu.__currentIndex = currentItem.__menuItemIndex
+                if (currentItem.styleData.type === MenuItemType.Menu
+                    && !currentItem.__menuItem.__popupVisible)
+                    currentItem.__showSubMenu(false)
             } else {
-                menu.__currentIndex = -1
+                __menu.__currentIndex = -1
             }
         }
     }
 
+    Component {
+        id: emptyScrollerStyle
+        Style {
+            padding { left: 0; right: 0; top: 0; bottom: 0 }
+            property bool scrollToClickedPosition: false
+            property Component frame: Item { visible: false }
+            property Component corner: Item { visible: false }
+            property Component __scrollbar: Item { visible: false }
+        }
+    }
+
     ScrollView {
         id: scrollView
         anchors {
             fill: parent
-            topMargin: content.margin + upScrollerHeight
-            bottomMargin: downScrollerHeight - content.margin - 1
-            rightMargin: -1
+            topMargin: upScrollerHeight
+            bottomMargin: downScrollerHeight
         }
 
-        style: scrollerStyle
+        style: scrollerStyle || emptyScrollerStyle
         __wheelAreaScrollSpeed: itemHeight
 
         ListView {
@@ -121,25 +133,23 @@ Item {
         onPositionChanged: updateCurrentItem(mouse)
         onReleased: content.triggered(currentItem)
         onExited: {
-            if (currentItem && !currentItem.menuItem.__popupVisible) {
+            if (currentItem && !currentItem.__menuItem.__popupVisible) {
                 currentItem = null
-                menu.__currentIndex = -1
+                __menu.__currentIndex = -1
             }
         }
 
         MenuContentScroller {
             id: upScroller
-            direction: "up"
+            direction: Qt.UpArrow
             visible: shouldUseScrollers && !list.atYBeginning
-            x: margin
             function scrollABit() { list.contentY -= itemHeight }
         }
 
         MenuContentScroller {
             id: downScroller
-            direction: "down"
+            direction: Qt.DownArrow
             visible: shouldUseScrollers && !list.atYEnd
-            x: margin
             function scrollABit() { list.contentY += itemHeight }
         }
     }
@@ -148,7 +158,7 @@ Item {
         interval: 1
         running: true
         repeat: false
-        onTriggered: list.positionViewAtIndex(currentIndex, scrollView.__style.useScrollers
+        onTriggered: list.positionViewAtIndex(currentIndex, !scrollView.__style
                                                             ? ListView.Center : ListView.Beginning)
     }
 
diff --git a/src/controls/Private/MenuContentItem.qml b/src/controls/Private/MenuContentItem.qml
index 7056b4e1f08c763f9f41cc4984c0b6256c004277..44312fa5389c50e08d568c24da3f3a782818cf10 100644
--- a/src/controls/Private/MenuContentItem.qml
+++ b/src/controls/Private/MenuContentItem.qml
@@ -45,42 +45,66 @@ import QtQuick.Controls.Styles 1.1
 Loader {
     id: menuFrameLoader
 
-    readonly property Style __style: styleLoader.item
-    readonly property Component menuItemStyle: __style ? __style.menuItem : null
-
-    property var menu: root
-    property alias contentWidth: content.width
-    property alias contentHeight: content.height
-
-    readonly property int subMenuXPos: width + (item && item["subMenuOverlap"] || 0)
+    property var __menu: root
 
     visible: status === Loader.Ready
-    sourceComponent: __style ? __style.frame : undefined
+    width: content.width + (d.style ? d.style.padding.left + d.style.padding.right : 0)
+    height: content.height + (d.style ? d.style.padding.top + d.style.padding.bottom : 0)
 
     Loader {
         id: styleLoader
-        active: !menu.isNative
-        sourceComponent: menu.style
+        active: !__menu.isNative
+        sourceComponent: __menu.style
         property alias __control: menuFrameLoader
         onStatusChanged: {
             if (status === Loader.Error)
-                console.error("Failed to load Style for", menu)
+                console.error("Failed to load Style for", __menu)
+        }
+    }
+    sourceComponent: d.style ? d.style.frame : undefined
+
+    QtObject {
+        id: d
+        property var mnemonicsMap: ({})
+        readonly property Style style: styleLoader.item
+        readonly property Component menuItemPanel: style ? style.menuItemPanel : null
+
+        function canBeHovered(index) {
+            var item = content.menuItemAt(index)
+            if (item && item.styleData.type !== MenuItemType.Separator && item.styleData.enabled) {
+                __menu.__currentIndex = index
+                return true
+            }
+            return false
+        }
+
+        function triggerCurrent() {
+            var item = content.menuItemAt(__menu.__currentIndex)
+            if (item)
+                content.triggered(item)
+        }
+
+        function triggerAndDismiss(item) {
+            if (item && item.styleData.type !== MenuItemType.Separator) {
+                __menu.__dismissMenu()
+                if (item.styleData.type !== MenuItemType.Menu)
+                    item.__menuItem.trigger()
+            }
         }
     }
 
     focus: true
-    property var mnemonicsMap: ({})
 
     Keys.onPressed: {
         var item = null
         if (!(event.modifiers & Qt.AltModifier)
-                && (item = mnemonicsMap[event.text.toUpperCase()])) {
-            if (item.isSubmenu) {
-                menu.__currentIndex = item.menuItemIndex
-                item.showSubMenu(true)
-                item.menuItem.__currentIndex = 0
+                && (item = d.mnemonicsMap[event.text.toUpperCase()])) {
+            if (item.styleData.type === MenuItemType.Menu) {
+                __menu.__currentIndex = item.__menuItemIndex
+                item.__showSubMenu(true)
+                item.__menuItem.__currentIndex = 0
             } else {
-                triggerAndDismiss(item)
+                d.triggerAndDismiss(item)
             }
             event.accepted = true
         } else {
@@ -88,64 +112,41 @@ Loader {
         }
     }
 
-    Keys.onEscapePressed: menu.__dismissMenu()
+    Keys.onEscapePressed: __menu.__dismissMenu()
 
     Keys.onDownPressed: {
-        if (menu.__currentIndex < 0)
-            menu.__currentIndex = -1
+        if (__menu.__currentIndex < 0)
+            __menu.__currentIndex = -1
 
-        for (var i = menu.__currentIndex + 1;
-             i < menu.items.length && !canBeHovered(i); i++)
+        for (var i = __menu.__currentIndex + 1;
+             i < __menu.items.length && !d.canBeHovered(i); i++)
             ;
         event.accepted = true
     }
 
     Keys.onUpPressed: {
-        for (var i = menu.__currentIndex - 1;
-             i >= 0 && !canBeHovered(i); i--)
+        for (var i = __menu.__currentIndex - 1;
+             i >= 0 && !d.canBeHovered(i); i--)
             ;
         event.accepted = true
     }
 
-    function canBeHovered(index) {
-        var item = content.menuItemAt(index)
-        if (item && !item["isSeparator"] && item.enabled) {
-            menu.__currentIndex = index
-            return true
-        }
-        return false
-    }
-
     Keys.onLeftPressed: {
-        if ((event.accepted = menu.__parentMenu.hasOwnProperty("title")))
+        if ((event.accepted = __menu.__parentMenu.hasOwnProperty("title")))
             __closeMenu()
     }
 
     Keys.onRightPressed: {
-        var item = content.menuItemAt(menu.__currentIndex)
-        if ((event.accepted = (item && item.isSubmenu))) {
-            item.showSubMenu(true)
-            item.menuItem.__currentIndex = 0
+        var item = content.menuItemAt(__menu.__currentIndex)
+        if ((event.accepted = (item && item.styleData.type === MenuItemType.Menu))) {
+            item.__showSubMenu(true)
+            item.__menuItem.__currentIndex = 0
         }
     }
 
-    Keys.onSpacePressed: triggerCurrent()
-    Keys.onReturnPressed: triggerCurrent()
-    Keys.onEnterPressed: triggerCurrent()
-
-    function triggerCurrent() {
-        var item = content.menuItemAt(menu.__currentIndex)
-        if (item)
-            content.triggered(item)
-    }
-
-    function triggerAndDismiss(item) {
-        if (item && !item.isSeparator) {
-            menu.__dismissMenu()
-            if (!item.isSubmenu)
-                item.menuItem.trigger()
-        }
-    }
+    Keys.onSpacePressed: d.triggerCurrent()
+    Keys.onReturnPressed: d.triggerCurrent()
+    Keys.onEnterPressed: d.triggerCurrent()
 
     Binding {
         // Make sure the styled frame is in the background
@@ -156,13 +157,15 @@ Loader {
 
     ColumnMenuContent {
         id: content
+        x: d.style ? d.style.padding.left : 0
+        y: d.style ? d.style.padding.top : 0
         menuItemDelegate: menuItemComponent
-        scrollerStyle: __style ? __style.scrollerStyle : undefined
-        itemsModel: menu.items
-        margin: menuFrameLoader.item ? menuFrameLoader.item.margin : 0
-        minWidth: menu.__minimumWidth
-        maxHeight: menuFrameLoader.item ? menuFrameLoader.item.maxHeight : 0
-        onTriggered: triggerAndDismiss(item)
+        scrollIndicatorStyle: d.style && d.style.scrollIndicator
+        scrollerStyle: d.style && d.style.__scrollerStyle
+        itemsModel: __menu.items
+        minWidth: __menu.__minimumWidth
+        maxHeight: d.style ? d.style.__maxPopupHeight : 0
+        onTriggered: d.triggerAndDismiss(item)
     }
 
     Component {
@@ -170,25 +173,38 @@ Loader {
         Loader {
             id: menuItemLoader
 
-            property var menuItem: modelData
-            readonly property bool isSeparator: !!menuItem && menuItem.type === MenuItemType.Separator
-            readonly property bool isSubmenu: !!menuItem && menuItem.type === MenuItemType.Menu
-            property bool selected: !(isSeparator || !!scrollerDirection) && menu.__currentIndex === index
-            property string text: isSubmenu ? menuItem.title : !(isSeparator || !!scrollerDirection) ? menuItem.text : ""
-            property bool showUnderlined: menu.__contentItem.altPressed
-            readonly property var scrollerDirection: menuItem["scrollerDirection"]
+            property QtObject styleData: QtObject {
+                id: opts
+                readonly property int index: __menuItemIndex
+                readonly property int type: __menuItem ? __menuItem.type : -1
+                readonly property bool selected: type !== MenuItemType.Separator && __menu.__currentIndex === index
+                readonly property string text: type === MenuItemType.Menu ? __menuItem.title :
+                                               type !== MenuItemType.Separator ? __menuItem.text : ""
+                readonly property bool underlineMnemonic: __menu.__contentItem.altPressed
+                readonly property string shortcut: !!__menuItem && __menuItem["shortcut"] || ""
+                readonly property var iconSource: !!__menuItem && __menuItem["iconSource"] || undefined
+                readonly property bool enabled: type !== MenuItemType.Separator && !!__menuItem && __menuItem.enabled
+                readonly property bool checked: !!__menuItem && !!__menuItem["checked"]
+                readonly property bool checkable: !!__menuItem && !!__menuItem["checkable"]
+                readonly property bool exclusive: !!__menuItem && !!__menuItem["exclusiveGroup"]
+                readonly property int scrollerDirection: Qt.NoArrow
+            }
 
-            property int menuItemIndex: index
+            readonly property var __menuItem: modelData
+            readonly property int __menuItemIndex: index
 
-            sourceComponent: menuFrameLoader.menuItemStyle
-            enabled: visible && !isSeparator && !!menuItem && menuItem.enabled
-            visible: !!menuItem && menuItem.visible
+            sourceComponent: d.menuItemPanel
+            enabled: visible && opts.enabled
+            visible: !!__menuItem && __menuItem.visible
             active: visible
 
-            function showSubMenu(immediately) {
+            function __showSubMenu(immediately) {
                 if (immediately) {
-                    if (menu.__currentIndex === menuItemIndex)
-                        menuItem.__popup(menuFrameLoader.subMenuXPos, 0, -1)
+                    if (__menu.__currentIndex === __menuItemIndex) {
+                        if (__menuItem.__usingDefaultStyle)
+                            __menuItem.style = __menu.style
+                        __menuItem.__popup(menuFrameLoader.width - (d.style.submenuOverlap + d.style.padding.right), -d.style.padding.top, -1)
+                    }
                 } else {
                     openMenuTimer.start()
                 }
@@ -197,37 +213,37 @@ Loader {
             Timer {
                 id: openMenuTimer
                 interval: 50
-                onTriggered: menuItemLoader.showSubMenu(true)
+                onTriggered: menuItemLoader.__showSubMenu(true)
             }
 
-            function closeSubMenu() { closeMenuTimer.start() }
+            function __closeSubMenu() { closeMenuTimer.start() }
 
             Timer {
                 id: closeMenuTimer
                 interval: 1
                 onTriggered: {
-                    if (menu.__currentIndex !== menuItemIndex)
-                        menuItem.__closeMenu()
+                    if (__menu.__currentIndex !== __menuItemIndex)
+                        __menuItem.__closeMenu()
                 }
             }
 
             onLoaded: {
-                menuItem.__visualItem = menuItemLoader
+                __menuItem.__visualItem = menuItemLoader
 
                 if (content.width < item.implicitWidth)
                     content.width = item.implicitWidth
 
-                var title = text
+                var title = opts.text
                 var ampersandPos = title.indexOf("&")
                 if (ampersandPos !== -1)
-                    menuFrameLoader.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = menuItemLoader
+                    d.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = menuItemLoader
             }
 
             Binding {
                 target: menuItemLoader.item
                 property: "width"
                 property alias menuItem: menuItemLoader.item
-                value: menuItem ? Math.max(menu.__minimumWidth, content.width) - 2 * menuItem.x : 0
+                value: menuItem ? Math.max(__menu.__minimumWidth, content.width) - 2 * menuItem.x : 0
             }
         }
     }
diff --git a/src/controls/Private/MenuContentScroller.qml b/src/controls/Private/MenuContentScroller.qml
index 30a8825af2ade1fdd94a4c94b787f4554a4b5674..e18132bb0312acb704ca291292b41deae4d2c51e 100644
--- a/src/controls/Private/MenuContentScroller.qml
+++ b/src/controls/Private/MenuContentScroller.qml
@@ -39,27 +39,36 @@
 ****************************************************************************/
 
 import QtQuick 2.1
+import QtQuick.Controls 1.1
 
 MouseArea {
-    property string direction
+    id: scrollIndicator
+    property int direction: 0
 
     anchors {
-        top: direction === "up" ? parent.top : undefined
-        bottom: direction === "down" ? parent.bottom : undefined
+        top: direction === Qt.UpArrow ? parent.top : undefined
+        bottom: direction === Qt.DownArrow ? parent.bottom : undefined
     }
 
     hoverEnabled: visible
-    height: scrollerLoader.item.height
+    height: scrollerLoader.height
     width: parent.width
 
     Loader {
         id: scrollerLoader
 
-        sourceComponent: menuItemDelegate
-        property int index: -1
-        property var modelData: {
-            "visible": true,
-            "scrollerDirection": direction,
+        width: parent.width
+        sourceComponent: scrollIndicatorStyle
+        // Extra property values for desktop style
+        property var __menuItem: null
+        property var styleData: {
+            "index": -1,
+            "type": MenuItemType.ScrollIndicator,
+            "text": "",
+            "selected": scrollIndicator.containsMouse,
+            "scrollerDirection": scrollIndicator.direction,
+            "checkable": false,
+            "checked": false,
             "enabled": true
         }
     }
diff --git a/src/controls/Private/MenuItemSubControls.qml b/src/controls/Private/MenuItemSubControls.qml
new file mode 100644
index 0000000000000000000000000000000000000000..af62bf5be63880f49b812a1193a2f927e3a690fc
--- /dev/null
+++ b/src/controls/Private/MenuItemSubControls.qml
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+
+QtObject {
+    property Component background: null
+    property Component label: null
+    property Component submenuIndicator: null
+    property Component shortcut: null
+    property Component checkmarkIndicator: null
+}
diff --git a/src/controls/Private/private.pri b/src/controls/Private/private.pri
index 7852edffbfd6f69455e27e9d1a0cfded079875c5..b12cabd771784dd577c650825091e9279b289492 100644
--- a/src/controls/Private/private.pri
+++ b/src/controls/Private/private.pri
@@ -34,6 +34,7 @@ PRIVATE_QML_FILES += \
     $$PWD/SourceProxy.qml\
     $$PWD/Style.qml \
     $$PWD/style.js \
+    $$PWD/MenuItemSubControls.qml \
     $$PWD/ModalPopupBehavior.qml \
     $$PWD/StackViewSlideDelegate.qml \
     $$PWD/StackView.js \
diff --git a/src/controls/Private/qmldir b/src/controls/Private/qmldir
index 5dc8061cde841b2f6ec0d883a4cb125041a02c06..7536b7e63f95b1bde0c24108101828ae72fbaf04 100644
--- a/src/controls/Private/qmldir
+++ b/src/controls/Private/qmldir
@@ -7,6 +7,7 @@ BasicButton 1.0 BasicButton.qml
 ScrollBar 1.0 ScrollBar.qml
 ScrollViewHelper 1.0 ScrollViewHelper.qml
 Style 1.0 Style.qml
+MenuItemSubControls 1.0 MenuItemSubControls.qml
 TabBar 1.0 TabBar.qml
 StackViewSlideDelegate 1.0 StackViewSlideDelegate.qml
 StyleHelpers 1.0 style.js
diff --git a/src/controls/Private/qquickstyleitem.cpp b/src/controls/Private/qquickstyleitem.cpp
index 105bb9f5470eb8b9e2fcf9d24bcaebcf17bfbd59..958adbdd9c52ea59617f993572feba335b9987b2 100644
--- a/src/controls/Private/qquickstyleitem.cpp
+++ b/src/controls/Private/qquickstyleitem.cpp
@@ -51,6 +51,7 @@
 #include <qquickwindow.h>
 #include "private/qguiapplication_p.h"
 #include <QtGui/qpa/qplatformtheme.h>
+#include "../qquickmenuitem_p.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -503,19 +504,23 @@ void QQuickStyleItem::initStyleOption()
         // For GTK style. See below, in setElementType()
         setProperty("_q_isComboBoxPopupItem", m_itemType == ComboBoxItem);
 
-        QString scrollerDirection = m_properties["scrollerDirection"].toString();
-        if (!scrollerDirection.isEmpty()) {
+        QQuickMenuItemType::MenuItemType type =
+                static_cast<QQuickMenuItemType::MenuItemType>(m_properties["type"].toInt());
+        if (type == QQuickMenuItemType::ScrollIndicator) {
+            int scrollerDirection = m_properties["scrollerDirection"].toInt();
             opt->menuItemType = QStyleOptionMenuItem::Scroller;
-            opt->state |= scrollerDirection == "up" ?
+            opt->state |= scrollerDirection == Qt::UpArrow ?
                         QStyle::State_UpArrow : QStyle::State_DownArrow;
-        } else if (text().isEmpty()) {
+        } else if (type == QQuickMenuItemType::Separator) {
             opt->menuItemType = QStyleOptionMenuItem::Separator;
         } else {
             opt->text = text();
 
-            if (m_properties["isSubmenu"].toBool()) {
+            if (type == QQuickMenuItemType::Menu) {
                 opt->menuItemType = QStyleOptionMenuItem::SubMenu;
             } else {
+                opt->menuItemType = QStyleOptionMenuItem::Normal;
+
                 QString shortcut = m_properties["shortcut"].toString();
                 if (!shortcut.isEmpty()) {
                     opt->text += QLatin1Char('\t') + shortcut;
@@ -527,8 +532,6 @@ void QQuickStyleItem::initStyleOption()
                     QVariant exclusive = m_properties["exclusive"];
                     opt->checkType = exclusive.toBool() ? QStyleOptionMenuItem::Exclusive :
                                                           QStyleOptionMenuItem::NonExclusive;
-                } else {
-                    opt->menuItemType = QStyleOptionMenuItem::Normal;
                 }
             }
             if (m_properties["icon"].canConvert<QIcon>())
diff --git a/src/controls/Styles/Base/ComboBoxStyle.qml b/src/controls/Styles/Base/ComboBoxStyle.qml
index 6eff488dea03ddc9bdddfc2daf80631ba8194b83..14f84c0d14a9c2ddbf29857aed7efae3a089ebab 100644
--- a/src/controls/Styles/Base/ComboBoxStyle.qml
+++ b/src/controls/Styles/Base/ComboBoxStyle.qml
@@ -213,15 +213,15 @@ Style {
 
     /*! \internal */
     property Component __dropDownStyle: MenuStyle {
-        maxPopupHeight: 600
+        __maxPopupHeight: 600
         __menuItemType: "comboboxitem"
-        scrollerStyle: ScrollViewStyle {
-            property bool useScrollers: false
-        }
+        __scrollerStyle: ScrollViewStyle { }
     }
 
     /*! \internal */
     property Component __popupStyle: Style {
+        property int __maxPopupHeight: 400
+        property int submenuOverlap: 0
 
         property Component frame: Rectangle {
             width: (parent ? parent.contentWidth : 0)
@@ -231,7 +231,7 @@ Style {
             property int margin: 1
         }
 
-        property Component menuItem: Text {
+        property Component menuItemPanel: Text {
             text: "NOT IMPLEMENTED"
             color: "red"
             font {
@@ -240,13 +240,6 @@ Style {
             }
         }
 
-        property Component scrollerStyle: Style {
-            padding { left: 0; right: 0; top: 0; bottom: 0 }
-            property bool scrollToClickedPosition: false
-            property Component frame: Item { visible: false }
-            property Component corner: Item { visible: false }
-            property Component __scrollbar: Item { visible: false }
-            property bool useScrollers: true
-        }
+        property Component __scrollerStyle: null
     }
 }
diff --git a/src/controls/Styles/Base/MenuBarStyle.qml b/src/controls/Styles/Base/MenuBarStyle.qml
index 3a3b552dd66e9abf1e7b87747aa485a98a3f06f6..050367c39782d66bd61f4b27f394b3139c029f30 100644
--- a/src/controls/Styles/Base/MenuBarStyle.qml
+++ b/src/controls/Styles/Base/MenuBarStyle.qml
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the Qt Quick Controls module of the Qt Toolkit.
@@ -44,33 +44,76 @@ import QtQuick.Controls.Private 1.0
 
 /*!
     \qmltype MenuBarStyle
-    \internal
-    \ingroup applicationwindowstyling
     \inqmlmodule QtQuick.Controls.Styles
+    \since 5.3
+    \ingroup controlsstyling
+    \brief Provides custom styling for MenuBar
+
+    \note Styling menu bars may not be supported on platforms using native menu bars
+    through their QPA plugin.
 */
 
 Style {
-    readonly property color __backgroundColor: "#dcdcdc"
 
-    property Component frame: Rectangle {
-        width: control.__contentItem.width
-        height: contentHeight
-        color: __backgroundColor
+    /*! Returns a formatted string to render mnemonics for a given menu item.
+
+        The mnemonic character is prefixed by an ampersand in the original string.
+
+        Passing \c true for \c underline will underline the mnemonic character (e.g.,
+        \c formatMnemonic("&File", true) will return \c "<u>F</u>ile"). Passing \c false
+        for \c underline will return the plain text form (e.g., \c formatMnemonic("&File", false)
+        will return \c "File").
+
+        \sa label
+    */
+    function formatMnemonic(text, underline) {
+        return underline ? StyleHelpers.stylizeMnemonics(text) : StyleHelpers.removeMnemonics(text)
     }
 
-    property Component menuItem: Rectangle {
-        width: text.width + 12
-        height: text.height + 4
-        color: sunken ? "#49d" :__backgroundColor
+    /*! The background for the full menu bar.
+
+        The background will be extended to the full containing window width.
+        Its height will always fit all of the menu bar items. The final size
+        will include the paddings.
+    */
+    property Component background: Rectangle {
+        color: "#dcdcdc"
+        implicitHeight: 20
+    }
+
+    /*! The menu bar item.
+
+        \target styleData properties
+        This item has to be configured using the \b styleData object which is in scope,
+        and contains the following read-only properties:
+        \table
+            \row \li \b {styleData.index} : int \li The index of the menu item in its menu.
+            \row \li \b {styleData.selected} : bool \li \c true if the menu item is selected.
+            \row \li \b {styleData.open} : bool \li \c true when the pull down menu is open.
+            \row \li \b {styleData.text} : string \li The menu bar item's text.
+            \row \li \b {styleData.underlineMnemonic} : bool \li When \c true, the style should underline the menu item's label mnemonic.
+        \endtable
+
+    */
+    property Component itemDelegate: Rectangle {
+        implicitWidth: text.width + 12
+        implicitHeight: text.height + 4
+        color: styleData.open ? "#49d" : "transparent"
 
         SystemPalette { id: syspal }
 
         Text {
             id: text
-            text: StyleHelpers.stylizeMnemonics(menuItem.title)
+            text: formatMnemonic(styleData.text, styleData.underlineMnemonic)
             anchors.centerIn: parent
             renderType: Text.NativeRendering
-            color: sunken ? "white" : syspal.windowText
+            color: styleData.open ? "white" : syspal.windowText
         }
     }
+
+    /*! The style component for the menubar's own menus and their submenus.
+
+        \sa MenuStyle
+    */
+    property Component menuStyle: MenuStyle { }
 }
diff --git a/src/controls/Styles/Base/MenuStyle.qml b/src/controls/Styles/Base/MenuStyle.qml
index c05c6a6d100a4a9a20361e0811b4e9d770b3e922..bec8410b7e3b06a871b234d594b431f10c7e7e18 100644
--- a/src/controls/Styles/Base/MenuStyle.qml
+++ b/src/controls/Styles/Base/MenuStyle.qml
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the Qt Quick Controls module of the Qt Toolkit.
@@ -45,67 +45,190 @@ import QtQuick.Controls.Private 1.0
 
 /*!
     \qmltype MenuStyle
-    \internal
-    \ingroup menusstyling
     \inqmlmodule QtQuick.Controls.Styles
+    \since 5.3
+    \ingroup controlsstyling
+    \brief Provides custom styling for Menu
+
+    \target styleData properties
+    The \b styleData object contains the following read-only properties:
+    \table
+        \row \li \b {styleData.index} : int \li The index of the menu item in its menu.
+        \row \li \b {styleData.type} : enumeration \li The type of menu item. See below for possible values.
+        \row \li \b {styleData.selected} : bool \li \c true if the menu item is selected.
+        \row \li \b {styleData.text} : string \li The menu item's text, or title if it's a submenu.
+        \row \li \b {styleData.underlineMnemonic} : bool \li Whether the style should underline the menu item's label mnemonic.
+        \row \li \b {styleData.shortcut} : string \li The text for the menu item's shortcut.
+        \row \li \b {styleData.iconSource} : url \li The source URL to the menu item's icon. Undefined if it has no icon.
+        \row \li \b {styleData.enabled} : bool \li \c true if the menu item is enabled.
+        \row \li \b {styleData.checkable} : bool \li \c true if the menu  item is checkable.
+        \row \li \b {styleData.exclusive} : bool \li \c true if the menu item is checkable, and it's part of an \l ExclusiveGroup.
+        \row \li \b {styleData.checked} : bool \li \c true if the menu item is checkable and currently checked.
+        \row \li \b {styleData.scrollerDirection} : enumeration \li If the menu item is a scroller, its pointing direction.
+                                                                     Valid values are \c Qt.UpArrow, \c Qt.DownArrow, and \c Qt.NoArrow.
+    \endtable
+
+    The valid values for \b {styleData.type} are:
+    \list
+    \li MenuItemType.Item
+    \li MenuItemType.Menu
+    \li MenuItemType.Separator
+    \li MenuItemType.ScrollIndicator
+    \endlist
+
+    \note Styling menus may not be supported on platforms using native menus
+    through their QPA plugin.
 */
 
 Style {
     id: styleRoot
 
-    property string __menuItemType: "menuitem"
-    property real maxPopupHeight: 600 // ### FIXME Screen.desktopAvailableHeight * 0.99
+    padding {
+        top: 1
+        bottom: 1
+        left: 1
+        right: 1
+    }
 
-    property Component frame: Rectangle {
-        width: (parent ? parent.contentWidth : 0) + 2
-        height: (parent ? parent.contentHeight : 0) + 2
+    /*! The amount of pixels by which a submenu popup overlaps horizontally its parent menu. */
+    property int submenuOverlap: 1
+
+    /*! Returns a rich-text string to render mnemonics for a given menu item.
+
+        The mnemonic character is prefixed by an ampersand in the original string.
 
-        color: "lightgray"
-        border { width: 1; color: "darkgray" }
+        Passing \c true for \c underline will underline the mnemonic character (e.g.,
+        \c formatMnemonic("&Open...", true) will return \c "<u>O</u>pen..."). Passing \c false
+        for \c underline will return the plain text form (e.g., \c formatMnemonic("&Open...", false)
+        will return \c "Open...").
 
-        property int subMenuOverlap: -1
-        property real maxHeight: maxPopupHeight
-        property int margin: 1
+        \sa label
+    */
+    function formatMnemonic(text, underline) {
+        return underline ? StyleHelpers.stylizeMnemonics(text) : StyleHelpers.removeMnemonics(text)
     }
 
-    property Component menuItem: Rectangle {
-        x: 1
-        y: 1
-        implicitWidth: Math.max((parent ? parent.width : 0),
-                                18 + text.paintedWidth + (rightDecoration.visible ? rightDecoration.width + 40 : 12))
-        implicitHeight: isSeparator ? text.font.pixelSize / 2 : !!scrollerDirection ? text.font.pixelSize * 0.75 : text.paintedHeight + 4
-        color: selected && enabled ? "" : backgroundColor
-        gradient: selected && enabled ? selectedGradient : undefined
-        border.width: 1
-        border.color: selected && enabled ? Qt.darker(selectedColor, 1) : color
-        readonly property int leftMargin: __menuItemType === "menuitem" ? 18 : 0
-
-        readonly property color backgroundColor: "#dcdcdc"
-        readonly property color selectedColor: "#49d"
-        Gradient {
-            id: selectedGradient
-            GradientStop {color: Qt.lighter(selectedColor, 1.3)  ; position: -0.2}
-            GradientStop {color: selectedColor; position: 1.4}
+    /*! The background frame for the menu popup.
+
+        The \l Menu will resize the frame to its contents plus the padding.
+    */
+    property Component frame: Rectangle {
+        color: styleRoot.__backgroundColor
+        border { width: 1; color: styleRoot.__borderColor }
+    }
+
+    /*! \qmlproperty Object MenuStyle::itemDelegate
+
+        The object containing the menu item subcontrol components. These subcontrols are used
+        for normal menu items only, i.e. not for separators or scroll indicators.
+
+        The subcontrols are:
+
+        \list
+        \li \b {itemDelegate.background} : Component
+
+        The menu item background component.
+
+        Its appearance generally changes with \l {styleData properties} {styleData.selected}
+        and \l {styleData properties} {styleData.enabled}.
+
+        The default implementation shows only when the item is enabled and selected. It remains
+        invisible otherwise.
+
+        \li \b {itemDelegate.label} : Component
+
+        Component for the actual text label.
+
+        The text itself is fetched from \l {styleData properties} {styleData.text}, and its appearance should depend
+        on \l {styleData properties} {styleData.enabled} and \l {styleData properties} {styleData.selected}.
+
+        If \l {styleData properties} {styleData.underlineMnemonic} is true, the label should underline its mnemonic
+        character. \l formatMnemonic provides the default formatting.
+
+        \li \b {itemDelegate.submenuIndicator} : Component
+
+        It indicates that the current menu item is a submenu.
+
+        Only used when \l {styleData properties} {styleData.type} equals \c MenuItemType.Menu.
+
+        \li \b {itemDelegate.shortcut} : Component
+
+        Displays the shortcut attached to the menu item.
+
+        Only used when \l {styleData properties} {styleData.shortcut} is not empty.
+
+        \li \b {itemDelegate.checkmarkIndicator} : Component
+
+        Will be used when \l {styleData properties} {styleData.checkable} is \c true and its appearance
+        may depend on \l {styleData properties} {styleData.exclusive}, i.e., whether it will behave like a
+        checkbox or a radio button. Use \l {styleData properties} {styleData.checked} for the checked state.
+        \endlist
+
+        \note This property cannot be overwritten although all of the subcontrol properties can.
+    */
+    property alias itemDelegate: internalMenuItem
+
+    MenuItemSubControls {
+        id: internalMenuItem
+
+        background: Rectangle {
+            visible: styleData.selected && styleData.enabled
+            gradient: Gradient {
+                id: selectedGradient
+                GradientStop { color: Qt.lighter(__selectedBackgroundColor, 1.3); position: -0.2 }
+                GradientStop { color: __selectedBackgroundColor; position: 1.4 }
+            }
+
+            border.width: 1
+            border.color: Qt.darker(__selectedBackgroundColor, 1)
+            antialiasing: true
         }
-        antialiasing: true
 
-        SystemPalette {
-            id: syspal
-            colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled
+        label: Text {
+            text: formatMnemonic(styleData.text, styleData.underlineMnemonic)
+            color: __currentTextColor
+            font.pixelSize: __labelFontPixelSize
         }
 
-        readonly property string itemText: parent ? parent.text : ""
-        readonly property bool mirrored: Qt.application.layoutDirection === Qt.RightToLeft
+        submenuIndicator: Text {
+            text: __mirrored ? "\u25c2" : "\u25b8" // BLACK LEFT/RIGHT-POINTING SMALL TRIANGLE
+            font.pixelSize: __labelFontPixelSize
+            color: __currentTextColor
+            style: styleData.selected ? Text.Normal : Text.Raised
+            styleColor: Qt.lighter(color, 4)
+        }
 
-        Loader {
-            id: checkMark
-            x: mirrored ? parent.width - width - 4 : 4
-            y: 6
-            active: __menuItemType === "menuitem" && !!menuItem && !!menuItem["checkable"]
-            sourceComponent: exclusive ? exclusiveCheckMark : nonExclusiveCheckMark
+        shortcut: Text {
+            text: styleData.shortcut
+            font.pixelSize: __labelFontPixelSize * 0.9
+            color: __currentTextColor
+        }
 
-            readonly property bool checked: !!menuItem && !!menuItem.checked
-            readonly property bool exclusive: !!menuItem && !!menuItem["exclusiveGroup"]
+        checkmarkIndicator: Loader {
+            sourceComponent: styleData.exclusive ? exclusiveCheckMark : nonExclusiveCheckMark
+            Component {
+                id: exclusiveCheckMark
+                Rectangle {
+                    x: 1
+                    width: 10
+                    height: 10
+                    color: "white"
+                    border.color: "gray"
+                    antialiasing: true
+                    radius: height/2
+
+                    Rectangle {
+                        anchors.centerIn: parent
+                        visible: styleData.checked
+                        width: 4
+                        height: 4
+                        color: "#666"
+                        border.color: "#222"
+                        antialiasing: true
+                        radius: height/2
+                    }
+                }
+            }
 
             Component {
                 id: nonExclusiveCheckMark
@@ -120,13 +243,11 @@ Style {
 
                     Rectangle {
                         antialiasing: true
-                        visible: checkMark.checked
+                        visible: styleData.checked
                         color: "#666"
                         radius: 1
                         anchors.margins: 4
                         anchors.fill: parent
-                        anchors.topMargin: 3
-                        anchors.bottomMargin: 5
                         border.color: "#222"
                         Rectangle {
                             anchors.fill: parent
@@ -137,70 +258,15 @@ Style {
                     }
                 }
             }
-
-            Component {
-                id: exclusiveCheckMark
-                Rectangle {
-                    x: 1
-                    width: 10
-                    height: 10
-                    color: "white"
-                    border.color: "gray"
-                    antialiasing: true
-                    radius: height/2
-
-                    Rectangle {
-                        anchors.centerIn: parent
-                        visible: checkMark.checked
-                        width: 4
-                        height: 4
-                        color: "#666"
-                        border.color: "#222"
-                        antialiasing: true
-                        radius: height/2
-                    }
-                }
-            }
-        }
-
-        Text {
-            id: text
-            visible: !isSeparator
-            text: StyleHelpers.stylizeMnemonics(itemText)
-            readonly property real offset: __menuItemType === "menuitem" ? 24 : 6
-            x: mirrored ? parent.width - width - offset : offset
-            anchors.verticalCenter: parent.verticalCenter
-            renderType: Text.NativeRendering
-            color: selected && enabled ? "white" : syspal.text
         }
+    }
 
-        Text {
-            id: rightDecoration
-            readonly property string shortcut: !!menuItem && menuItem["shortcut"] || ""
-            visible: isSubmenu || shortcut !== ""
-            text: isSubmenu ? mirrored ? "\u25c2" : "\u25b8" // BLACK LEFT/RIGHT-POINTING SMALL TRIANGLE
-                            : shortcut
-            LayoutMirroring.enabled: mirrored
-            anchors {
-                right: parent.right
-                rightMargin: 6
-                baseline: isSubmenu ? undefined : text.baseline
-            }
-            font.pixelSize: isSubmenu ? text.font.pixelSize : text.font.pixelSize * 0.9
-            color: text.color
-            renderType: Text.NativeRendering
-            style: selected || !isSubmenu ? Text.Normal : Text.Raised; styleColor: Qt.lighter(color, 4)
-        }
-
-        Image {
-            id: scrollerDecoration
-            visible: !!scrollerDirection
-            anchors.centerIn: parent
-            source: scrollerDirection === "up" ? "images/arrow-up.png" : "images/arrow-down.png"
-        }
+    /*! Component for the separator menu item.
 
+        Will be used when \l {styleData properties} {styleData.type} equals \c MenuItemType.Separator.
+    */
+    property Component separator: Item {
         Rectangle {
-            visible: isSeparator
             width: parent.width - 2
             height: 1
             x: 1
@@ -209,12 +275,178 @@ Style {
         }
     }
 
-    property Component scrollerStyle: Style {
-        padding { left: 0; right: 0; top: 0; bottom: 0 }
-        property bool scrollToClickedPosition: false
-        property Component frame: Item { visible: false }
-        property Component corner: Item { visible: false }
-        property Component __scrollbar: Item { visible: false }
-        property bool useScrollers: true
+    /*! Component for the scroll indicator menu item.
+
+        Will be used when \l {styleData properties} {styleData.type} equals \c MenuItemType.ScrollIndicator.
+        Its appearance should follow \l {styleData properties} {styleData.scrollerDirection}.
+
+        This is the item added at the top and bottom of the menu popup when its contents won't fit the screen
+        to indicate more content is available in the direction of the arrow.
+    */
+    property Component scrollIndicator: Image {
+        anchors.centerIn: parent
+        source: styleData.scrollerDirection === Qt.UpArrow ? "images/arrow-up.png" : "images/arrow-down.png"
+    }
+
+    /*! \internal */
+    property string __menuItemType: "menuitem"
+
+    /*! \internal
+        The menu popup frame background color.
+
+        This is set to be a uniform background. If you want a gradient or a pixmap,
+        you should override \l frame.
+
+        \sa frame, borderColor
+    */
+    property color __backgroundColor: "#dcdcdc"
+
+    /*! \internal
+        The menu popup frame border color.
+
+        The border width is set to 1 pixel. Override \l frame if you want a larger border.
+
+        \sa frame, backgroundColor
+    */
+    property color __borderColor: "darkgray"
+
+    /*! \internal
+        The maximum height for a popup before it will show scrollers.
+    */
+    property int __maxPopupHeight: 600
+
+    /*! \internal
+        The menu item background color when selected.
+
+        This property is provided for convenience and only sets the color.
+        It does not change the style in any other way.
+    */
+    property color __selectedBackgroundColor: "#49d"
+
+    /*! \internal
+        The menu item label color.
+
+        When set, keyboard shorcuts get the same color as the item's text.
+
+        \sa selectedLabelColor, disabledLabelColor
+    */
+    property color __labelColor: "#444"
+
+    /*! \internal
+        The menu item label color when selected.
+
+        \sa labelColor, selectedLabelColor
+    */
+    property color __selectedLabelColor: "white"
+
+    /*! \internal
+        The menu item label color when disabled.
+
+        \sa labelColor, disabledLabelColor
+    */
+    property color __disabledLabelColor: "gray"
+
+
+    /*! \internal */
+    readonly property bool __mirrored: Qt.application.layoutDirection === Qt.RightToLeft
+
+    /*! \internal */
+    readonly property real __labelFontPixelSize: TextSingleton.font.pixelSize
+
+    /*! \internal
+        The margin between the frame and the menu item label's left side.
+
+        Generally, this should be large enough to fit optional checkmarks on
+        the label's left side.
+    */
+    property int __leftLabelMargin: 18
+
+    /*! \internal
+        The margin between the menu item label's right side and the frame. */
+    property int __rightLabelMargin: 12
+
+    /*! \internal
+        The minimum spacing between the menu item label's text right side and any
+        element located on its right (submenu indicator or shortcut).
+    */
+    property int __minRightLabelSpacing: 28
+
+    /*! \internal */
+    property Component __scrollerStyle: null
+
+    /*! \internal
+        The menu item contents itself.
+
+        The default implementation uses \l MenuItemStyle.
+    */
+    property Component menuItemPanel: Item {
+        id: panel
+
+        property QtObject __styleData: styleData
+        /*! \internal
+            The current color of the text label.
+
+            Use this if you're overriding e.g. \l shortcutIndicator to keep the color matched
+            with \l label, or to derive new colors from it.
+        */
+        property color currentTextColor: !styleData.enabled ? __disabledLabelColor :
+                                         styleData.selected ? __selectedLabelColor : __labelColor
+
+        implicitWidth: Math.max((parent ? parent.width : 0),
+                                Math.round(__leftLabelMargin + labelLoader.width + __rightLabelMargin +
+                                           (rightIndicatorLoader.active ? __minRightLabelSpacing + rightIndicatorLoader.width : 0)))
+        implicitHeight: Math.round(styleData.isSeparator ? __labelFontPixelSize / 2 :
+                                   !!styleData.scrollerDirection ? __labelFontPixelSize * 0.75 : labelLoader.height + 4)
+
+        Loader {
+            property alias styleData: panel.__styleData
+            property alias __currentTextColor: panel.currentTextColor
+            anchors.fill: parent
+            sourceComponent: itemDelegate.background
+        }
+
+        Loader {
+            property alias styleData: panel.__styleData
+            property alias __currentTextColor: panel.currentTextColor
+            anchors.fill: parent
+            sourceComponent: separator
+            active: styleData.type === MenuItemType.Separator
+        }
+
+        Loader {
+            property alias styleData: panel.__styleData
+            property alias __currentTextColor: panel.currentTextColor
+            x: __mirrored ? parent.width - width - 4 : 4
+            y: styleData.exclusive ? 5 : 4
+            active: __menuItemType === "menuitem" && styleData.checkable
+            sourceComponent: itemDelegate.checkmarkIndicator
+        }
+
+        Loader {
+            id: labelLoader
+            readonly property real offset: __menuItemType === "menuitem" ? __leftLabelMargin : 6
+            property alias styleData: panel.__styleData
+            property alias __currentTextColor: panel.currentTextColor
+            x: __mirrored ? parent.width - width - offset : offset
+            y: 1
+            active: styleData.type !== MenuItemType.Separator
+            sourceComponent: itemDelegate.label
+            baselineOffset: item ? item.baselineOffset : 0.0
+        }
+
+        Loader {
+            id: rightIndicatorLoader
+            property alias styleData: panel.__styleData
+            property alias __currentTextColor: panel.currentTextColor
+            active: styleData.type === MenuItemType.Menu || styleData.shortcut !== ""
+            sourceComponent: styleData.type === MenuItemType.Menu ? itemDelegate.submenuIndicator : itemDelegate.shortcut
+            LayoutMirroring.enabled: __mirrored
+            baselineOffset: item ? item.baselineOffset : 0.0
+            anchors {
+                right: parent.right
+                rightMargin: 6
+                baseline: !styleData.isSubmenu ? labelLoader.baseline : undefined
+            }
+        }
     }
 }
diff --git a/src/controls/Styles/Desktop/ComboBoxStyle.qml b/src/controls/Styles/Desktop/ComboBoxStyle.qml
index d1b456b677ad7b55b1702a4fcb7f338802dff055..613bba04e620f8d81849527377d31ed7653c9ea1 100644
--- a/src/controls/Styles/Desktop/ComboBoxStyle.qml
+++ b/src/controls/Styles/Desktop/ComboBoxStyle.qml
@@ -40,7 +40,6 @@
 import QtQuick 2.1
 import QtQuick.Window 2.1
 import QtQuick.Controls 1.1
-import QtQuick.Controls.Styles 1.1
 import QtQuick.Controls.Private 1.0
 import "." as Desktop
 
@@ -86,18 +85,18 @@ Style {
     }
 
     property Component __dropDownStyle: Style {
+        property int __maxPopupHeight: 600
+        property int submenuOverlap: 0
+
         property Component frame: StyleItem {
             elementType: "frame"
-
             width: (parent ? parent.contentWidth : 0)
             height: (parent ? parent.contentHeight : 0) + 2 * pixelMetric("defaultframewidth")
-            property real maxHeight: 600
-            property int margin: pixelMetric("menuvmargin") + pixelMetric("menupanelwidth")
         }
 
-        property Component menuItem: StyleItem {
+        property Component menuItemPanel: StyleItem {
             elementType: "itemrow"
-            selected: parent ? parent.selected : false
+            selected: styleData.selected
 
             x: pixelMetric("defaultframewidth")
             y: pixelMetric("defaultframewidth")
@@ -110,13 +109,11 @@ Style {
                 elementType: "item"
                 contentWidth: textWidth(text)
                 contentHeight: textHeight(text)
-                text: parent && parent.parent ? parent.parent.text : ""
+                text: styleData.text
                 selected: parent ? parent.selected : false
             }
         }
 
-        property Component scrollerStyle: Desktop.ScrollViewStyle {
-            property bool useScrollers: false
-        }
+        property Component __scrollerStyle: Desktop.ScrollViewStyle { }
     }
 }
diff --git a/src/controls/Styles/Desktop/MenuBarStyle.qml b/src/controls/Styles/Desktop/MenuBarStyle.qml
index a8b389c1a70da9eaf8f37aabfb18cdde56a46d4f..c032a7c0b095c746c1e0496e1255a60745e5e0d2 100644
--- a/src/controls/Styles/Desktop/MenuBarStyle.qml
+++ b/src/controls/Styles/Desktop/MenuBarStyle.qml
@@ -41,13 +41,11 @@
 import QtQuick 2.1
 import QtQuick.Controls 1.1
 import QtQuick.Controls.Private 1.0
-
+import "." as Desktop
 
 Style {
-    property Component frame: StyleItem {
+    property Component background: StyleItem {
         elementType: "menubar"
-        contentWidth: control.__contentItem.width
-        contentHeight: parent ? parent.contentHeight : 0
         width: implicitWidth + 2 * (pixelMetric("menubarhmargin") + pixelMetric("menubarpanelwidth"))
         height: implicitHeight + 2 * (pixelMetric("menubarvmargin") + pixelMetric("menubarpanelwidth"))
                 + pixelMetric("spacebelowmenubar")
@@ -55,23 +53,22 @@ Style {
         Accessible.role: Accessible.MenuBar
     }
 
-    property Component menuItem: StyleItem {
+    property Component itemDelegate: StyleItem {
         elementType: "menubaritem"
-        x: pixelMetric("menubarhmargin") + pixelMetric("menubarpanelwidth")
-        y: pixelMetric("menubarvmargin") + pixelMetric("menubarpanelwidth")
 
-        text: menuItem.title
+        text: styleData.text
         contentWidth: textWidth(text)
         contentHeight: textHeight(text)
         width: implicitWidth + pixelMetric("menubaritemspacing")
 
-        enabled: menuItem.enabled
-        selected: (parent && parent.selected) || sunken
-        sunken: parent && parent.sunken
+        enabled: styleData.enabled
+        sunken: styleData.open
 
-        hints: { "showUnderlined": showUnderlined }
+        hints: { "showUnderlined": styleData.underlineMnemonic }
 
         Accessible.role: Accessible.MenuItem
         Accessible.name: StyleHelpers.removeMnemonics(text)
     }
+
+    property Component menuStyle: Desktop.MenuStyle { }
 }
diff --git a/src/controls/Styles/Desktop/MenuStyle.qml b/src/controls/Styles/Desktop/MenuStyle.qml
index ad04281de85f469d4ed295d19c0f008671bd9df6..b44dd70d7fe2ff968017a3c55f100f91cdc712d7 100644
--- a/src/controls/Styles/Desktop/MenuStyle.qml
+++ b/src/controls/Styles/Desktop/MenuStyle.qml
@@ -48,18 +48,16 @@ Style {
 
     property string __menuItemType: "menuitem"
 
+    property int submenuOverlap: 0
+    property int __maxPopupHeight: 0
+
     property Component frame: StyleItem {
         elementType: "menu"
 
-        contentWidth: parent ? parent.contentWidth : 0
-        contentHeight: parent ? parent.contentHeight : 0
-        width: implicitWidth
-        height: implicitHeight
-
-        property int subMenuOverlap: -2 * pixelMetric("menupanelwidth")
-        property real maxHeight: Screen.desktopAvailableHeight * 0.99
-        property int margin: pixelMetric("menuvmargin") + pixelMetric("menupanelwidth")
-
+        contentWidth: parent ? Math.round(parent.contentWidth) : 0
+        contentHeight: parent ? Math.round(parent.contentHeight) : 0
+        width: implicitWidth + 2 * (pixelMetric("menuhmargin") + pixelMetric("menupanelwidth"))
+        height: implicitHeight + 2 * (pixelMetric("menuvmargin") + pixelMetric("menupanelwidth"))
         Rectangle {
             visible: anchors.margins > 0
             anchors {
@@ -70,43 +68,57 @@ Style {
         }
 
         Accessible.role: Accessible.PopupMenu
+
+        Binding {
+            target: styleRoot
+            property: "submenuOverlap"
+            value: 2 * pixelMetric("menupanelwidth")
+        }
+
+        Binding {
+            target: styleRoot
+            property: "margin"
+            value: pixelMetric("menuvmargin") + pixelMetric("menupanelwidth")
+        }
+
+        // ### The Screen attached property can only be set on an Item,
+        // ### and will get its values only when put on a Window.
+        readonly property int desktopAvailableHeight: Screen.desktopAvailableHeight
+        Binding {
+            target: styleRoot
+            property: "__maxPopupHeight"
+            value: desktopAvailableHeight * 0.99
+        }
     }
 
-    property Component menuItem: StyleItem {
+    property Component menuItemPanel: StyleItem {
         elementType: __menuItemType
-        x: pixelMetric("menuhmargin") + pixelMetric("menupanelwidth")
-        y: pixelMetric("menuvmargin")
 
-        text: !!parent && parent.text
-        property string textAndShorcut: text + (properties.shortcut ? "\t" + properties.shortcut : "")
+        text: styleData.text
+        property string textAndShorcut: text + (styleData.shortcut ? "\t" + styleData.shortcut : "")
         contentWidth: textWidth(textAndShorcut)
         contentHeight: textHeight(textAndShorcut)
 
-        enabled: !!parent && parent.enabled
-        selected: !!parent && parent.selected
-        on: !!menuItem && !!menuItem["checkable"] && menuItem.checked
+        enabled: styleData.enabled
+        selected: styleData.selected
+        on: styleData.checkable && styleData.checked
 
-        hints: { "showUnderlined": showUnderlined }
+        hints: { "showUnderlined": styleData.underlineMnemonics }
 
         properties: {
-            "checkable": !!menuItem && !!menuItem["checkable"],
-            "exclusive": !!menuItem && !!menuItem["exclusiveGroup"],
-            "shortcut": !!menuItem && menuItem["shortcut"] || "",
-            "isSubmenu": isSubmenu,
-            "scrollerDirection": scrollerDirection,
-            "icon": !!menuItem && menuItem.__icon
+            "checkable": styleData.checkable,
+            "exclusive": styleData.exclusive,
+            "shortcut": styleData.shortcut,
+            "type": styleData.type,
+            "scrollerDirection": styleData.scrollerDirection,
+            "icon": !!__menuItem && __menuItem.__icon
         }
 
         Accessible.role: Accessible.MenuItem
         Accessible.name: StyleHelpers.removeMnemonics(text)
     }
 
-    property Component scrollerStyle: Style {
-        padding { left: 0; right: 0; top: 0; bottom: 0 }
-        property bool scrollToClickedPosition: false
-        property Component frame: Item { visible: false }
-        property Component corner: Item { visible: false }
-        property Component __scrollbar: Item { visible: false }
-        property bool useScrollers: true
-    }
+    property Component scrollIndicator: menuItemPanel
+
+    property Component __scrollerStyle: null
 }
diff --git a/src/controls/Styles/qmldir b/src/controls/Styles/qmldir
index 5cd368ac881ba1074b360f8c00e02f0f884eb1c5..4ffb08ee0eb46eccb3577ef22100b78f3601ad11 100644
--- a/src/controls/Styles/qmldir
+++ b/src/controls/Styles/qmldir
@@ -3,6 +3,8 @@ ButtonStyle 1.0 Base/ButtonStyle.qml
 BusyIndicatorStyle 1.1 Base/BusyIndicatorStyle.qml
 CheckBoxStyle 1.0 Base/CheckBoxStyle.qml
 ComboBoxStyle 1.0 Base/ComboBoxStyle.qml
+MenuStyle 1.2 Base/MenuStyle.qml
+MenuBarStyle 1.2 Base/MenuBarStyle.qml
 ProgressBarStyle 1.0 Base/ProgressBarStyle.qml
 RadioButtonStyle 1.0 Base/RadioButtonStyle.qml
 ScrollViewStyle 1.0 Base/ScrollViewStyle.qml
diff --git a/src/controls/qquickmenuitem_p.h b/src/controls/qquickmenuitem_p.h
index 3ba719f6459e03bce074d1176210238f5fc1a7a7..a2e74d7f5497520562bc453a7db73d88210c3de9 100644
--- a/src/controls/qquickmenuitem_p.h
+++ b/src/controls/qquickmenuitem_p.h
@@ -68,7 +68,8 @@ public:
     enum MenuItemType {
         Separator = 0,
         Item,
-        Menu
+        Menu,
+        ScrollIndicator
     };
 };