noctalia-shell/Widgets/NComboBox.qml
quadbyte b723eccc78 Renamed most font and sizing shorthands properties for easier understanding and maintenance
property real fontSizeXS: 9
  property real fontSizeS: 10
  property real fontSizeM: 11
  property real fontSizeL: 13
  property real fontSizeXL: 16
  property real fontSizeXXL: 18
  property real fontSizeXXXL: 24
2025-08-18 11:12:51 -04:00

141 lines
3.9 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
import qs.Services
import qs.Widgets
ColumnLayout {
id: root
readonly property real preferredHeight: Style.baseWidgetSize * 1.25 * scaling
property string label: ""
property string description: ""
property ListModel model: {
}
property string currentKey: ''
signal selected(string key)
spacing: Style.marginS * scaling
Layout.fillWidth: true
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NText {
text: label
font.pointSize: Style.fontSizeM * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: description
font.pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurface
wrapMode: Text.WordWrap
}
}
function findIndexByKey(key) {
for (var i = 0; i < root.model.count; i++) {
if (root.model.get(i).key === key) {
return i
}
}
return -1
}
ComboBox {
id: combo
Layout.fillWidth: true
Layout.preferredHeight: height
model: model
currentIndex: findIndexByKey(currentKey)
onActivated: {
root.selected(model.get(combo.currentIndex).key)
}
background: Rectangle {
implicitWidth: Style.baseWidgetSize * 3.75 * scaling
implicitHeight: preferredHeight
color: Color.mSurface
border.color: combo.activeFocus ? Color.mTertiary : Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
radius: Style.radiusM * scaling
}
contentItem: NText {
leftPadding: Style.marginL * scaling
rightPadding: combo.indicator.width + Style.marginL * scaling
font.pointSize: Style.fontSizeM * scaling
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
text: (combo.currentIndex >= 0 && combo.currentIndex < root.model.count) ? root.model.get(
combo.currentIndex).name : ""
}
indicator: NIcon {
x: combo.width - width - Style.marginM * scaling
y: combo.topPadding + (combo.availableHeight - height) / 2
text: "arrow_drop_down"
font.pointSize: Style.fontSizeXXL * scaling
}
popup: Popup {
y: combo.height
width: combo.width
implicitHeight: Math.min(160 * scaling, contentItem.implicitHeight + Style.marginM * scaling * 2)
padding: Style.marginM * scaling
contentItem: ListView {
property var comboBoxRoot: root
clip: true
implicitHeight: contentHeight
model: combo.popup.visible ? root.model : null
ScrollIndicator.vertical: ScrollIndicator {}
delegate: ItemDelegate {
width: combo.width
hoverEnabled: true
highlighted: ListView.view.currentIndex === index
onHoveredChanged: {
if (hovered) {
ListView.view.currentIndex = index
}
}
onClicked: {
ListView.view.comboBoxRoot.selected(ListView.view.comboBoxRoot.model.get(index).key)
combo.currentIndex = index
combo.popup.close()
}
contentItem: NText {
text: name
font.pointSize: Style.fontSizeM * scaling
color: highlighted ? Color.mSurface : Color.mOnSurface
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
width: combo.width - Style.marginM * scaling * 3
color: highlighted ? Color.mTertiary : Color.transparent
radius: Style.radiusS * scaling
}
}
}
background: Rectangle {
color: Color.mSurfaceVariant
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
radius: Style.radiusM * scaling
}
}
}
}