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 }