262 lines
7.5 KiB
QML
262 lines
7.5 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import QtQuick.Window
|
|
import qs.Commons
|
|
import qs.Widgets
|
|
import qs.Services
|
|
|
|
ColumnLayout {
|
|
id: root
|
|
spacing: Style.marginM * scaling
|
|
|
|
property var widgetData: null
|
|
property var widgetMetadata: null
|
|
|
|
function saveSettings() {
|
|
var settings = Object.assign({}, widgetData || {})
|
|
settings.icon = iconInput.text
|
|
settings.leftClickExec = leftClickExecInput.text
|
|
settings.rightClickExec = rightClickExecInput.text
|
|
settings.middleClickExec = middleClickExecInput.text
|
|
settings.textCommand = textCommandInput.text
|
|
settings.textIntervalMs = parseInt(textIntervalInput.text || textIntervalInput.placeholderText, 10)
|
|
return settings
|
|
}
|
|
|
|
NTextInput {
|
|
id: iconInput
|
|
Layout.fillWidth: true
|
|
label: "Icon Name"
|
|
description: "Select an icon from the library."
|
|
placeholderText: "Enter icon name (e.g., cat, gear, house, ...)"
|
|
text: widgetData?.icon || widgetMetadata.icon
|
|
}
|
|
|
|
RowLayout {
|
|
spacing: Style.marginS * scaling
|
|
Layout.alignment: Qt.AlignLeft
|
|
NIcon {
|
|
Layout.alignment: Qt.AlignVCenter
|
|
icon: iconInput.text
|
|
visible: iconInput.text !== ""
|
|
}
|
|
NButton {
|
|
text: "Browse"
|
|
onClicked: iconPicker.open()
|
|
}
|
|
}
|
|
|
|
Popup {
|
|
id: iconPicker
|
|
modal: true
|
|
width: {
|
|
var w = Math.round(Math.max(Screen.width * 0.35, 900) * scaling)
|
|
w = Math.min(w, Screen.width - Style.marginL * 2)
|
|
return w
|
|
}
|
|
height: {
|
|
var h = Math.round(Math.max(Screen.height * 0.65, 700) * scaling)
|
|
h = Math.min(h, Screen.height - Style.barHeight * scaling - Style.marginL * 2)
|
|
return h
|
|
}
|
|
anchors.centerIn: Overlay.overlay
|
|
padding: Style.marginXL * scaling
|
|
|
|
property string query: ""
|
|
property string selectedIcon: ""
|
|
property var allIcons: Object.keys(Icons.icons)
|
|
property var filteredIcons: allIcons.filter(function (name) {
|
|
return query === "" || name.toLowerCase().indexOf(query.toLowerCase()) !== -1
|
|
})
|
|
readonly property int columns: 6
|
|
readonly property int cellW: Math.floor(grid.width / columns)
|
|
readonly property int cellH: Math.round(cellW * 0.7 + 36 * scaling)
|
|
|
|
background: Rectangle {
|
|
color: Color.mSurface
|
|
radius: Style.radiusL * scaling
|
|
border.color: Color.mPrimary
|
|
border.width: Style.borderM * scaling
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
spacing: Style.marginM * scaling
|
|
|
|
// Title row
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
NText {
|
|
text: "Icon Picker"
|
|
font.pointSize: Style.fontSizeL * scaling
|
|
font.weight: Style.fontWeightBold
|
|
color: Color.mPrimary
|
|
Layout.fillWidth: true
|
|
}
|
|
NIconButton {
|
|
icon: "close"
|
|
onClicked: iconPicker.close()
|
|
}
|
|
}
|
|
|
|
NDivider {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: Style.marginS * scaling
|
|
NTextInput {
|
|
Layout.fillWidth: true
|
|
label: "Search"
|
|
placeholderText: "Search (e.g., arrow, battery, cloud)"
|
|
text: iconPicker.query
|
|
onTextChanged: iconPicker.query = text.trim().toLowerCase()
|
|
}
|
|
}
|
|
|
|
// Icon grid
|
|
NScrollView {
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
clip: true
|
|
horizontalPolicy: ScrollBar.AlwaysOff
|
|
verticalPolicy: ScrollBar.AlwaysOn
|
|
|
|
GridView {
|
|
id: grid
|
|
anchors.fill: parent
|
|
anchors.margins: Style.marginM * scaling
|
|
cellWidth: iconPicker.cellW
|
|
cellHeight: iconPicker.cellH
|
|
model: iconPicker.filteredIcons
|
|
delegate: Rectangle {
|
|
width: grid.cellWidth
|
|
height: grid.cellHeight
|
|
radius: Style.radiusS * scaling
|
|
clip: true
|
|
color: (iconPicker.selectedIcon === modelData) ? Qt.alpha(Color.mPrimary, 0.15) : "transparent"
|
|
border.color: (iconPicker.selectedIcon === modelData) ? Color.mPrimary : Qt.rgba(0, 0, 0, 0)
|
|
border.width: (iconPicker.selectedIcon === modelData) ? Style.borderS * scaling : 0
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: iconPicker.selectedIcon = modelData
|
|
onDoubleClicked: {
|
|
iconPicker.selectedIcon = modelData
|
|
iconInput.text = iconPicker.selectedIcon
|
|
iconPicker.close()
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: Style.marginS * scaling
|
|
spacing: Style.marginS * scaling
|
|
Item {
|
|
Layout.fillHeight: true
|
|
Layout.preferredHeight: 4 * scaling
|
|
}
|
|
NIcon {
|
|
Layout.alignment: Qt.AlignHCenter
|
|
icon: modelData
|
|
font.pointSize: 42 * scaling
|
|
}
|
|
NText {
|
|
Layout.alignment: Qt.AlignHCenter
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: Style.marginXS * scaling
|
|
elide: Text.ElideRight
|
|
wrapMode: Text.NoWrap
|
|
maximumLineCount: 1
|
|
horizontalAlignment: Text.AlignHCenter
|
|
color: Color.mOnSurfaceVariant
|
|
font.pointSize: Style.fontSizeXS * scaling
|
|
text: modelData
|
|
}
|
|
Item {
|
|
Layout.fillHeight: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: Style.marginM * scaling
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
NButton {
|
|
text: "Cancel"
|
|
outlined: true
|
|
onClicked: iconPicker.close()
|
|
}
|
|
NButton {
|
|
text: "Apply"
|
|
icon: "check"
|
|
enabled: iconPicker.selectedIcon !== ""
|
|
onClicked: {
|
|
iconInput.text = iconPicker.selectedIcon
|
|
iconPicker.close()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NTextInput {
|
|
id: leftClickExecInput
|
|
Layout.fillWidth: true
|
|
label: "Left Click Command"
|
|
placeholderText: "Enter command to execute (app or custom script)"
|
|
text: widgetData?.leftClickExec || widgetMetadata.leftClickExec
|
|
}
|
|
|
|
NTextInput {
|
|
id: rightClickExecInput
|
|
Layout.fillWidth: true
|
|
label: "Right Click Command"
|
|
placeholderText: "Enter command to execute (app or custom script)"
|
|
text: widgetData?.rightClickExec || widgetMetadata.rightClickExec
|
|
}
|
|
|
|
NTextInput {
|
|
id: middleClickExecInput
|
|
Layout.fillWidth: true
|
|
label: "Middle Click Command"
|
|
placeholderText: "Enter command to execute (app or custom script)"
|
|
text: widgetData.middleClickExec || widgetMetadata.middleClickExec
|
|
}
|
|
|
|
NDivider {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
NText {
|
|
text: "Dynamic Text"
|
|
font.pointSize: Style.fontSizeM * scaling
|
|
font.weight: Style.fontWeightBold
|
|
color: Color.mPrimary
|
|
}
|
|
|
|
NTextInput {
|
|
id: textCommandInput
|
|
Layout.fillWidth: true
|
|
label: "Text Command"
|
|
description: "Shell command to run periodically (first line becomes the text)."
|
|
placeholderText: "echo \"Hello World\""
|
|
text: widgetData?.textCommand || widgetMetadata.textCommand
|
|
}
|
|
|
|
NTextInput {
|
|
id: textIntervalInput
|
|
Layout.fillWidth: true
|
|
label: "Refresh Interval"
|
|
description: "Interval in milliseconds."
|
|
placeholderText: String(widgetMetadata.textIntervalMs || 3000)
|
|
text: widgetData && widgetData.textIntervalMs !== undefined ? String(widgetData.textIntervalMs) : ""
|
|
}
|
|
}
|