Files
2026-07-21 14:34:39 +03:00

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
}
}