linphone-desktop/Linphone/view/Control/Button/ComboBox.qml
2025-11-07 16:55:05 +00:00

270 lines
12 KiB
QML

import QtQuick
import QtQuick.Controls.Basic as Control
import QtQuick.Layouts
import QtQuick.Effects
import Linphone
import CustomControls 1.0
import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
Control.ComboBox {
id: mainItem
// Usage : each item of the model list must be {text: …, img: …}
// If string list, only text part of the delegate will be filled
// readonly property string currentText: selectedItemText.text
property alias listView: listView
property string constantImageSource
property real pixelSize: Typography.p1.pixelSize
property real weight: Typography.p1.weight
property real leftMargin: Utils.getSizeWithScreenRatio(10)
property bool oneLine: false
property bool shadowEnabled: mainItem.activeFocus || mainItem.hovered
property string flagRole // Specific case if flag is shown (special font)
property var indicatorColor: DefaultStyle.main2_600
property int indicatorRightMargin: Utils.getSizeWithScreenRatio(20)
leftPadding: Utils.getSizeWithScreenRatio(10)
rightPadding: indicImage.width + indicatorRightMargin
property bool keyboardFocus: FocusHelper.keyboardFocus
// Text properties
property color textColor: DefaultStyle.main2_600
property color disabledTextColor: DefaultStyle.grey_400
// Border properties
property color borderColor: DefaultStyle.grey_200
property color disabledBorderColor: DefaultStyle.grey_400
property color activeFocusedBorderColor: DefaultStyle.main1_500_main
property color keyboardFocusedBorderColor: DefaultStyle.main2_900
property real borderWidth: Utils.getSizeWithScreenRatio(1)
property real keyboardFocusedBorderWidth: Utils.getSizeWithScreenRatio(3)
// Background properties
property color color: DefaultStyle.grey_100
property color disabledColor: DefaultStyle.grey_200
onConstantImageSourceChanged: if (constantImageSource)
selectedItemImg.imageSource = constantImageSource
onCurrentIndexChanged: {
var item = model[currentIndex];
if (!item)
item = model.getAt(currentIndex);
if (!item)
return;
selectedItemText.text = mainItem.textRole ? item[mainItem.textRole] : item.text ? item.text : item ? item : "";
if (mainItem.flagRole)
selectedItemFlag.text = item[mainItem.flagRole];
selectedItemImg.imageSource = constantImageSource ? constantImageSource : item.img ? item.img : "";
}
Keys.onPressed: event => {
if (!mainItem.contentItem.activeFocus && (event.key == Qt.Key_Space || event.key == Qt.Key_Enter || event.key == Qt.Key_Return)) {
mainItem.popup.open();
event.accepted = true;
}
}
background: Item {
Rectangle {
id: buttonBackground
anchors.fill: parent
radius: Math.round(mainItem.height / 2)
color: mainItem.enabled ? mainItem.color : mainItem.disabledColor
border.color: !mainItem.enabled ? mainItem.disabledBorderColor : mainItem.keyboardFocus ? mainItem.keyboardFocusedBorderColor : mainItem.activeFocus || mainItem.popup.opened ? mainItem.activeFocusedBorderColor : mainItem.borderColor
border.width: mainItem.keyboardFocus ? mainItem.keyboardFocusedBorderWidth : mainItem.borderWidth
}
MultiEffect {
enabled: mainItem.shadowEnabled
anchors.fill: buttonBackground
source: buttonBackground
visible: mainItem.shadowEnabled
// Crash : https://bugreports.qt.io/browse/QTBUG-124730
shadowEnabled: true //mainItem.shadowEnabled
shadowColor: DefaultStyle.grey_1000
shadowBlur: 0.5
shadowOpacity: mainItem.shadowEnabled ? 0.1 : 0.0
}
}
contentItem: RowLayout {
spacing: Utils.getSizeWithScreenRatio(5)
EffectImage {
id: selectedItemImg
Layout.preferredWidth: visible ? Utils.getSizeWithScreenRatio(24) : 0
Layout.preferredHeight: visible ? Utils.getSizeWithScreenRatio(24) : 0
Layout.leftMargin: mainItem.leftMargin
imageSource: mainItem.constantImageSource ? mainItem.constantImageSource : ""
colorizationColor: mainItem.enabled ? mainItem.textColor : mainItem.disabledTextColor
visible: imageSource != ""
fillMode: Image.PreserveAspectFit
}
Text {
id: selectedItemFlag
Layout.preferredWidth: implicitWidth
Layout.leftMargin: selectedItemImg.visible ? 0 : Utils.getSizeWithScreenRatio(5)
Layout.alignment: Qt.AlignCenter
color: mainItem.enabled ? mainItem.textColor : mainItem.disabledTextColor
font {
family: DefaultStyle.flagFont
pixelSize: mainItem.pixelSize
weight: mainItem.weight
}
}
Text {
id: selectedItemText
Layout.fillWidth: true
Layout.leftMargin: selectedItemImg.visible ? 0 : Utils.getSizeWithScreenRatio(5)
Layout.rightMargin: Utils.getSizeWithScreenRatio(20)
Layout.alignment: Qt.AlignCenter
color: mainItem.enabled ? mainItem.textColor : mainItem.disabledTextColor
elide: Text.ElideRight
maximumLineCount: oneLine ? 1 : 2
wrapMode: Text.WrapAnywhere
font {
family: DefaultStyle.defaultFont
pixelSize: mainItem.pixelSize
weight: mainItem.weight
}
}
}
indicator: EffectImage {
id: indicImage
z: 1
anchors.right: parent.right
anchors.rightMargin: mainItem.indicatorRightMargin
anchors.verticalCenter: parent.verticalCenter
imageSource: AppIcons.downArrow
width: Utils.getSizeWithScreenRatio(15)
height: Utils.getSizeWithScreenRatio(15)
fillMode: Image.PreserveAspectFit
colorizationColor: mainItem.indicatorColor
// Rotate when popup open/close
transformOrigin: Item.Center
rotation: mainItem.popup.opened ? 180 : 0
Behavior on rotation {
NumberAnimation {
duration: 200
easing.type: Easing.InOutQuad
}
}
}
popup: Control.Popup {
id: popup
y: mainItem.height - 1
width: mainItem.width
implicitHeight: Math.min(contentItem.implicitHeight, mainWindow.height)
padding: Utils.getSizeWithScreenRatio(1)
onOpened: {
listView.positionViewAtIndex(listView.currentIndex, ListView.Center);
listView.forceActiveFocus();
}
contentItem: ListView {
id: listView
clip: true
implicitHeight: contentHeight
height: popup.height
model: visible ? mainItem.model : []
currentIndex: mainItem.highlightedIndex >= 0 ? mainItem.highlightedIndex : 0
highlightFollowsCurrentItem: true
highlightMoveDuration: -1
highlightMoveVelocity: -1
highlight: Rectangle {
width: listView.width
color: DefaultStyle.main2_200
radius: Utils.getSizeWithScreenRatio(15)
y: listView.currentItem ? listView.currentItem.y : 0
}
Keys.onPressed: event => {
if (event.key == Qt.Key_Space || event.key == Qt.Key_Enter || event.key == Qt.Key_Return) {
event.accepted = true;
mainItem.currentIndex = listView.currentIndex;
popup.close();
}
}
delegate: Item {
width: mainItem.width
height: mainItem.height
// anchors.left: listView.left
// anchors.right: listView.right
Accessible.name: typeof (modelData) != "undefined" ? mainItem.textRole ? modelData[mainItem.textRole] : modelData.text ? modelData.text : modelData : $modelData ? mainItem.textRole ? $modelData[mainItem.textRole] : $modelData : ""
RowLayout {
anchors.fill: parent
EffectImage {
id: delegateImg
Layout.preferredWidth: visible ? Utils.getSizeWithScreenRatio(20) : 0
Layout.leftMargin: Utils.getSizeWithScreenRatio(10)
visible: imageSource != ""
imageWidth: Utils.getSizeWithScreenRatio(20)
imageSource: typeof (modelData) != "undefined" && modelData.img ? modelData.img : ""
fillMode: Image.PreserveAspectFit
}
Text {
id: flagItem
Layout.preferredWidth: implicitWidth
Layout.leftMargin: delegateImg.visible ? 0 : Utils.getSizeWithScreenRatio(5)
Layout.alignment: Qt.AlignCenter
visible: mainItem.flagRole
font {
family: DefaultStyle.flagFont
pixelSize: mainItem.pixelSize
weight: mainItem.weight
}
text: mainItem.flagRole ? typeof (modelData) != "undefined" ? modelData[mainItem.flagRole] : $modelData[mainItem.flagRole] : ""
}
Text {
Layout.fillWidth: true
Layout.leftMargin: delegateImg.visible ? 0 : Utils.getSizeWithScreenRatio(flagItem.visble ? 5 : 25)
Layout.rightMargin: Utils.getSizeWithScreenRatio(20)
Layout.alignment: Qt.AlignCenter
text: typeof (modelData) != "undefined" ? mainItem.textRole ? modelData[mainItem.textRole] : modelData.text ? modelData.text : modelData : $modelData ? mainItem.textRole ? $modelData[mainItem.textRole] : $modelData : ""
elide: Text.ElideRight
maximumLineCount: 1
wrapMode: Text.WrapAnywhere
font {
family: DefaultStyle.defaultFont
pixelSize: Utils.getSizeWithScreenRatio(15)
weight: Font.Normal
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
Rectangle {
anchors.fill: parent
opacity: 0.1
radius: Utils.getSizeWithScreenRatio(15)
color: DefaultStyle.main2_500_main
visible: parent.containsMouse
}
onClicked: {
mainItem.currentIndex = index;
popup.close();
}
}
}
Control.ScrollIndicator.vertical: Control.ScrollIndicator {}
}
background: Item {
implicitWidth: mainItem.width
implicitHeight: Utils.getSizeWithScreenRatio(30)
Rectangle {
id: cboxBg
anchors.fill: parent
radius: Utils.getSizeWithScreenRatio(15)
}
MultiEffect {
anchors.fill: cboxBg
source: cboxBg
shadowEnabled: true
shadowColor: DefaultStyle.grey_1000
shadowBlur: 0.1
shadowOpacity: 0.1
}
}
}
}