diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/controls/Menu.qml | 209 | ||||
-rw-r--r-- | src/controls/Private/ColumnMenuContent.qml | 160 | ||||
-rw-r--r-- | src/controls/Private/MenuContentScroller.qml | 74 | ||||
-rw-r--r-- | src/controls/Private/ScrollBar.qml | 2 | ||||
-rw-r--r-- | src/controls/Private/private.pri | 2 | ||||
-rw-r--r-- | src/controls/Private/qmldir | 2 | ||||
-rw-r--r-- | src/controls/Private/qquickstyleitem.cpp | 23 | ||||
-rw-r--r-- | src/controls/ScrollView.qml | 3 | ||||
-rw-r--r-- | src/controls/Styles/Base/ComboBoxStyle.qml | 16 | ||||
-rw-r--r-- | src/controls/Styles/Base/MenuStyle.qml | 22 | ||||
-rw-r--r-- | src/controls/Styles/Desktop/ComboBoxStyle.qml | 8 | ||||
-rw-r--r-- | src/controls/Styles/Desktop/MenuStyle.qml | 13 | ||||
-rw-r--r-- | src/controls/Styles/Desktop/ScrollViewStyle.qml | 2 | ||||
-rw-r--r-- | src/controls/qquickmenu.cpp | 2 | ||||
-rw-r--r-- | src/controls/qquickmenu_p.h | 3 | ||||
-rw-r--r-- | src/controls/qquickmenupopupwindow.cpp | 10 | ||||
-rw-r--r-- | src/controls/qquickmenupopupwindow_p.h | 1 |
17 files changed, 418 insertions, 134 deletions
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; |