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

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