Warning, /plasma/latte-dock/declarativeimports/components/ComboBox.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 import QtQuick 2.7
0008 import QtQuick.Window 2.2
0009 import QtQuick.Templates 2.2 as T
0010 import QtQuick.Controls 2.2 as Controls
0011 import QtQuick.Layouts 1.3
0012 import QtGraphicalEffects 1.0
0013 import org.kde.plasma.core 2.0 as PlasmaCore
0014 import org.kde.plasma.components 2.0 as PlasmaComponents
0015 import org.kde.kirigami 2.2 as Kirigami
0016 import "private" as Private
0017 
0018 T.ComboBox {
0019     id: control
0020 
0021     implicitWidth: Math.max(background ? background.implicitWidth : 0,
0022                             contentItem.implicitWidth + leftPadding + rightPadding) + indicator.implicitWidth + rightPadding
0023     implicitHeight: units.gridUnit * 1.6
0024     baselineOffset: contentItem.y + contentItem.baselineOffset
0025 
0026     hoverEnabled: true
0027     topPadding: surfaceNormal.margins.top
0028     leftPadding: surfaceNormal.margins.left
0029     rightPadding: surfaceNormal.margins.right + units.gridUnit * 2
0030     bottomPadding: surfaceNormal.margins.bottom
0031 
0032     wheelEnabled: false
0033 
0034     property bool hideDisplayText: false
0035     property bool hideSelectedItemIcon: false
0036 
0037     property bool blankSpaceForEmptyIcons: false
0038     property bool forcePressed: false
0039     property bool popUpAlignRight: true
0040     property bool buttonIsTransparent: false
0041     property int minimumPopUpWidth: 150
0042     property int popUpRelativeX: 0
0043     property int popUpTextHorizontalAlignment: Text.AlignLeft
0044 
0045     property string enabledRole
0046     property string iconRole
0047     property string iconToolTipRole
0048     property string iconOnlyWhenHoveredRole
0049     property string isSeparatorRole
0050     property string toolTipRole
0051 
0052     signal iconClicked(int index);
0053 
0054     delegate: ItemDelegate {
0055         width: control.popup.width
0056         enabled: !isSeparator && (control.enabledRole.length>0 ? (isArray ? modelData[control.enabledRole] : model[control.enabledRole]) : true)
0057         text: control.textRole.length>0 ? (isArray ? modelData[control.textRole] : model[control.textRole]) : modelData
0058         icon: control.iconRole.length>0 ? (isArray ? modelData[control.iconRole] : model[control.iconRole]) : ''
0059         iconToolTip: control.iconToolTipRole.length>0 ? (isArray ? modelData[control.iconToolTipRole] : model[control.iconToolTipRole]) : ''
0060         iconOnlyWhenHovered: control.iconOnlyWhenHoveredRole.length>0 ? (isArray ? modelData[control.iconOnlyWhenHoveredRole] : model[control.iconOnlyWhenHoveredRole]) : ''
0061         isSeparator: control.isSeparatorRole.length>0 ? (isArray ? modelData[control.isSeparatorRole] : model[control.isSeparatorRole]) : false
0062         toolTip: control.toolTipRole.length>0 ? (isArray ? modelData[control.toolTipRole] : model[control.toolTipRole]) : ''
0063 
0064         highlighted: mouseArea.pressed ? listView.currentIndex == index : control.currentIndex == index
0065         blankSpaceForEmptyIcons: control.blankSpaceForEmptyIcons
0066         textHorizontalAlignment: popUpTextHorizontalAlignment
0067 
0068         readonly property bool isArray: Array.isArray(control.model)
0069         property bool separatorVisible: false
0070 
0071         PlasmaComponents.Button {
0072             id: tooltipBtn
0073             anchors.fill: parent
0074             opacity: 0
0075             tooltip: parent.toolTip
0076             visible: tooltip !== ''
0077 
0078             onPressedChanged: {
0079                 if (!pressed) {
0080                     control.currentIndex = index;
0081                     control.down = false;
0082                     control.pressed = false;
0083                     control.popup.visible = false;
0084                 }
0085             }
0086         }
0087     }
0088 
0089     indicator: PlasmaCore.SvgItem {
0090         implicitWidth: units.iconSizes.small
0091         implicitHeight: implicitWidth
0092         anchors {
0093             right: parent.right
0094             rightMargin: control.buttonIsTransparent ? 0 : surfaceNormal.margins.right
0095             verticalCenter: parent.verticalCenter
0096         }
0097         svg: PlasmaCore.Svg {
0098             imagePath: "widgets/arrows"
0099             colorGroup: PlasmaCore.Theme.ButtonColorGroup
0100         }
0101         elementId: "down-arrow"
0102     }
0103 
0104     //     contentItem: Label {
0105     //         text: control.displayText
0106     //         font: control.font
0107     //         color: theme.buttonTextColor
0108     //         horizontalAlignment: Text.AlignLeft
0109     //         verticalAlignment: Text.AlignVCenter
0110     //         elide: Text.ElideRight
0111     //     }
0112     contentItem: MouseArea {
0113         id: mouseArea
0114         anchors.fill: parent
0115         acceptedButtons: Qt.LeftButton
0116         preventStealing: true
0117         property int indexUnderMouse: -1
0118         onWheel: {
0119             if (!control.wheelEnabled) {
0120                 return;
0121             }
0122 
0123             if (wheel.pixelDelta.y < 0 || wheel.angleDelta.y < 0) {
0124                 control.currentIndex = Math.min(control.currentIndex + 1, delegateModel.count -1);
0125             } else {
0126                 control.currentIndex = Math.max(control.currentIndex - 1, 0);
0127             }
0128             control.activated(control.currentIndex);
0129         }
0130         onPressed: onGenericPressed()
0131         onReleased: onGenericReleased()
0132         onCanceled: {
0133             control.down = false;
0134             control.pressed = false;
0135         }
0136         onPositionChanged: {
0137             var pos = listView.mapFromItem(this, mouse.x, mouse.y);
0138             indexUnderMouse = listView.indexAt(pos.x, pos.y);
0139             listView.currentIndex = indexUnderMouse;
0140             control.activated(indexUnderMouse);
0141         }
0142 
0143         Connections {
0144             target: popup
0145             onClosed: {
0146                 control.down = false;
0147                 control.pressed = false;
0148             }
0149         }
0150 
0151         function onGenericPressed() {
0152             indexUnderMouse = -1;
0153             listView.currentIndex = control.highlightedIndex;
0154             control.down = true;
0155             control.pressed = true;
0156             control.popup.visible = !control.popup.visible;
0157         }
0158 
0159         function onGenericReleased() {
0160             if (!containsMouse && !hiddenTooltipButton.hovered) {
0161                 control.down = false;
0162                 control.pressed = false;
0163                 control.popup.visible = false;
0164             }
0165             if (indexUnderMouse > -1) {
0166                 control.currentIndex = indexUnderMouse;
0167             }
0168         }
0169 
0170         PlasmaComponents.Button {
0171             id: hiddenTooltipButton
0172             anchors.fill: parent
0173             opacity: 0
0174             visible: control && control.currentIndex>=0 && control.toolTipRole.length>0
0175             tooltip: {
0176                 if (!visible) {
0177                     return "";
0178                 }
0179 
0180                 if (Array.isArray(control.model)) {
0181                     return control.model[control.currentIndex][control.toolTipRole];
0182                 } else {
0183                     return control.model.get(control.currentIndex)[control.toolTipRole];
0184                 }
0185             }
0186 
0187             onPressedChanged: {
0188                 if (pressed) {
0189                     mouseArea.onGenericPressed();
0190                 } else {
0191                     mouseArea.onGenericReleased();
0192                 }
0193             }
0194         }
0195 
0196         RowLayout {
0197             anchors.fill: parent
0198             spacing: 0
0199 
0200             anchors {
0201                 leftMargin: !control.mirrored ? 1 : 0
0202                 rightMargin: control.mirrored ? 1 : 0
0203             }
0204 
0205             PlasmaCore.IconItem {
0206                 id: selectedIcon
0207                 implicitWidth: textLabel.height
0208                 implicitHeight: textLabel.height
0209 
0210                 colorGroup: PlasmaCore.Theme.ButtonColorGroup
0211                 source: {
0212                     if (control
0213                             && control.currentIndex>=0
0214                             && control.iconRole.length>0) {
0215 
0216                         if (Array.isArray(control.model)) {
0217                             return control.model[control.currentIndex][control.iconRole];
0218                         } else {
0219                             return control.model.get(control.currentIndex)[control.iconRole];
0220                         }
0221                     }
0222 
0223                     return "";
0224                 }
0225 
0226                 visible: source !== '' && !control.hideSelectedItemIcon
0227             }
0228 
0229             Label {
0230                 id: textLabel
0231                 Layout.fillWidth: true
0232                 Layout.fillHeight: true
0233                 Layout.leftMargin: !selectedIcon.visible && !control.mirrored ? units.smallSpacing : 0
0234                 Layout.rightMargin: !selectedIcon.visible && control.mirrored ? units.smallSpacing : 0
0235 
0236                 text: control.displayText
0237                 font: control.font
0238                 color: control.pressed ? theme.highlightedTextColor : theme.buttonTextColor
0239                 horizontalAlignment: Text.AlignLeft
0240                 verticalAlignment: Text.AlignVCenter
0241                 opacity: control.enabled ? 1 : 0.6
0242 
0243                 visible: !control.hideDisplayText
0244             }
0245 
0246          /*   T.TextField {
0247                 id: textField
0248                 padding: 0
0249                 Layout.fillWidth: true
0250                 Layout.fillHeight: true
0251 
0252                 text: control.editable ? control.editText : control.displayText
0253 
0254                 enabled: control.editable
0255                 autoScroll: control.editable
0256 
0257                 readOnly: control.down || !control.hasOwnProperty("editable") || !control.editable
0258                 inputMethodHints: control.inputMethodHints
0259                 validator: control.validator
0260 
0261                 // Work around Qt bug where NativeRendering breaks for non-integer scale factors
0262                 // https://bugreports.qt.io/browse/QTBUG-67007
0263                 renderType: Screen.devicePixelRatio % 1 !== 0 ? Text.QtRendering : Text.NativeRendering
0264                 color: theme.buttonTextColor //control.enabled ? theme.textColor : theme.disabledTextColor
0265                 selectionColor: Kirigami.Theme.highlightColor
0266                 selectedTextColor: Kirigami.Theme.highlightedTextColor
0267 
0268                 selectByMouse: !Kirigami.Settings.tabletMode
0269                 cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : undefinedCursor
0270 
0271                 font: control.font
0272                 horizontalAlignment: Text.AlignLeft
0273                 verticalAlignment: Text.AlignVCenter
0274                 opacity: control.enabled ? 1 : 0.6
0275                 onFocusChanged: {
0276                     if (focus) {
0277                         Private.MobileTextActionsToolBar.controlRoot = textField;
0278                     }
0279                 }
0280 
0281                 onPressAndHold: {
0282                     if (!Kirigami.Settings.tabletMode) {
0283                         return;
0284                     }
0285                     forceActiveFocus();
0286                     cursorPosition = positionAt(event.x, event.y);
0287                     selectWord();
0288                 }
0289             }*/
0290         }
0291     }
0292 
0293   /*  Component {
0294         id: mobileCursor
0295         Private.MobileCursor {
0296             target: textField
0297         }
0298     }*/
0299 
0300     Component {
0301         id: undefinedCursor
0302         Item{}
0303     }
0304 
0305  /*   Private.MobileCursor {
0306         target: textField
0307         selectionStartHandle: true
0308         property var rect: textField.positionToRectangle(textField.selectionStart)
0309         //FIXME: this magic values seem to be always valid, for every font,every dpi, every scaling
0310         x: rect.x + 5
0311         y: rect.y + 6
0312     }*/
0313 
0314     background: PlasmaCore.FrameSvgItem {
0315         id: surfaceNormal
0316         //retrocompatibility with old controls
0317         implicitWidth: units.gridUnit * 6
0318         width: parent.width
0319         height: parent.height
0320 
0321         anchors.right: parent.right
0322         anchors.verticalCenter: parent.verticalCenter
0323         anchors.rightMargin: control.buttonIsTransparent ? -margins.right : 0
0324         readonly property bool editable: control.hasOwnProperty("editable") && control.editable
0325         imagePath: editable ? "widgets/lineedit" : "widgets/button"
0326         prefix: editable
0327                 ? "base"
0328                 : (control.pressed || control.forcePressed ? "pressed" : "normal")
0329 
0330         opacity: control.buttonIsTransparent && prefix !== "pressed" && textFieldPrivate.state !== "hover" && !control.popup.visible ? 0 : 1
0331 
0332         Private.TextFieldFocus {
0333             id: textFieldPrivate
0334             visible: parent.editable
0335             z: -1
0336             state: control.activeFocus ? "focus" : (control.hovered ? "hover" : "hidden")
0337             anchors.fill: parent
0338         }
0339         Private.ButtonShadow {
0340             z: -1
0341             visible: !parent.editable
0342             anchors.fill: parent
0343             state: {
0344                 if (control.pressed) {
0345                     return "hidden"
0346                 } else if (control.hovered) {
0347                     return "hover"
0348                 } else if (control.activeFocus) {
0349                     return "focus"
0350                 } else {
0351                     return "shadow"
0352                 }
0353             }
0354         }
0355 
0356         MouseArea {
0357             anchors {
0358                 fill: parent
0359                 leftMargin: control.leftPadding
0360                 rightMargin: control.rightPadding
0361             }
0362             acceptedButtons: Qt.NoButton
0363             onWheel: {
0364                 if (!control.wheelEnabled) {
0365                     return;
0366                 }
0367 
0368                 if (wheel.pixelDelta.y < 0 || wheel.angleDelta.y < 0) {
0369                     control.currentIndex = Math.min(control.currentIndex + 1, delegateModel.count -1);
0370                 } else {
0371                     control.currentIndex = Math.max(control.currentIndex - 1, 0);
0372                 }
0373                 control.activated(control.currentIndex);
0374             }
0375         }
0376     }
0377 
0378     popup: T.Popup {
0379         x: {
0380             if (!control.mirrored) {
0381                 if (popUpRelativeX !== 0) {
0382                     var adjustedX = exceedsContent && control.popUpAlignRight ? -(width - control.width) : popUpRelativeX;
0383                     return  adjustedX;
0384                 } else {
0385                     return 0;
0386                 }
0387             } else {
0388                 //! mirrored case
0389                 if (exceedsContent && control.popUpAlignRight) {
0390                     var adjustedX = width - control.width - popUpRelativeX;
0391                     return  -adjustedX;
0392                 } else {
0393                     return 0;
0394                 }
0395             }
0396         }
0397         y: control.height
0398         width: Math.max(control.width, control.minimumPopUpWidth)
0399         implicitHeight: contentItem.implicitHeight
0400         topMargin: 6
0401         bottomMargin: 6
0402 
0403         readonly property bool exceedsContent: control.width < width
0404 
0405         /*onVisibleChanged: {
0406             if (visible) {
0407                 console.log("  mirrored:" + control.mirrored);
0408                 console.log("  exceeds: " + exceedsContent);
0409                 console.log("  popupAR: " + control.popUpAlignRight);
0410                 console.log("  popupRX: " + popUpRelativeX);
0411             }
0412         }*/
0413 
0414         contentItem: ListView {
0415             id: listView
0416             clip: true
0417             implicitHeight: contentHeight
0418             model: control.popup.visible ? control.delegateModel : null
0419             currentIndex: control.highlightedIndex
0420             highlightRangeMode: ListView.ApplyRange
0421             highlightMoveDuration: 0
0422             // HACK: When the ComboBox is not inside a top-level Window, it's Popup does not inherit
0423             // the LayoutMirroring options. This is a workaround to fix this by enforcing
0424             // the LayoutMirroring options properly.
0425             // QTBUG: https://bugreports.qt.io/browse/QTBUG-66446
0426             LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
0427             LayoutMirroring.childrenInherit: true
0428             T.ScrollBar.vertical: Controls.ScrollBar { }
0429 
0430             signal iconClicked(int index);
0431 
0432             onIconClicked: control.iconClicked(index);
0433         }
0434         background: Rectangle {
0435             anchors {
0436                 fill: parent
0437                 margins: -1
0438             }
0439             radius: 2
0440             color: theme.viewBackgroundColor
0441             border.color: Qt.rgba(theme.textColor.r, theme.textColor.g, theme.textColor.b, 0.3)
0442             layer.enabled: true
0443 
0444             layer.effect: DropShadow {
0445                 transparentBorder: true
0446                 radius: 4
0447                 samples: 8
0448                 horizontalOffset: 2
0449                 verticalOffset: 2
0450                 color: Qt.rgba(0, 0, 0, 0.3)
0451             }
0452         }
0453     }
0454 }