summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/quick/controls/gallery/content/Controls.qml5
-rw-r--r--src/controls/Menu.qml209
-rw-r--r--src/controls/Private/ColumnMenuContent.qml160
-rw-r--r--src/controls/Private/MenuContentScroller.qml74
-rw-r--r--src/controls/Private/ScrollBar.qml2
-rw-r--r--src/controls/Private/private.pri2
-rw-r--r--src/controls/Private/qmldir2
-rw-r--r--src/controls/Private/qquickstyleitem.cpp23
-rw-r--r--src/controls/ScrollView.qml3
-rw-r--r--src/controls/Styles/Base/ComboBoxStyle.qml16
-rw-r--r--src/controls/Styles/Base/MenuStyle.qml22
-rw-r--r--src/controls/Styles/Desktop/ComboBoxStyle.qml8
-rw-r--r--src/controls/Styles/Desktop/MenuStyle.qml13
-rw-r--r--src/controls/Styles/Desktop/ScrollViewStyle.qml2
-rw-r--r--src/controls/qquickmenu.cpp2
-rw-r--r--src/controls/qquickmenu_p.h3
-rw-r--r--src/controls/qquickmenupopupwindow.cpp10
-rw-r--r--src/controls/qquickmenupopupwindow_p.h1
18 files changed, 423 insertions, 134 deletions
diff --git a/examples/quick/controls/gallery/content/Controls.qml b/examples/quick/controls/gallery/content/Controls.qml
index 98945675..7f6ea9aa 100644
--- a/examples/quick/controls/gallery/content/Controls.qml
+++ b/examples/quick/controls/gallery/content/Controls.qml
@@ -87,6 +87,11 @@ Item {
currentIndex: 2
}
ComboBox {
+ model: Qt.fontFamilies()
+ width: parent.width
+ currentIndex: 47
+ }
+ ComboBox {
id: editableCombo
editable: true
model: choices
diff --git a/src/controls/Menu.qml b/src/controls/Menu.qml
index 4c3bc1be..949b6a91 100644
--- a/src/controls/Menu.qml
+++ b/src/controls/Menu.qml
@@ -152,14 +152,14 @@ MenuPrivate {
property Component __menuComponent: Loader {
id: menuFrameLoader
- property Style __style: styleLoader.item
- property Component menuItemStyle: __style ? __style.menuItem : null
+ readonly property Style __style: styleLoader.item
+ readonly property Component menuItemStyle: __style ? __style.menuItem : null
- property var control: root
- property alias contentWidth: column.width
- property alias contentHeight: column.height
+ readonly property var control: root
+ property alias contentWidth: content.width
+ property alias contentHeight: content.height
- property int subMenuXPos: width + (item && item["subMenuOverlap"] || 0)
+ readonly property int subMenuXPos: width + (item && item["subMenuOverlap"] || 0)
visible: status === Loader.Ready
sourceComponent: __style ? __style.frame : undefined
@@ -204,17 +204,19 @@ MenuPrivate {
for (var i = root.__currentIndex + 1;
i < root.items.length && !canBeHovered(i); i++)
;
+ event.accepted = true
}
Keys.onUpPressed: {
for (var i = root.__currentIndex - 1;
i >= 0 && !canBeHovered(i); i--)
;
+ event.accepted = true
}
function canBeHovered(index) {
- var item = itemsRepeater.itemAt(index)
- if (!item["isSeparator"] && item.enabled) {
+ var item = content.menuItemAt(index)
+ if (item && !item["isSeparator"] && item.enabled) {
root.__currentIndex = index
return true
}
@@ -227,20 +229,24 @@ MenuPrivate {
}
Keys.onRightPressed: {
- var item = itemsRepeater.itemAt(root.__currentIndex)
+ var item = content.menuItemAt(root.__currentIndex)
if ((event.accepted = (item && item.isSubmenu))) {
item.showSubMenu(true)
item.menuItem.__currentIndex = 0
}
}
- Keys.onSpacePressed: menuFrameLoader.triggerAndDismiss()
- Keys.onReturnPressed: menuFrameLoader.triggerAndDismiss()
- Keys.onEnterPressed: menuFrameLoader.triggerAndDismiss()
+ Keys.onSpacePressed: triggerCurrent()
+ Keys.onReturnPressed: triggerCurrent()
+ Keys.onEnterPressed: triggerCurrent()
+
+ function triggerCurrent() {
+ var item = content.menuItemAt(root.__currentIndex)
+ if (item)
+ content.triggered(item)
+ }
function triggerAndDismiss(item) {
- if (!item)
- item = itemsRepeater.itemAt(root.__currentIndex)
if (item && !item.isSeparator) {
root.__dismissMenu()
if (!item.isSubmenu)
@@ -250,126 +256,85 @@ MenuPrivate {
Binding {
// Make sure the styled frame is in the background
- target: menuFrameLoader.item
+ target: item
property: "z"
- value: menuMouseArea.z - 1
+ value: content.z - 1
}
- MouseArea {
- id: menuMouseArea
- anchors.fill: parent
- hoverEnabled: true
- acceptedButtons: Qt.AllButtons
-
- onPositionChanged: updateCurrentItem(mouse)
- onReleased: menuFrameLoader.triggerAndDismiss()
- onExited: {
- if (currentItem && !currentItem.menuItem.__popupVisible) {
- currentItem = null
- root.__currentIndex = -1
- }
- }
-
- property Item currentItem: null
-
- function updateCurrentItem(mouse) {
- var pos = mapToItem(column, mouse.x, mouse.y)
- if (!currentItem || !currentItem.contains(Qt.point(pos.x - currentItem.x, pos.y - currentItem.y))) {
- if (currentItem && !pressed && currentItem.isSubmenu)
- currentItem.closeSubMenu()
- var itemUnderMouse = column.childAt(pos.x, pos.y)
- if (itemUnderMouse) {
- currentItem = itemUnderMouse
- } else if (currentItem) {
- var itemItem = currentItem.item
- if (!itemItem.contains(itemItem.mapFromItem(column, pos)))
- currentItem = null
- }
+ ColumnMenuContent {
+ id: content
+ menuItemDelegate: menuItemComponent
+ scrollerStyle: __style ? __style.scrollerStyle : undefined
+ itemsModel: root.items
+ margin: menuFrameLoader.item ? menuFrameLoader.item.margin : 0
+ minWidth: root.__minimumWidth
+ maxHeight: menuFrameLoader.item ? menuFrameLoader.item.maxHeight : 0
+ onTriggered: triggerAndDismiss(item)
+ }
- if (currentItem) {
- root.__currentIndex = currentItem.menuItemIndex
- if (currentItem.isSubmenu && !currentItem.menuItem.__popupVisible)
- currentItem.showSubMenu(false)
+ Component {
+ id: menuItemComponent
+ 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) && root.__currentIndex === index
+ property string text: isSubmenu ? menuItem.title : !(isSeparator || !!scrollerDirection) ? menuItem.text : ""
+ property bool showUnderlined: __contentItem.altPressed
+ readonly property var scrollerDirection: menuItem["scrollerDirection"]
+
+ property int menuItemIndex: index
+
+ sourceComponent: menuFrameLoader.menuItemStyle
+ enabled: visible && !isSeparator && !!menuItem && menuItem.enabled
+ visible: menuItem.visible
+ active: visible
+
+ function showSubMenu(immediately) {
+ if (immediately) {
+ if (root.__currentIndex === menuItemIndex)
+ menuItem.__popup(menuFrameLoader.subMenuXPos, 0, -1)
} else {
- root.__currentIndex = -1
+ openMenuTimer.start()
}
}
- }
- // Each menu item has its own mouse area, and for events to be
- // propagated to the menu mouse area, they need to be embedded.
- Column {
- id: column
-
- Repeater {
- id: itemsRepeater
- model: root.items
-
- 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 && root.__currentIndex === index
- property string text: isSubmenu ? menuItem.title : !isSeparator ? menuItem.text : ""
- property bool showUnderlined: __contentItem.altPressed
-
- property int menuItemIndex: index
-
- sourceComponent: menuFrameLoader.menuItemStyle
- enabled: visible && !isSeparator && !!menuItem && menuItem.enabled
- visible: menuItem.visible
- active: visible
-
- function showSubMenu(immediately) {
- if (immediately) {
- if (root.__currentIndex === menuItemIndex) {
- if (Qt.application.layoutDirection === Qt.RightToLeft)
- menuItem.__popup(0, 0, -1)
- else
- menuItem.__popup(menuFrameLoader.subMenuXPos, 0, -1)
- }
- } else {
- openMenuTimer.start()
- }
- }
-
- Timer {
- id: openMenuTimer
- interval: 50
- onTriggered: menuItemLoader.showSubMenu(true)
- }
-
- function closeSubMenu() { closeMenuTimer.start() }
-
- Timer {
- id: closeMenuTimer
- interval: 1
- onTriggered: {
- if (root.__currentIndex !== menuItemIndex)
- menuItem.__closeMenu()
- }
- }
-
- Component.onCompleted: {
- menuItem.__visualItem = menuItemLoader
-
- var title = text
- var ampersandPos = title.indexOf("&")
- if (ampersandPos !== -1)
- menuFrameLoader.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = menuItemLoader
- }
- }
+ Timer {
+ id: openMenuTimer
+ interval: 50
+ onTriggered: menuItemLoader.showSubMenu(true)
}
- onWidthChanged: {
- for (var i = 0; i < children.length; i++) {
- var item = children[i]["item"]
- if (item)
- item.implicitWidth = Math.max(root.__minimumWidth, implicitWidth)
+ function closeSubMenu() { closeMenuTimer.start() }
+
+ Timer {
+ id: closeMenuTimer
+ interval: 1
+ onTriggered: {
+ if (root.__currentIndex !== menuItemIndex)
+ menuItem.__closeMenu()
}
}
+
+ onLoaded: {
+ menuItem.__visualItem = menuItemLoader
+
+ if (content.width < item.implicitWidth)
+ content.width = item.implicitWidth
+
+ var title = text
+ var ampersandPos = title.indexOf("&")
+ if (ampersandPos !== -1)
+ menuFrameLoader.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = menuItemLoader
+ }
+
+ Binding {
+ target: menuItemLoader.item
+ property: "width"
+ value: Math.max(root.__minimumWidth, content.width)
+ }
}
}
}
diff --git a/src/controls/Private/ColumnMenuContent.qml b/src/controls/Private/ColumnMenuContent.qml
new file mode 100644
index 00000000..505756d1
--- /dev/null
+++ b/src/controls/Private/ColumnMenuContent.qml
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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
+import QtQuick.Controls 1.1
+
+Item {
+ id: content
+
+ property Component menuItemDelegate
+ property Component scrollerStyle
+ property var itemsModel
+ property int minWidth: 100
+ property real maxHeight: 800
+ property int margin: 1
+
+ signal triggered(var item)
+
+ function menuItemAt(index) {
+ list.currentIndex = index
+ return list.currentItem
+ }
+
+ width: Math.max(list.contentWidth, minWidth)
+ height: Math.min(list.contentHeight, fittedMaxHeight) + 2 * margin
+
+ readonly property int currentIndex: root.__currentIndex
+ property Item currentItem: null
+ readonly property int itemHeight: list.count > 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 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()
+ currentItem = list.itemAt(pos.x, pos.y)
+ if (currentItem) {
+ root.__currentIndex = currentItem.menuItemIndex
+ if (currentItem.isSubmenu && !currentItem.menuItem.__popupVisible)
+ currentItem.showSubMenu(false)
+ } else {
+ root.__currentIndex = -1
+ }
+ }
+ }
+
+ MouseArea {
+ id: hoverArea
+ anchors.left: scrollView.left
+ width: scrollView.width - scrollView.__verticalScrollBar.width
+ height: parent.height
+
+ hoverEnabled: true
+ acceptedButtons: Qt.AllButtons
+
+ onPositionChanged: updateCurrentItem(mouse)
+ onReleased: content.triggered(currentItem)
+ onExited: {
+ if (currentItem && !currentItem.menuItem.__popupVisible) {
+ currentItem = null
+ root.__currentIndex = -1
+ }
+ }
+
+ MenuContentScroller {
+ id: upScroller
+ direction: "up"
+ visible: shouldUseScrollers && !list.atYBeginning
+ x: margin
+ function scrollABit() { list.contentY -= itemHeight }
+ }
+
+ MenuContentScroller {
+ id: downScroller
+ direction: "down"
+ visible: shouldUseScrollers && !list.atYEnd
+ x: margin
+ function scrollABit() { list.contentY += itemHeight }
+ }
+ }
+
+ ScrollView {
+ id: scrollView
+ anchors {
+ fill: parent
+ topMargin: content.margin + upScrollerHeight
+ bottomMargin: downScrollerHeight - content.margin - 1
+ rightMargin: -1
+ }
+
+ style: scrollerStyle
+ __wheelAreaScrollSpeed: itemHeight
+
+ ListView {
+ id: list
+ model: itemsModel
+ delegate: menuItemDelegate
+ snapMode: ListView.SnapToItem
+ boundsBehavior: Flickable.StopAtBounds
+ highlightFollowsCurrentItem: true
+ highlightMoveDuration: 0
+ }
+ }
+
+ Timer {
+ interval: 1
+ running: true
+ repeat: false
+ onTriggered: list.positionViewAtIndex(currentIndex, scrollView.__style.useScrollers
+ ? ListView.Center : ListView.Beginning)
+ }
+
+ Binding {
+ target: scrollView.__verticalScrollBar
+ property: "singleStep"
+ value: itemHeight
+ }
+}
diff --git a/src/controls/Private/MenuContentScroller.qml b/src/controls/Private/MenuContentScroller.qml
new file mode 100644
index 00000000..30a8825a
--- /dev/null
+++ b/src/controls/Private/MenuContentScroller.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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
+
+MouseArea {
+ property string direction
+
+ anchors {
+ top: direction === "up" ? parent.top : undefined
+ bottom: direction === "down" ? parent.bottom : undefined
+ }
+
+ hoverEnabled: visible
+ height: scrollerLoader.item.height
+ width: parent.width
+
+ Loader {
+ id: scrollerLoader
+
+ sourceComponent: menuItemDelegate
+ property int index: -1
+ property var modelData: {
+ "visible": true,
+ "scrollerDirection": direction,
+ "enabled": true
+ }
+ }
+
+ Timer {
+ interval: 100
+ repeat: true
+ triggeredOnStart: true
+ running: parent.containsMouse
+ onTriggered: scrollABit()
+ }
+}
diff --git a/src/controls/Private/ScrollBar.qml b/src/controls/Private/ScrollBar.qml
index 9ee330d3..49dd20a4 100644
--- a/src/controls/Private/ScrollBar.qml
+++ b/src/controls/Private/ScrollBar.qml
@@ -56,6 +56,7 @@ Item {
property alias minimumValue: slider.minimumValue
property alias maximumValue: slider.maximumValue
property alias value: slider.value
+ property int singleStep: 20
activeFocusOnTab: false
@@ -89,7 +90,6 @@ Item {
id: internal
property bool horizontal: orientation === Qt.Horizontal
property int pageStep: internal.horizontal ? width : height
- property int singleStep: 20
property bool scrollToClickposition: internal.scrollToClickPosition
anchors.fill: parent
cursorShape: __panel.visible ? Qt.ArrowCursor : Qt.IBeamCursor // forces a cursor change
diff --git a/src/controls/Private/private.pri b/src/controls/Private/private.pri
index bd001c0a..58cc7f11 100644
--- a/src/controls/Private/private.pri
+++ b/src/controls/Private/private.pri
@@ -37,6 +37,8 @@ PRIVATE_QML_FILES += \
$$PWD/ScrollViewHelper.qml \
$$PWD/ScrollBar.qml \
$$PWD/FocusFrame.qml \
+ $$PWD/ColumnMenuContent.qml \
+ $$PWD/MenuContentScroller.qml \
$$PWD/qmldir
QML_FILES += $$PRIVATE_QML_FILES
diff --git a/src/controls/Private/qmldir b/src/controls/Private/qmldir
index 1ee66461..a49401dc 100644
--- a/src/controls/Private/qmldir
+++ b/src/controls/Private/qmldir
@@ -16,3 +16,5 @@ SpinBoxStyle 1.0 ../Styles/Base/SpinBoxStyle.qml
ToolBarStyle 1.0 ../Styles/Base/ToolBarStyle.qml
StatusBarStyle 1.0 ../Styles/Base/StatusBarStyle.qml
ToolButtonStyle 1.0 ../Styles/Base/ToolButtonStyle.qml
+MenuContentScroller 1.0 MenuContentScroller.qml
+ColumnMenuContent 1.0 ColumnMenuContent.qml
diff --git a/src/controls/Private/qquickstyleitem.cpp b/src/controls/Private/qquickstyleitem.cpp
index 4101f90f..82e503dd 100644
--- a/src/controls/Private/qquickstyleitem.cpp
+++ b/src/controls/Private/qquickstyleitem.cpp
@@ -418,7 +418,13 @@ void QQuickStyleItem::initStyleOption()
QStyleOptionMenuItem *opt = qstyleoption_cast<QStyleOptionMenuItem*>(m_styleoption);
// For GTK style. See below, in setElementType()
setProperty("_q_isComboBoxPopupItem", m_itemType == ComboBoxItem);
- if (text().isEmpty()) {
+
+ QString scrollerDirection = m_properties["scrollerDirection"].toString();
+ if (!scrollerDirection.isEmpty()) {
+ opt->menuItemType = QStyleOptionMenuItem::Scroller;
+ opt->state |= scrollerDirection == "up" ?
+ QStyle::State_UpArrow : QStyle::State_DownArrow;
+ } else if (text().isEmpty()) {
opt->menuItemType = QStyleOptionMenuItem::Separator;
} else {
opt->text = text();
@@ -861,7 +867,12 @@ QSize QQuickStyleItem::sizeFromContents(int width, int height)
break;
case MenuItem:
case ComboBoxItem:
- size = qApp->style()->sizeFromContents(QStyle::CT_MenuItem, m_styleoption, QSize(width,height));
+ if (static_cast<QStyleOptionMenuItem *>(m_styleoption)->menuItemType == QStyleOptionMenuItem::Scroller) {
+ size.setHeight(qMax(QApplication::globalStrut().height(),
+ qApp->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, 0)));
+ } else {
+ size = qApp->style()->sizeFromContents(QStyle::CT_MenuItem, m_styleoption, QSize(width,height));
+ }
break;
default:
break;
@@ -1286,8 +1297,12 @@ void QQuickStyleItem::paint(QPainter *painter)
qApp->style()->drawControl(QStyle::CE_MenuBarItem, m_styleoption, painter);
break;
case MenuItem:
- case ComboBoxItem: // fall through
- qApp->style()->drawControl(QStyle::CE_MenuItem, m_styleoption, painter);
+ case ComboBoxItem: { // fall through
+ QStyle::ControlElement menuElement =
+ static_cast<QStyleOptionMenuItem *>(m_styleoption)->menuItemType == QStyleOptionMenuItem::Scroller ?
+ QStyle::CE_MenuScroller : QStyle::CE_MenuItem;
+ qApp->style()->drawControl(menuElement, m_styleoption, painter);
+ }
break;
case CheckBox:
qApp->style()->drawControl(QStyle::CE_CheckBox, m_styleoption, painter);
diff --git a/src/controls/ScrollView.qml b/src/controls/ScrollView.qml
index 5717d70f..06343b74 100644
--- a/src/controls/ScrollView.qml
+++ b/src/controls/ScrollView.qml
@@ -137,6 +137,8 @@ FocusScope {
/*! \internal */
property Item __scroller: scroller
/*! \internal */
+ property alias __wheelAreaScrollSpeed: wheelArea.scrollSpeed
+ /*! \internal */
property int __scrollBarTopMargin: 0
/*! \internal */
property int __viewTopMargin: 0
@@ -287,7 +289,6 @@ FocusScope {
verticalScrollBar.width + scrollBarSpacing : 0
property int horizontalScrollbarOffset: horizontalScrollBar.visible && !horizontalScrollBar.isTransient ?
horizontalScrollBar.height + scrollBarSpacing : 0
-
Loader {
id: frameLoader
sourceComponent: __style ? __style.frame : null
diff --git a/src/controls/Styles/Base/ComboBoxStyle.qml b/src/controls/Styles/Base/ComboBoxStyle.qml
index 2011b219..b49d8f97 100644
--- a/src/controls/Styles/Base/ComboBoxStyle.qml
+++ b/src/controls/Styles/Base/ComboBoxStyle.qml
@@ -38,6 +38,7 @@
**
****************************************************************************/
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
@@ -188,7 +189,11 @@ Style {
/*! \internal */
property Component __dropDownStyle: MenuStyle {
+ maxPopupHeight: 600
__menuItemType: "comboboxitem"
+ scrollerStyle: ScrollViewStyle {
+ property bool useScrollers: false
+ }
}
/*! \internal */
@@ -198,6 +203,8 @@ Style {
width: (parent ? parent.contentWidth : 0)
height: (parent ? parent.contentHeight : 0) + 2
border.color: "#777"
+ property real maxHeight: Math.min(500, Screen.desktopAvailableHeight)
+ property int margin: 1
}
property Component menuItem: Rectangle {
@@ -211,5 +218,14 @@ Style {
text: textRef
}
}
+
+ 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
+ }
}
}
diff --git a/src/controls/Styles/Base/MenuStyle.qml b/src/controls/Styles/Base/MenuStyle.qml
index 9be32459..c05c6a6d 100644
--- a/src/controls/Styles/Base/MenuStyle.qml
+++ b/src/controls/Styles/Base/MenuStyle.qml
@@ -39,6 +39,7 @@
****************************************************************************/
import QtQuick 2.1
+import QtQuick.Window 2.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Private 1.0
@@ -53,6 +54,7 @@ Style {
id: styleRoot
property string __menuItemType: "menuitem"
+ property real maxPopupHeight: 600 // ### FIXME Screen.desktopAvailableHeight * 0.99
property Component frame: Rectangle {
width: (parent ? parent.contentWidth : 0) + 2
@@ -62,6 +64,8 @@ Style {
border { width: 1; color: "darkgray" }
property int subMenuOverlap: -1
+ property real maxHeight: maxPopupHeight
+ property int margin: 1
}
property Component menuItem: Rectangle {
@@ -69,7 +73,7 @@ Style {
y: 1
implicitWidth: Math.max((parent ? parent.width : 0),
18 + text.paintedWidth + (rightDecoration.visible ? rightDecoration.width + 40 : 12))
- implicitHeight: isSeparator ? text.font.pixelSize / 2 : text.paintedHeight + 4
+ 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
@@ -188,6 +192,13 @@ Style {
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"
+ }
+
Rectangle {
visible: isSeparator
width: parent.width - 2
@@ -197,4 +208,13 @@ Style {
color: "darkgray"
}
}
+
+ 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
+ }
}
diff --git a/src/controls/Styles/Desktop/ComboBoxStyle.qml b/src/controls/Styles/Desktop/ComboBoxStyle.qml
index e6495ceb..2c1cd7c2 100644
--- a/src/controls/Styles/Desktop/ComboBoxStyle.qml
+++ b/src/controls/Styles/Desktop/ComboBoxStyle.qml
@@ -38,9 +38,11 @@
**
****************************************************************************/
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
Style {
readonly property ComboBox control: __control
@@ -86,6 +88,8 @@ Style {
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 {
@@ -107,5 +111,9 @@ Style {
selected: parent ? parent.selected : false
}
}
+
+ property Component scrollerStyle: Desktop.ScrollViewStyle {
+ property bool useScrollers: false
+ }
}
}
diff --git a/src/controls/Styles/Desktop/MenuStyle.qml b/src/controls/Styles/Desktop/MenuStyle.qml
index b1f5e9cf..a3f3e8fa 100644
--- a/src/controls/Styles/Desktop/MenuStyle.qml
+++ b/src/controls/Styles/Desktop/MenuStyle.qml
@@ -39,6 +39,7 @@
****************************************************************************/
import QtQuick 2.1
+import QtQuick.Window 2.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Private 1.0
@@ -56,6 +57,8 @@ Style {
height: implicitHeight + 2 * (pixelMetric("menuvmargin") + pixelMetric("menupanelwidth"))
property int subMenuOverlap: pixelMetric("submenuoverlap")
+ property real maxHeight: Screen.desktopAvailableHeight * 0.99
+ property int margin: pixelMetric("menuvmargin") + pixelMetric("menupanelwidth")
Rectangle {
visible: anchors.margins > 0
@@ -90,10 +93,20 @@ Style {
"exclusive": !!menuItem && !!menuItem["exclusiveGroup"],
"shortcut": !!menuItem && menuItem["shortcut"] || "",
"isSubmenu": isSubmenu,
+ "scrollerDirection": 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
+ }
}
diff --git a/src/controls/Styles/Desktop/ScrollViewStyle.qml b/src/controls/Styles/Desktop/ScrollViewStyle.qml
index 9342d524..cd8a2a04 100644
--- a/src/controls/Styles/Desktop/ScrollViewStyle.qml
+++ b/src/controls/Styles/Desktop/ScrollViewStyle.qml
@@ -58,7 +58,7 @@ Style {
id: styleitem
elementType: "frame"
sunken: true
- visible: frameVisible
+ visible: control.frameVisible
}
property Component corner: StyleItem { elementType: "scrollareacorner" }
diff --git a/src/controls/qquickmenu.cpp b/src/controls/qquickmenu.cpp
index 62e7a7bd..600dbe79 100644
--- a/src/controls/qquickmenu.cpp
+++ b/src/controls/qquickmenu.cpp
@@ -298,6 +298,8 @@ void QQuickMenu::setMinimumWidth(int w)
m_minimumWidth = w;
if (m_platformMenu)
m_platformMenu->setMinimumWidth(w);
+
+ emit minimumWidthChanged();
}
void QQuickMenu::setFont(const QFont &arg)
diff --git a/src/controls/qquickmenu_p.h b/src/controls/qquickmenu_p.h
index f15e6caa..c1fab0b5 100644
--- a/src/controls/qquickmenu_p.h
+++ b/src/controls/qquickmenu_p.h
@@ -69,7 +69,7 @@ class QQuickMenu : public QQuickMenuText
Q_PROPERTY(int __selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY __selectedIndexChanged)
Q_PROPERTY(bool __popupVisible READ popupVisible NOTIFY popupVisibleChanged)
Q_PROPERTY(QQuickItem *__contentItem READ menuContentItem WRITE setMenuContentItem NOTIFY menuContentItemChanged)
- Q_PROPERTY(int __minimumWidth READ minimumWidth WRITE setMinimumWidth)
+ Q_PROPERTY(int __minimumWidth READ minimumWidth WRITE setMinimumWidth NOTIFY minimumWidthChanged)
Q_PROPERTY(QFont __font READ font WRITE setFont)
Q_PROPERTY(qreal __xOffset READ xOffset WRITE setXOffset)
Q_PROPERTY(qreal __yOffset READ yOffset WRITE setYOffset)
@@ -100,6 +100,7 @@ Q_SIGNALS:
void __menuClosed();
void popupVisibleChanged();
void menuContentItemChanged();
+ void minimumWidthChanged();
public:
QQuickMenu(QObject *parent = 0);
diff --git a/src/controls/qquickmenupopupwindow.cpp b/src/controls/qquickmenupopupwindow.cpp
index d21bd0d5..e06b5f03 100644
--- a/src/controls/qquickmenupopupwindow.cpp
+++ b/src/controls/qquickmenupopupwindow.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
QQuickMenuPopupWindow::QQuickMenuPopupWindow(QWindow *parent) :
QQuickWindow(parent), m_mouseMoved(false), m_needsActivatedEvent(true),
- m_itemAt(0), m_parentItem(0), m_menuContentItem(0)
+ m_dismissed(false), m_itemAt(0), m_parentItem(0), m_menuContentItem(0)
{
setFlags(Qt::Popup);
setModality(Qt::WindowModal);
@@ -176,6 +176,7 @@ void QQuickMenuPopupWindow::setGeometry(int posx, int posy, int w, int h)
void QQuickMenuPopupWindow::dismissMenu()
{
+ m_dismissed = true;
emit menuDismissed();
close();
}
@@ -210,7 +211,9 @@ void QQuickMenuPopupWindow::mouseMoveEvent(QMouseEvent *e)
void QQuickMenuPopupWindow::mousePressEvent(QMouseEvent *e)
{
QRect rect = QRect(QPoint(), size());
- if (!rect.contains(e->pos()))
+ if (rect.contains(e->pos()))
+ QQuickWindow::mousePressEvent(e);
+ else
forwardEventToTransientParent(e);
}
@@ -221,7 +224,8 @@ void QQuickMenuPopupWindow::mouseReleaseEvent(QMouseEvent *e)
if (m_mouseMoved) {
QMouseEvent pe = QMouseEvent(QEvent::MouseButtonPress, e->pos(), e->button(), e->buttons(), e->modifiers());
QQuickWindow::mousePressEvent(&pe);
- QQuickWindow::mouseReleaseEvent(e);
+ if (!m_dismissed)
+ QQuickWindow::mouseReleaseEvent(e);
}
m_mouseMoved = true; // Initial mouse release counts as move.
} else {
diff --git a/src/controls/qquickmenupopupwindow_p.h b/src/controls/qquickmenupopupwindow_p.h
index 4407fdec..4c629219 100644
--- a/src/controls/qquickmenupopupwindow_p.h
+++ b/src/controls/qquickmenupopupwindow_p.h
@@ -89,6 +89,7 @@ private:
bool m_mouseMoved;
bool m_needsActivatedEvent;
+ bool m_dismissed;
QQuickItem *m_itemAt;
QPointF m_oldItemPos;
QQuickItem *m_parentItem;