200 lines
5.9 KiB
QML
200 lines
5.9 KiB
QML
import QtQuick 2.12
|
|
import QtQuick.Window 2.12
|
|
import QtQuick.Controls 2.12
|
|
import QtQuick.Layouts 1.12
|
|
import QtGraphicalEffects 1.12
|
|
import QtQuick.VirtualKeyboard 2.4
|
|
|
|
Window {
|
|
id: root
|
|
visible: true
|
|
width: 480
|
|
height: 480
|
|
title: "ButtonTask"
|
|
color: "black"
|
|
visibility: Window.FullScreen
|
|
|
|
property bool darkMode: true
|
|
|
|
BackgroundLayer {
|
|
id: bg
|
|
anchors.fill: parent
|
|
}
|
|
|
|
// Main content area
|
|
Item {
|
|
id: content
|
|
anchors.fill: parent
|
|
anchors.margins: 10
|
|
|
|
Loader {
|
|
id: viewLoader
|
|
anchors.fill: parent
|
|
sourceComponent: settingsContainer.layoutMode === "list" ? listComp : gridComp
|
|
}
|
|
|
|
Component {
|
|
id: gridComp
|
|
Item {
|
|
id: gridRoot
|
|
anchors.fill: parent
|
|
|
|
readonly property int gridColumns: Math.max(1, settingsContainer.layoutColumns)
|
|
readonly property real cellSide: Math.max(64, width / gridColumns)
|
|
readonly property int gridRows: buttonsModel.count === 0
|
|
? 0
|
|
: Math.ceil(buttonsModel.count / gridColumns)
|
|
readonly property real gridContentHeight: gridRows * cellSide
|
|
readonly property bool gridFits: gridContentHeight > 0
|
|
&& gridContentHeight <= height
|
|
|
|
GridView {
|
|
id: gridView
|
|
width: gridRoot.width
|
|
height: gridRoot.gridFits ? gridRoot.gridContentHeight : gridRoot.height
|
|
y: gridRoot.gridFits ? (gridRoot.height - gridRoot.gridContentHeight) / 2 : 0
|
|
|
|
cellWidth: gridRoot.cellSide
|
|
cellHeight: gridRoot.cellSide
|
|
model: buttonsModel
|
|
clip: true
|
|
interactive: !gridRoot.gridFits
|
|
boundsBehavior: Flickable.StopAtBounds
|
|
|
|
delegate: ButtonDelegate {
|
|
width: gridView.cellWidth - settingsContainer.layoutSpacing
|
|
height: gridView.cellHeight - settingsContainer.layoutSpacing
|
|
showLabel: settingsContainer.showLabels
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: listComp
|
|
SwipeView {
|
|
id: swipeView
|
|
anchors.fill: parent
|
|
clip: true
|
|
interactive: buttonsModel.count > 1
|
|
|
|
Repeater {
|
|
model: buttonsModel
|
|
Item {
|
|
// Each page must match SwipeView size — anchors.fill stacks all pages.
|
|
width: swipeView.width
|
|
height: swipeView.height
|
|
|
|
ButtonDelegate {
|
|
anchors.centerIn: parent
|
|
width: Math.min(parent.width, parent.height) * 0.8
|
|
height: width
|
|
showLabel: settingsContainer.showLabels
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
anchors.centerIn: parent
|
|
visible: buttonsModel.count === 0
|
|
text: "Нет кнопок.\nОткройте настройки и добавьте кнопку."
|
|
color: root.darkMode ? "#cccccc" : "#222222"
|
|
font.pixelSize: 18
|
|
horizontalAlignment: Text.AlignHCenter
|
|
}
|
|
}
|
|
|
|
// Settings gear (top-right)
|
|
Rectangle {
|
|
id: settingsBtn
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.margins: 8
|
|
width: Math.max(40, parent.width / 14)
|
|
height: width
|
|
color: "transparent"
|
|
opacity: 0.85
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: width / 2
|
|
color: root.darkMode ? "#40ffffff" : "#40000000"
|
|
}
|
|
|
|
Text {
|
|
anchors.centerIn: parent
|
|
text: "\u2699"
|
|
font.pixelSize: parent.width * 0.6
|
|
color: root.darkMode ? "white" : "black"
|
|
}
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: passwordDialog.open()
|
|
}
|
|
}
|
|
|
|
// Password dialog
|
|
Dialog {
|
|
id: passwordDialog
|
|
modal: true
|
|
title: "Пароль"
|
|
anchors.centerIn: parent
|
|
width: Math.min(420, parent.width * 0.8)
|
|
closePolicy: Popup.CloseOnEscape
|
|
standardButtons: Dialog.Ok | Dialog.Cancel
|
|
|
|
contentItem: ColumnLayout {
|
|
spacing: 8
|
|
TextField {
|
|
id: pwdField
|
|
Layout.fillWidth: true
|
|
placeholderText: "Введите пароль"
|
|
echoMode: TextInput.Password
|
|
onAccepted: passwordDialog.accept()
|
|
}
|
|
Text {
|
|
id: wrongPwd
|
|
Layout.fillWidth: true
|
|
visible: false
|
|
color: "red"
|
|
text: "Неверный пароль"
|
|
}
|
|
}
|
|
|
|
onOpened: {
|
|
pwdField.text = ""
|
|
wrongPwd.visible = false
|
|
pwdField.forceActiveFocus()
|
|
}
|
|
onAccepted: {
|
|
if (btnController.checkPassword(pwdField.text)) {
|
|
wrongPwd.visible = false
|
|
pwdField.text = ""
|
|
settingsDialog.open()
|
|
} else {
|
|
wrongPwd.visible = true
|
|
Qt.callLater(passwordDialog.open)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Settings dialog (single instance)
|
|
SettingsDialog {
|
|
id: settingsDialog
|
|
}
|
|
|
|
// Virtual keyboard — parented to Overlay so it's above dialogs
|
|
InputPanel {
|
|
id: inputPanel
|
|
parent: Overlay.overlay
|
|
z: 999
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
visible: active
|
|
}
|
|
}
|