Warning, /plasma/qqc2-breeze-style/style/qtquickcontrols/ComboBox.qml is written in an unsupported language. File is not indexed.
0001 /* SPDX-FileCopyrightText: 2017 The Qt Company Ltd.
0002 * SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org>
0003 * SPDX-FileCopyrightText: 2020 Noah Davis <noahadvs@gmail.com>
0004 * SPDX-License-Identifier: LicenseRef-KDE-Accepted-LGPL
0005 */
0006
0007 import QtQuick
0008 import QtQuick.Window
0009 import QtQuick.Templates as T
0010 import QtQuick.Controls as Controls
0011 import org.kde.kirigami as Kirigami
0012
0013 import org.kde.breeze.impl as Impl
0014
0015 T.ComboBox {
0016 id: control
0017
0018 property real __indicatorMargin: control.indicator && control.indicator.visible && control.indicator.width > 0 ? control.spacing + indicator.width + control.spacing : 0
0019 property real __widestImplicitContentWidth: implicitContentWidth
0020 readonly property bool __isContentItemTextInput: contentItem instanceof TextInput
0021
0022 implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
0023 __widestImplicitContentWidth + leftPadding + rightPadding)
0024 implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
0025 implicitContentHeight + topPadding + bottomPadding,
0026 implicitIndicatorHeight + topPadding + bottomPadding)
0027
0028 // palette: Kirigami.Theme.palette
0029 Kirigami.Theme.colorSet: control.editable ? Kirigami.Theme.View : Kirigami.Theme.Button
0030 Kirigami.Theme.inherit: false
0031
0032 spacing: Kirigami.Units.mediumSpacing
0033
0034 hoverEnabled: Qt.styleHints.useHoverEffects
0035
0036 leftPadding: horizontalPadding + (!control.mirrored ? 0 : __indicatorMargin)
0037 rightPadding: horizontalPadding + (control.mirrored ? 0 : __indicatorMargin)
0038
0039 contentItem: Controls.TextField {
0040 id: textField
0041 palette: control.palette
0042 // TextField padding doesn't automatically mirror
0043 leftPadding: control.mirrored ? 0 : Impl.Units.mediumHorizontalPadding
0044 rightPadding: !control.mirrored ? 0 : Impl.Units.mediumHorizontalPadding
0045
0046 text: control.editable ? control.editText : control.displayText
0047
0048 enabled: control.editable
0049 autoScroll: control.editable
0050 readOnly: control.down || !control.editable
0051 inputMethodHints: control.inputMethodHints
0052 validator: control.validator
0053
0054 // Using control.Kirigami.Theme.textColor instead of directly using
0055 // Kirigami.Theme.textColor because the latter always uses the disabled
0056 // palette when textField.enabled == false
0057 color: control.Kirigami.Theme.textColor
0058
0059 background: null
0060 }
0061
0062 indicator: Kirigami.Icon {
0063 implicitHeight: Kirigami.Units.iconSizes.sizeForLabels
0064 implicitWidth: implicitHeight
0065 x: control.mirrored ? control.leftPadding : control.leftPadding + control.availableWidth + control.spacing
0066 y: control.topPadding + (control.availableHeight - height) / 2
0067 source: "arrow-down"
0068 }
0069
0070 background: Impl.ComboBoxBackground {
0071 control: control
0072
0073 Rectangle {
0074 id: separator
0075 visible: control.editable
0076 width: Impl.Units.smallBorder
0077 anchors {
0078 right: parent.right
0079 top: parent.top
0080 bottom: parent.bottom
0081 rightMargin: (control.mirrored ? control.leftPadding : control.rightPadding) - width
0082 topMargin: control.topPadding + (__isContentItemTextInput ? control.contentItem.topPadding : 0)
0083 bottomMargin: control.bottomPadding + (__isContentItemTextInput ? control.contentItem.bottomPadding : 0)
0084 }
0085
0086 color: control.down
0087 || ((control.hovered || control.visualFocus)
0088 && !(control.contentItem && control.contentItem.hasOwnProperty("hovered") && control.contentItem.hovered))
0089 ? Kirigami.Theme.focusColor : Impl.Theme.separatorColor()
0090
0091 Behavior on color {
0092 enabled: control.down || control.hovered
0093 ColorAnimation {
0094 duration: Kirigami.Units.shortDuration
0095 easing.type: Easing.OutCubic
0096 }
0097 }
0098 }
0099
0100 Kirigami.ShadowedRectangle {
0101 id: pressedBg
0102 property real leftRadius: control.mirrored ? radius : 0
0103 property real rightRadius: !control.mirrored ? radius : 0
0104 visible: false
0105
0106 anchors {
0107 left: separator.left
0108 right: parent.right
0109 top: parent.top
0110 bottom: parent.bottom
0111 }
0112
0113 Kirigami.Theme.colorSet: Kirigami.Theme.Button
0114 Kirigami.Theme.inherit: false
0115 color: Kirigami.Theme.alternateBackgroundColor
0116
0117 radius: parent.radius
0118 corners {
0119 topLeftRadius: leftRadius
0120 topRightRadius: rightRadius
0121 bottomLeftRadius: leftRadius
0122 bottomRightRadius: rightRadius
0123 }
0124
0125 border.color: Kirigami.Theme.focusColor
0126 border.width: Impl.Units.smallBorder
0127
0128 opacity: 0
0129
0130 states: State {
0131 name: "pressed"
0132 when: control.down && control.editable
0133 PropertyChanges {
0134 target: pressedBg
0135 opacity: 1
0136 visible: true
0137 }
0138 }
0139 transitions: Transition {
0140 from: "pressed"
0141 to: ""
0142 SequentialAnimation {
0143 OpacityAnimator {
0144 duration: Kirigami.Units.shortDuration
0145 easing.type: Easing.OutCubic
0146 }
0147 PropertyAction {
0148 target: pressedBg
0149 property: "visible"
0150 value: false
0151 }
0152 }
0153 }
0154 }
0155 }
0156
0157 delegate: Controls.MenuItem {
0158 implicitWidth: leftPadding + implicitContentWidth + rightPadding
0159 width: parent ? parent.width : implicitWidth
0160 text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
0161 highlighted: control.highlightedIndex === index
0162 hoverEnabled: control.hoverEnabled
0163 __reserveSpaceForIndicator: false
0164 __reserveSpaceForIcon: false
0165 __reserveSpaceForArrow: false
0166 }
0167
0168 popup: Controls.Menu {
0169 y: control.height
0170 x: (control.width - width)/2
0171 implicitWidth: contentWidth + leftPadding + rightPadding
0172 width: Math.max(control.width, implicitWidth)
0173 padding: Kirigami.Units.smallSpacing
0174
0175 delegate: null
0176
0177 contentItem: ListView {
0178 id: listView
0179 // this causes us to load at least one delegate
0180 // this is essential in guessing the contentHeight
0181 // which is needed to initially resize the popup
0182 //cacheBuffer: 1
0183 implicitHeight: contentHeight
0184 implicitWidth: contentWidth
0185 model: control.delegateModel // Why isn't this in the ComboBox documentation?
0186 currentIndex: control.highlightedIndex
0187 highlightMoveDuration: Kirigami.Units.shortDuration
0188 highlightMoveVelocity: Kirigami.Units.gridUnit * 20
0189 highlight: Impl.ListViewHighlight {
0190 currentIndex: control.highlightedIndex
0191 count: control.count
0192 alwaysCurveCorners: true
0193 }
0194 interactive: Window.window ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height : false
0195 clip: interactive // Only needed when the ListView can be dragged/flicked
0196 keyNavigationWraps: true
0197 ScrollBar.vertical: Controls.ScrollBar {}
0198 }
0199 }
0200
0201 WheelHandler {
0202 target: control
0203 // FIXME: shouldDec and shouldInc don't work reliably with touchpads when the popup is open.
0204 // Sometimes it's fine, sometimes you need to scroll extra hard to move the highlight.
0205 enabled: control.count > 1 && (popup ? !popup.visible : true)
0206 // Maybe only handle mouse wheels (default) for now. Touchpad scrolling can be too sensitive sometimes.
0207 acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
0208 onWheel: {
0209 // Degrees still change by differences greater than 1 scrollwheel notch (typically 15) if you scroll fast enough.
0210 // That means multiple scroll ticks are registered before the code can run.
0211 // Doesn't seem to impact how the control feels much at least.
0212 let shouldDec = rotation >= 15
0213 let shouldInc = rotation <= -15
0214 let shouldReset = (rotation > 0 && control.currentIndex == 0) || (rotation < 0 && control.currentIndex == control.count-1)
0215 if (shouldDec) {
0216 control.decrementCurrentIndex(); // This moves the highlight up
0217 rotation = 0
0218 } else if (shouldInc) {
0219 control.incrementCurrentIndex(); // This moves the highlight down
0220 rotation = 0
0221 } else if (shouldReset) {
0222 rotation = 0
0223 }
0224 }
0225 }
0226
0227 TextMetrics {
0228 id: textMetrics
0229 }
0230
0231 // Mimicks WidestTextWhenCompleted from Qt 6.
0232 // Maybe use this if app devs are interested.
0233 // Don't use it for now because lots of GUIs aren't designed for it.
0234 /*
0235 Component.onCompleted: {
0236 // TODO: Remove in Qt 6
0237 if (// Qt 6 does this in QQuickComboBoxPrivate::calculateWidestTextWidth()
0238 __isContentItemTextInput
0239 // Kind of an arbitrary limit, but prevents making lots of calculations with larger models
0240 && control.count <= 20
0241 ) {
0242 let widest = Math.ceil(contentItem.contentWidth)
0243 for (let i = 0; i < count; ++i) {
0244 textMetrics.text = control.textAt(i)
0245 widest = Math.max(widest, textMetrics.width)
0246 }
0247 __widestImplicitContentWidth = Math.ceil(widest) + contentItem.leftPadding + contentItem.rightPadding
0248 }
0249 }
0250 */
0251 }