mirror of
https://github.com/arthur-pbty/arthur-os.git
synced 2026-08-06 12:39:35 +02:00
Settings dialogs were rendering text/spin/combo controls with Qt's default light style, which clashed with the dark Omarchy theme — black text on dark fills, white dropdown popups, rounded corners, and a pill-style toggle that didn't match the native StyleToggleRow switch. - Style.qml: collapse all radius tokens to 0 so Noctalia-compat widgets inherit Omarchy's sharp-corner convention - NToggle: rewrite to mirror the native 48x22 switch with accent fill and a sliding 16x16 thumb - NComboBox: skin contentItem, indicator, popup, and delegate so the dropdown reads on dark themes - NSpinBox: add a styled background, contentItem, and up/down indicators - SettingsPanel calendar form + DynamicSettingsForm string field: drop default TextField chrome for the same translucent foreground fill used by WidgetCard, accent border on focus
139 lines
3.6 KiB
QML
139 lines
3.6 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import qs.Commons
|
|
|
|
ComboBox {
|
|
id: root
|
|
|
|
property string label: ""
|
|
// Noctalia's NComboBox API commonly uses a model of { key, name } objects,
|
|
// a currentKey property, and an onSelected(key, item) handler. Qt's ComboBox
|
|
// only knows currentIndex/currentText, so bridge the small API surface here.
|
|
property string currentKey: ""
|
|
|
|
signal selected(var key, var item)
|
|
|
|
textRole: "name"
|
|
valueRole: "key"
|
|
font.family: "JetBrainsMono Nerd Font"
|
|
font.pixelSize: Style.fontSizeS
|
|
implicitHeight: 32
|
|
leftPadding: 10
|
|
rightPadding: 28
|
|
topPadding: 4
|
|
bottomPadding: 4
|
|
|
|
function itemAt(index) {
|
|
if (index < 0) return null
|
|
if (Array.isArray(root.model)) return root.model[index] || null
|
|
return null
|
|
}
|
|
|
|
function keyAt(index) {
|
|
var item = itemAt(index)
|
|
if (!item) return ""
|
|
if (item.key !== undefined && item.key !== null) return String(item.key)
|
|
if (item.value !== undefined && item.value !== null) return String(item.value)
|
|
if (item.name !== undefined && item.name !== null) return String(item.name)
|
|
return String(item)
|
|
}
|
|
|
|
function syncCurrentIndex() {
|
|
if (!Array.isArray(root.model)) return
|
|
for (var i = 0; i < root.model.length; i++) {
|
|
if (keyAt(i) === String(root.currentKey || "")) {
|
|
if (root.currentIndex !== i) root.currentIndex = i
|
|
return
|
|
}
|
|
}
|
|
if (root.model.length > 0 && root.currentIndex < 0) root.currentIndex = 0
|
|
}
|
|
|
|
Component.onCompleted: syncCurrentIndex()
|
|
onCurrentKeyChanged: syncCurrentIndex()
|
|
onModelChanged: syncCurrentIndex()
|
|
|
|
onActivated: function(index) {
|
|
var item = itemAt(index)
|
|
var key = keyAt(index)
|
|
root.currentKey = key
|
|
root.selected(key, item)
|
|
}
|
|
|
|
contentItem: Text {
|
|
text: root.displayText
|
|
color: Color.mOnSurface
|
|
font: root.font
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
background: Rectangle {
|
|
color: Color.mSurfaceVariant
|
|
border.color: root.activeFocus ? Color.mPrimary : Color.mOutline
|
|
border.width: Style.borderS
|
|
radius: 0
|
|
}
|
|
|
|
indicator: Text {
|
|
x: root.width - width - 10
|
|
y: (root.height - height) / 2
|
|
text: "▾"
|
|
color: Color.mOnSurfaceVariant
|
|
font.family: root.font.family
|
|
font.pixelSize: 11
|
|
}
|
|
|
|
delegate: ItemDelegate {
|
|
id: del
|
|
required property int index
|
|
required property var modelData
|
|
width: ListView.view ? ListView.view.width : root.width
|
|
height: 28
|
|
highlighted: root.highlightedIndex === del.index
|
|
|
|
contentItem: Text {
|
|
text: {
|
|
var m = del.modelData
|
|
if (m === null || m === undefined) return ""
|
|
if (root.textRole && m[root.textRole] !== undefined) return String(m[root.textRole])
|
|
return String(m)
|
|
}
|
|
color: Color.mOnSurface
|
|
font: root.font
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
background: Rectangle {
|
|
color: del.highlighted || del.hovered
|
|
? Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.14)
|
|
: "transparent"
|
|
radius: 0
|
|
}
|
|
}
|
|
|
|
popup: Popup {
|
|
y: root.height
|
|
width: root.width
|
|
implicitHeight: Math.min(contentItem.implicitHeight + 2, 280)
|
|
padding: 1
|
|
|
|
background: Rectangle {
|
|
color: Color.mSurface
|
|
border.color: Color.mOutline
|
|
border.width: Style.borderS
|
|
radius: 0
|
|
}
|
|
|
|
contentItem: ListView {
|
|
clip: true
|
|
implicitHeight: contentHeight
|
|
model: root.popup.visible ? root.delegateModel : null
|
|
currentIndex: root.highlightedIndex
|
|
boundsBehavior: Flickable.StopAtBounds
|
|
ScrollIndicator.vertical: ScrollIndicator { }
|
|
}
|
|
}
|
|
}
|