Files
Button/qml/settings/ButtonEditorDialog.qml
T

337 lines
12 KiB
QML

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import "../components"
Dialog {
id: editorDialog
modal: true
parent: Overlay.overlay
title: editId === "" ? "Новая кнопка" : "Редактирование"
anchors.centerIn: parent
width: Math.min(520, parent ? parent.width * 0.95 : 520)
height: Math.min(720, parent ? parent.height * 0.92 : 720)
standardButtons: Dialog.Ok | Dialog.Cancel
readonly property color panelBg: "#161628"
readonly property color panelFg: "#ffffff"
readonly property color controlBg: "#2a2a40"
readonly property bool isVoice: kindCombo.currentIndex === 1
palette.button: controlBg
palette.buttonText: panelFg
palette.window: panelBg
palette.windowText: panelFg
palette.text: panelFg
palette.base: "#222236"
palette.highlight: "#4a4a70"
palette.highlightedText: panelFg
background: Rectangle {
color: panelBg
radius: 4
}
property string editId: ""
property bool responseCheckWasEnabled: false
function openForCreate() {
editId = ""
labelF.text = ""
urlF.text = ""
successF.text = ""
errorF.text = "Ошибка"
pendingF.text = "..."
colorF.text = "#7b007b"
colorPicker.hex = "#7b007b"
iconCombo.model = btnController.listIcons()
iconCombo.currentIndex = 0
typeCombo.currentIndex = 0
kindCombo.currentIndex = 0
holdSwitch.checked = true
holdSlider.value = 800
latchSwitch.checked = true
resetUrlF.text = ""
successMatchF.text = "OK"
fireAndForgetSwitch.checked = false
responseCheckSwitch.checked = false
responseCheckWasEnabled = false
cancelUrlF.text = ""
sourceIdF.text = "panel-01"
apiKeyF.text = ""
open()
}
function openForEdit(o) {
editId = o.btnId
labelF.text = o.label
urlF.text = o.actionUrl
successF.text = o.successText
errorF.text = o.errorText
pendingF.text = o.pendingText || "..."
colorF.text = o.btnColor || "#7b007b"
colorPicker.hex = o.btnColor || "#7b007b"
iconCombo.model = btnController.listIcons()
var ip = o.iconPath || ""
var fname = ip
var slash = ip.lastIndexOf("/")
if (slash >= 0) fname = ip.substring(slash + 1)
var idx = iconCombo.model.indexOf(fname)
iconCombo.currentIndex = idx >= 0 ? idx : 0
typeCombo.currentIndex = (o.actionType === "http_post") ? 1 : 0
kindCombo.currentIndex = (o.kind === "voice") ? 1 : 0
holdSwitch.checked = (o.triggerMode !== "click")
holdSlider.value = (o.holdMs && o.holdMs > 0) ? o.holdMs : 800
latchSwitch.checked = !!o.latchResetEnabled
resetUrlF.text = o.latchResetUrl || ""
successMatchF.text = o.latchSuccessMatch || "OK"
fireAndForgetSwitch.checked = !!o.latchFireAndForget
responseCheckSwitch.checked = !!o.responseCheckEnabled
responseCheckWasEnabled = responseCheckSwitch.checked
cancelUrlF.text = o.voiceCancelUrl || ""
sourceIdF.text = o.voiceSourceId || "panel-01"
apiKeyF.text = o.apiKey || ""
open()
}
contentItem: ScrollView {
id: scroll
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout {
width: scroll.availableWidth
spacing: 6
TextField {
id: labelF
Layout.fillWidth: true
placeholderText: "Подпись"
}
RowLayout {
Layout.fillWidth: true
Text { text: "Тип:"; color: editorDialog.panelFg }
ComboBox {
id: kindCombo
Layout.fillWidth: true
model: ["Нажатие", "Голос (запись)"]
}
}
RowLayout {
Layout.fillWidth: true
Text { text: "Иконка:"; color: editorDialog.panelFg }
ComboBox {
id: iconCombo
Layout.fillWidth: true
model: btnController.listIcons()
}
Button {
text: "\u21BB"
onClicked: iconCombo.model = btnController.listIcons()
}
}
RowLayout {
Layout.fillWidth: true
visible: !editorDialog.isVoice
Text { text: "Метод:"; color: editorDialog.panelFg }
ComboBox {
id: typeCombo
model: ["http_get", "http_post"]
}
}
TextField {
id: urlF
Layout.fillWidth: true
placeholderText: editorDialog.isVoice ? "URL classify-audio" : "URL"
}
ColumnLayout {
Layout.fillWidth: true
spacing: 6
visible: editorDialog.isVoice
TextField {
id: cancelUrlF
Layout.fillWidth: true
placeholderText: "URL отмены (cancel)"
}
TextField {
id: sourceIdF
Layout.fillWidth: true
placeholderText: "source_id устройства"
}
TextField {
id: apiKeyF
Layout.fillWidth: true
placeholderText: "X-API-Key"
echoMode: TextInput.Password
}
Text {
Layout.fillWidth: true
text: "Удержание: запись пока зажата. Клик: старт/стоп записи. Повторное нажатие на горящей кнопке — отмена."
color: "#aaaaaa"
font.pixelSize: 10
wrapMode: Text.WordWrap
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 6
visible: !editorDialog.isVoice
RowLayout {
Layout.fillWidth: true
Text { text: "Сброс повторным нажатием:"; color: editorDialog.panelFg }
Switch { id: latchSwitch; checked: true }
}
Text {
Layout.fillWidth: true
visible: latchSwitch.checked
text: "Первое нажатие — URL выше. Успех, если в ответе есть указанный текст или HTTP < 400. Зелёный статус держится до повторного нажатия."
color: "#aaaaaa"
font.pixelSize: 10
wrapMode: Text.WordWrap
}
TextField {
id: resetUrlF
Layout.fillWidth: true
visible: latchSwitch.checked
placeholderText: "URL сброса"
}
TextField {
id: successMatchF
Layout.fillWidth: true
visible: latchSwitch.checked
placeholderText: "Успех если в ответе (OK)"
}
RowLayout {
Layout.fillWidth: true
visible: latchSwitch.checked
Text {
text: "Мгновенный отклик:"
color: editorDialog.panelFg
Layout.fillWidth: true
wrapMode: Text.WordWrap
}
Switch { id: fireAndForgetSwitch }
}
Text {
Layout.fillWidth: true
visible: latchSwitch.checked && fireAndForgetSwitch.checked
text: "Статус обновляется сразу после нажатия; команда на сервер уходит параллельно."
color: "#aaaaaa"
font.pixelSize: 10
wrapMode: Text.WordWrap
}
}
TextField {
id: successF
Layout.fillWidth: true
placeholderText: editorDialog.isVoice ? "Текст успеха (пусто = категория)" : "Текст успеха"
}
TextField {
id: errorF
Layout.fillWidth: true
placeholderText: "Текст ошибки"
}
TextField {
id: pendingF
Layout.fillWidth: true
placeholderText: editorDialog.isVoice ? "Текст записи (Слушаю...)" : "Текст ожидания"
}
RowLayout {
Layout.fillWidth: true
ColorPickerField {
id: colorPicker
label: "Цвет:"
onColorChanged: colorF.text = hex
}
TextField {
id: colorF
visible: false
}
}
RowLayout {
Layout.fillWidth: true
Text {
text: editorDialog.isVoice ? "Жест записи:" : "Срабатывание:"
color: editorDialog.panelFg
}
Switch {
id: holdSwitch
checked: true
}
Text {
text: holdSwitch.checked
? (editorDialog.isVoice ? "Удержание + речь" : "Удержание")
: (editorDialog.isVoice ? "Клик старт/стоп" : "Клик")
color: "#cccccc"
}
Item { Layout.fillWidth: true }
}
RowLayout {
Layout.fillWidth: true
visible: holdSwitch.checked && !editorDialog.isVoice
Text {
text: "Длительность: " + Math.round(holdSlider.value) + " мс"
color: editorDialog.panelFg
Layout.preferredWidth: 180
}
Slider {
id: holdSlider
Layout.fillWidth: true
from: 200; to: 3000; stepSize: 50
value: 800
}
}
RowLayout {
Layout.fillWidth: true
visible: !editorDialog.isVoice && !latchSwitch.checked
Text { text: "Расширенная проверка:"; color: editorDialog.panelFg }
Switch { id: responseCheckSwitch }
Text {
Layout.fillWidth: true
text: "Правила JSON — в веб-конфигураторе"
color: "#cccccc"
font.pixelSize: 11
wrapMode: Text.WordWrap
}
}
}
}
onAccepted: {
var mode = holdSwitch.checked ? "hold" : "click"
var hold = Math.round(holdSlider.value)
var kind = editorDialog.isVoice ? "voice" : "press"
var latchOn = !editorDialog.isVoice && latchSwitch.checked
var resetUrl = resetUrlF.text.trim()
var successMatch = successMatchF.text.trim() || "OK"
var fireAndForget = latchOn && fireAndForgetSwitch.checked
var cancelUrl = cancelUrlF.text.trim()
var sourceId = sourceIdF.text.trim() || "panel-01"
var apiKey = apiKeyF.text.trim()
var actionType = editorDialog.isVoice ? "http_post" : typeCombo.currentText
if (editId === "") {
btnController.addButton(labelF.text, iconCombo.currentText,
actionType, urlF.text,
successF.text, errorF.text, pendingF.text,
colorF.text, mode, hold,
latchOn, resetUrl, successMatch, fireAndForget,
kind, cancelUrl, sourceId, 30000, apiKey)
} else {
btnController.updateButton(editId, labelF.text, iconCombo.currentText,
actionType, urlF.text,
successF.text, errorF.text, pendingF.text,
colorF.text, mode, hold,
latchOn, resetUrl, successMatch, fireAndForget,
kind, cancelUrl, sourceId, 30000, apiKey)
if (!latchOn && !editorDialog.isVoice
&& responseCheckSwitch.checked !== responseCheckWasEnabled)
btnController.setResponseCheckEnabled(editId, responseCheckSwitch.checked)
}
}
}