Warning, /libraries/kirigami-addons/src/formcard/FormComboBoxDelegate.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  * Copyright 2022 Devin Lin <devin@kde.org>
0003  * SPDX-License-Identifier: LGPL-2.0-or-later
0004  */
0005 
0006 import QtQuick 2.15
0007 import QtQuick.Controls 2.15 as QQC2
0008 import QtQuick.Layouts 1.15
0009 
0010 import org.kde.kirigami 2.19 as Kirigami
0011 
0012 /**
0013  * @brief A Form delegate that corresponds to a combobox.
0014  *
0015  * This component is used for individual settings that can have multiple
0016  * possible values shown in a vertical list, typically defined in a ::model.
0017  *
0018  * Many of its properties require familiarity with QtQuick.Controls.ComboBox.
0019  *
0020  * Use the inherited QtQuick.Controls.AbstractButton.text property to define
0021  * the main text of the combobox.
0022  *
0023  * If you need a purely on/off toggle, use a FormSwitchDelegate instead.
0024  *
0025  * If you need an on/off/tristate toggle, use a FormCheckDelegate instead.
0026  *
0027  * If you need multiple toggles instead of multiple values for the same
0028  * setting, consider using a FormRadioDelegate.
0029  *
0030  * @since KirigamiAddons 0.11.0
0031  *
0032  * @see QtQuick.Controls.AbstractButton
0033  * @see FormSwitchDelegate
0034  * @see FormCheckDelegate
0035  * @see FormRadioDelegate
0036  *
0037  * @inherit AbstractFormDelegate
0038  */
0039 AbstractFormDelegate {
0040     id: controlRoot
0041 
0042     /**
0043      * @brief This signal is emitted when the item at @p index is activated
0044      * by the user.
0045      */
0046     signal activated(int index)
0047 
0048     /**
0049      * @brief This signal is emitted when the Return or Enter key is pressed
0050      * while an editable combo box is focused.
0051      *
0052      * @see editable
0053      */
0054     signal accepted()
0055 
0056     /**
0057      * @brief A label that contains secondary text that appears under the
0058      * inherited text property.
0059      *
0060      * This provides additional information shown in a faint gray color.
0061      *
0062      * This is supposed to be a short text and the API user should avoid
0063      * making it longer than two lines.
0064      */
0065     property string description: ""
0066 
0067     /**
0068      * @brief This property holds the value of the current item in the combobox.
0069      */
0070     property alias currentValue: combobox.currentValue
0071 
0072     /**
0073      * @brief This property holds the text of the current item in the combobox.
0074      *
0075      * @see displayText
0076      */
0077     property alias currentText: combobox.currentText
0078 
0079     /**
0080      * @brief This property holds the model providing data for the combobox.
0081      *
0082      * @see displayText
0083      * @see QtQuick.Controls.ComboBox.model
0084      * @see <a href="https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html">Models and Views in QtQuick</a>
0085      */
0086     property var model
0087 
0088     /**
0089      * @brief This property holds the `textRole` of the internal combobox.
0090      *
0091      * @see QtQuick.Controls.ComboBox.textRole
0092      */
0093     property alias textRole: combobox.textRole
0094 
0095     /**
0096      * @brief This property holds the `valueRole` of the internal combobox.
0097      *
0098      * @see QtQuick.Controls.ComboBox.valueRole
0099      */
0100     property alias valueRole: combobox.valueRole
0101 
0102     /**
0103      * @brief This property holds the `currentIndex` of the internal combobox.
0104      *
0105      * default: `-1` when the ::model has no data, `0` otherwise
0106      *
0107      * @see QtQuick.Controls.ComboBox.currentIndex
0108      */
0109     property alias currentIndex: combobox.currentIndex
0110 
0111     /**
0112      * @brief This property holds the `highlightedIndex` of the internal combobox.
0113      *
0114      * @see QtQuick.Controls.ComboBox.highlightedIndex
0115      */
0116     property alias highlightedIndex: combobox.highlightedIndex
0117 
0118     /**
0119      * @brief This property holds the `displayText` of the internal combobox.
0120      *
0121      * This can be used to slightly modify the text to be displayed in the combobox, for instance, by adding a string with the ::currentText.
0122      *
0123      * @see QtQuick.Controls.ComboBox.displayText
0124      */
0125     property alias displayText: combobox.displayText
0126 
0127     /**
0128      * @brief This property holds the `editable` property of the internal combobox.
0129      *
0130      * This turns the combobox editable, allowing the user to specify
0131      * existing values or add new ones.
0132      *
0133      * Use this only when ::displayMode is set to
0134      * FormComboBoxDelegate.ComboBox.
0135      *
0136      * @see QtQuick.Controls.ComboBox.editable
0137      */
0138     property alias editable: combobox.editable
0139 
0140     /**
0141      * @brief This property holds the `editText` property of the internal combobox.
0142      *
0143      * @see QtQuick.Controls.ComboBox.editText
0144      */
0145     property alias editText: combobox.editText
0146 
0147     /** @brief The enum used to determine the ::displayMode. **/
0148     enum DisplayMode {
0149         /**
0150          * A standard combobox component containing a vertical list of values.
0151          */
0152         ComboBox,
0153         /**
0154          * A button with similar appearance to a combobox that, when clicked,
0155          * shows a Kirigami.OverlaySheet at the middle of the window
0156          * containing a vertical list of values.
0157          */
0158         Dialog,
0159         /**
0160          * A button with similar appearance to a combobox that, when clicked,
0161          * shows a Kirigami.ScrollablePage in a new window containing a
0162          * vertical list of values.
0163          */
0164         Page
0165     }
0166 
0167     /**
0168      * @brief This property holds what display mode the delegate should show as.
0169      *
0170      * Set this property to the desired ::DisplayMode.
0171      *
0172      * default: `FormComboBoxDelegate.ComboBox`
0173      *
0174      * @see DisplayMode
0175      */
0176     property int displayMode: Kirigami.Settings.isMobile ? FormComboBoxDelegate.Dialog : FormComboBoxDelegate.ComboBox
0177 
0178     /**
0179      * @brief The delegate component to use as entries in the combobox display mode.
0180      */
0181     property Component comboBoxDelegate: QQC2.ItemDelegate {
0182         implicitWidth: ListView.view ? ListView.view.width : Kirigami.Units.gridUnit * 16
0183         text: controlRoot.textRole ? (Array.isArray(controlRoot.model) ? modelData[controlRoot.textRole] : model[controlRoot.textRole]) : modelData
0184         highlighted: controlRoot.highlightedIndex === index
0185         property bool separatorVisible: false
0186         Kirigami.Theme.colorSet: controlRoot.Kirigami.Theme.inherit ? controlRoot.Kirigami.Theme.colorSet : Kirigami.Theme.View
0187         Kirigami.Theme.inherit: controlRoot.Kirigami.Theme.inherit
0188     }
0189 
0190     /**
0191      * @brief The delegate component to use as entries for each value in the dialog and page display mode.
0192      */
0193     property Component dialogDelegate: QQC2.RadioDelegate {
0194         implicitWidth: ListView.view ? ListView.view.width : Kirigami.Units.gridUnit * 16
0195         text: controlRoot.textRole ? (Array.isArray(controlRoot.model) ? modelData[controlRoot.textRole] : model[controlRoot.textRole]) : modelData
0196         checked: controlRoot.currentIndex === index
0197         property bool separatorVisible: false
0198         Kirigami.Theme.colorSet: controlRoot.Kirigami.Theme.inherit ? controlRoot.Kirigami.Theme.colorSet : Kirigami.Theme.View
0199         Kirigami.Theme.inherit: controlRoot.Kirigami.Theme.inherit
0200         onClicked: {
0201             controlRoot.currentIndex = index;
0202             controlRoot.activated(index);
0203             controlRoot.closeDialog();
0204         }
0205     }
0206 
0207     /**
0208      * @brief Closes the dialog or layer.
0209      *
0210      * This function can be used when reimplementing the ::page or ::dialog.
0211      */
0212     function closeDialog() {
0213         if (_selectionPageItem) {
0214             _selectionPageItem.closeDialog();
0215             _selectionPageItem = null;
0216         }
0217 
0218         if (dialog) {
0219             dialog.close();
0220         }
0221     }
0222 
0223     property var _selectionPageItem: null
0224     property real __indicatorMargin: controlRoot.indicator && controlRoot.indicator.visible && controlRoot.indicator.width > 0 ? controlRoot.spacing + indicator.width + controlRoot.spacing : 0
0225 
0226     leftPadding: horizontalPadding + (!controlRoot.mirrored ? 0 : __indicatorMargin)
0227     rightPadding: horizontalPadding + (controlRoot.mirrored ? 0 : __indicatorMargin)
0228 
0229 
0230     // use connections instead of onClicked on root, so that users can supply
0231     // their own behaviour.
0232     Connections {
0233         target: controlRoot
0234         function onClicked() {
0235             if (controlRoot.displayMode === FormComboBoxDelegate.Dialog) {
0236                 controlRoot.dialog.open();
0237             } else if (controlRoot.displayMode === FormComboBoxDelegate.Page) {
0238                 controlRoot._selectionPageItem = applicationWindow().pageStack.pushDialogLayer(page)
0239             } else {
0240                 combobox.popup.open();
0241             }
0242         }
0243     }
0244 
0245     /**
0246      * @brief The dialog component used for the combobox.
0247      *
0248      * This property allows to override the internal dialog
0249      * with a custom component.
0250      */
0251     property var dialog: Kirigami.Dialog {
0252         id: dialog
0253         showCloseButton: false
0254         title: controlRoot.text
0255         preferredWidth: Kirigami.Units.gridUnit * 16
0256         parent: QQC2.Overlay.overlay
0257 
0258         ColumnLayout {
0259             spacing: 0
0260 
0261             Repeater {
0262                 model: controlRoot.model
0263                 delegate: controlRoot.dialogDelegate
0264             }
0265 
0266             QQC2.TextField {
0267                 visible: controlRoot.editable
0268                 onTextChanged: controlRoot.editText = text;
0269                 Layout.fillWidth: true
0270             }
0271         }
0272     }
0273 
0274     /**
0275      * @brief The page component used for the combobox, if applicable.
0276      *
0277      * This property allows to override the internal
0278      * Kirigami.ScrollablePage with a custom component.
0279      */
0280     property Component page: Kirigami.ScrollablePage {
0281         title: controlRoot.text
0282 
0283         ListView {
0284             spacing: 0
0285             model: controlRoot.model
0286             delegate: controlRoot.dialogDelegate
0287 
0288             footer: QQC2.TextField {
0289                 visible: controlRoot.editable
0290                 onTextChanged: controlRoot.editText = text;
0291                 Layout.fillWidth: true
0292             }
0293         }
0294     }
0295 
0296     function indexOfValue(value) {
0297         return combobox.indexOfValue(value);
0298     }
0299 
0300     focusPolicy: Qt.StrongFocus
0301     Accessible.description: description
0302     Accessible.onPressAction: controlRoot.clicked()
0303 
0304     contentItem: ColumnLayout {
0305         spacing: Kirigami.Units.smallSpacing
0306 
0307         RowLayout {
0308             Layout.fillWidth: true
0309             spacing: Kirigami.Units.smallSpacing
0310 
0311             QQC2.Label {
0312                 Layout.fillWidth: true
0313                 text: controlRoot.text
0314                 elide: Text.ElideRight
0315                 color: controlRoot.enabled ? Kirigami.Theme.textColor : Kirigami.Theme.disabledTextColor
0316                 wrapMode: Text.Wrap
0317                 maximumLineCount: 2
0318                 Accessible.ignored: true
0319             }
0320 
0321             QQC2.Label {
0322                 Layout.alignment: Qt.AlignRight
0323                 Layout.rightMargin: Kirigami.Units.smallSpacing
0324                 color: Kirigami.Theme.disabledTextColor
0325                 text: controlRoot.displayText
0326                 visible: controlRoot.displayMode === FormComboBoxDelegate.Dialog || controlRoot.displayMode === FormComboBoxDelegate.Page
0327             }
0328 
0329             QQC2.ComboBox {
0330                 id: combobox
0331                 focusPolicy: Qt.NoFocus // provided by parent
0332                 model: controlRoot.model
0333                 visible: controlRoot.displayMode == FormComboBoxDelegate.ComboBox
0334                 delegate: controlRoot.comboBoxDelegate
0335                 currentIndex: controlRoot.currentIndex
0336                 onActivated: index => controlRoot.activated(index)
0337                 onAccepted: controlRoot.accepted()
0338             }
0339 
0340             FormArrow {
0341                 Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
0342                 direction: Qt.DownArrow
0343                 visible: controlRoot.displayMode === FormComboBoxDelegate.Dialog || controlRoot.displayMode === FormComboBoxDelegate.Page
0344             }
0345         }
0346 
0347         QQC2.Label {
0348             visible: controlRoot.description !== ""
0349             Layout.fillWidth: true
0350             text: controlRoot.description
0351             color: Kirigami.Theme.disabledTextColor
0352             wrapMode: Text.Wrap
0353             Accessible.ignored: true
0354         }
0355     }
0356 }
0357