Files
sddm-theme/themes/sm1tee/components/MenuArea.qml
Ваше Имя ed9ba99412 update
2025-06-30 23:19:29 +03:00

575 lines
20 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.VirtualKeyboard.Settings
Item {
id: menuArea
anchors.fill: parent
Component {
id: sessionMenuComponent
IconButton {
id: sessionButton
property bool showLabel: Config.sessionDisplaySessionName
preferredWidth: showLabel ? (Config.sessionButtonWidth === -1 ? undefined : Config.sessionButtonWidth) : Config.menuAreaButtonsSize
height: Config.menuAreaButtonsSize
iconSize: Config.sessionIconSize
fontSize: Config.sessionFontSize
enabled: loginScreen.state === "normal" || popup.visible
active: popup.visible
contentColor: Config.sessionContentColor
activeContentColor: Config.sessionActiveContentColor
borderRadius: Config.menuAreaButtonsBorderRadius
borderSize: Config.sessionBorderSize
backgroundColor: Config.sessionBackgroundColor
backgroundOpacity: Config.sessionBackgroundOpacity
activeBackgroundColor: Config.sessionBackgroundColor
activeBackgroundOpacity: Config.sessionActiveBackgroundOpacity
fontFamily: Config.menuAreaButtonsFontFamily
activeFocusOnTab: true
focus: false
onClicked: {
if (loginScreen.isSelectingUser) {
loginScreen.isSelectingUser = false;
} else {
popup.open();
}
}
tooltipText: "Change session"
Popup {
id: popup
parent: sessionButton
padding: Config.menuAreaPopupsPadding
z: 1000
background: Rectangle {
color: Config.menuAreaPopupsBackgroundColor
opacity: Config.menuAreaPopupsBackgroundOpacity
radius: Config.menuAreaButtonsBorderRadius
Rectangle {
anchors.fill: parent
visible: Config.menuAreaPopupsBorderSize > 0
radius: parent.radius
color: "transparent"
border {
color: Config.menuAreaPopupsBorderColor
width: Config.menuAreaPopupsBorderSize
}
}
}
dim: true
Overlay.modal: Rectangle {
color: "transparent"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: function (event) {
popup.close();
event.accepted = true;
}
}
}
onOpened: {
loginScreen.safeStateChange("popup");
[x, y] = menuArea.calculatePopupPos(Config.sessionPopupDirection, Config.sessionPopupAlign, popup, sessionButton);
}
onClosed: loginScreen.safeStateChange("normal")
modal: true
popupType: Popup.Item
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
focus: visible
SessionSelector {
focus: popup.focus
onSessionChanged: function (newSessionIndex, sessionIcon, sessionLabel) {
loginScreen.sessionIndex = newSessionIndex;
sessionButton.icon = sessionIcon;
sessionButton.label = sessionButton.showLabel ? sessionLabel : "";
}
onClose: {
popup.close();
}
}
}
}
}
Component {
id: layoutMenuComponent
IconButton {
id: layoutButton
property bool showLabel: Config.layoutDisplayLayoutName
height: Config.menuAreaButtonsSize
icon: Config.getIcon(Config.layoutIcon)
active: popup.visible
borderRadius: Config.menuAreaButtonsBorderRadius
borderSize: Config.layoutBorderSize
iconSize: Config.layoutIconSize
fontSize: Config.layoutFontSize
backgroundColor: Config.layoutBackgroundColor
backgroundOpacity: Config.layoutBackgroundOpacity
activeBackgroundColor: Config.layoutBackgroundColor
activeBackgroundOpacity: Config.layoutActiveBackgroundOpacity
contentColor: Config.layoutContentColor
activeContentColor: Config.layoutActiveContentColor
fontFamily: Config.menuAreaButtonsFontFamily
activeFocusOnTab: true
enabled: loginScreen.state === "normal" || popup.visible
focus: false
onClicked: {
if (loginScreen.isSelectingUser) {
loginScreen.isSelectingUser = false;
} else {
if (keyboard && keyboard.layouts) {
console.log("Available layouts:", keyboard.layouts.length);
for (var i = 0; i < keyboard.layouts.length; i++) {
console.log("Layout", i, ":", keyboard.layouts[i].shortName, keyboard.layouts[i].longName);
}
}
popup.open();
}
}
tooltipText: "Change keyboard layout"
label: {
if (!showLabel) return "";
if (!keyboard || !keyboard.layouts || keyboard.layouts.length === 0) return "";
if (keyboard.currentLayout < 0 || keyboard.currentLayout >= keyboard.layouts.length) return "";
return keyboard.layouts[keyboard.currentLayout].shortName.toUpperCase();
}
Connections {
target: loginScreen
function onToggleLayoutPopup() {
if (popup.visible) {
popup.close();
} else {
popup.open();
}
}
}
Component.onDestruction: {
if (typeof connections !== 'undefined') {
connections.target = null;
}
}
Popup {
id: popup
parent: layoutButton
padding: Config.menuAreaPopupsPadding
z: 1000
background: Rectangle {
color: Config.menuAreaPopupsBackgroundColor
opacity: Config.menuAreaPopupsBackgroundOpacity
radius: Config.menuAreaButtonsBorderRadius
Rectangle {
anchors.fill: parent
visible: Config.menuAreaPopupsBorderSize > 0
radius: parent.radius
color: "transparent"
border {
color: Config.menuAreaPopupsBorderColor
width: Config.menuAreaPopupsBorderSize
}
}
}
focus: visible
dim: true
Overlay.modal: Rectangle {
color: "transparent"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: function (event) {
popup.close();
event.accepted = true;
}
}
}
onOpened: {
loginScreen.safeStateChange("popup");
if (layoutSelector) {
layoutSelector.forceUpdate();
}
[x, y] = menuArea.calculatePopupPos(Config.layoutPopupDirection, Config.layoutPopupAlign, popup, layoutButton);
}
onImplicitHeightChanged: {
if (visible) {
[x, y] = menuArea.calculatePopupPos(Config.layoutPopupDirection, Config.layoutPopupAlign, popup, layoutButton);
}
}
onClosed: loginScreen.safeStateChange("normal")
modal: true
popupType: Popup.Item
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
LayoutSelector {
id: layoutSelector
focus: popup.focus
onLayoutChanged: function (index) {
if (keyboard && keyboard.layouts && index >= 0 && index < keyboard.layouts.length) {
layoutButton.label = showLabel ? keyboard.layouts[index].shortName.toUpperCase() : "";
VirtualKeyboardSettings.locale = Languages.getKBCodeFor(keyboard.layouts[index].shortName);
}
}
onClose: {
popup.close();
}
}
}
}
}
Component {
id: keyboardMenuComponent
IconButton {
id: keyboardButton
height: Config.menuAreaButtonsSize
width: Config.menuAreaButtonsSize
icon: Config.getIcon(Config.keyboardIcon)
iconSize: Config.keyboardIconSize
backgroundColor: Config.keyboardBackgroundColor
backgroundOpacity: Config.keyboardBackgroundOpacity
activeBackgroundColor: Config.keyboardBackgroundColor
activeBackgroundOpacity: Config.keyboardActiveBackgroundOpacity
contentColor: Config.keyboardContentColor
activeContentColor: Config.keyboardActiveContentColor
active: showKeyboard
fontFamily: Config.menuAreaButtonsFontFamily
borderRadius: Config.menuAreaButtonsBorderRadius
borderSize: Config.keyboardBorderSize
enabled: loginScreen.showKeyboard || loginScreen.state === "normal"
activeFocusOnTab: true
focus: false
onClicked: {
loginScreen.showKeyboard = !loginScreen.showKeyboard;
}
tooltipText: "Toggle virtual keyboard"
}
}
Component {
id: powerMenuComponent
IconButton {
id: powerButton
height: Config.menuAreaButtonsSize
width: Config.menuAreaButtonsSize
icon: Config.getIcon(Config.powerIcon)
iconSize: Config.powerIconSize
contentColor: Config.powerContentColor
activeContentColor: Config.powerActiveContentColor
fontFamily: Config.menuAreaButtonsFontFamily
active: popup.visible
borderRadius: Config.menuAreaButtonsBorderRadius
borderSize: Config.powerBorderSize
backgroundColor: Config.powerBackgroundColor
backgroundOpacity: Config.powerBackgroundOpacity
activeBackgroundColor: Config.powerBackgroundColor
activeBackgroundOpacity: Config.powerActiveBackgroundOpacity
enabled: loginScreen.state === "normal" || popup.visible
activeFocusOnTab: true
focus: false
onClicked: {
popup.open();
}
tooltipText: "Power options"
Popup {
id: popup
parent: powerButton
z: 1000
background: Rectangle {
color: Config.menuAreaPopupsBackgroundColor
opacity: Config.menuAreaPopupsBackgroundOpacity
radius: Config.menuAreaButtonsBorderRadius
Rectangle {
anchors.fill: parent
visible: Config.menuAreaPopupsBorderSize > 0
radius: parent.radius
color: "transparent"
border {
color: Config.menuAreaPopupsBorderColor
width: Config.menuAreaPopupsBorderSize
}
}
}
dim: true
padding: Config.menuAreaPopupsPadding
Overlay.modal: Rectangle {
color: "transparent"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: function (event) {
popup.close();
event.accepted = true;
}
}
}
onOpened: {
loginScreen.safeStateChange("popup");
[x, y] = menuArea.calculatePopupPos(Config.powerPopupDirection, Config.powerPopupAlign, popup, powerButton);
}
onClosed: loginScreen.safeStateChange("normal")
modal: true
popupType: Popup.Item
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
focus: visible
PowerMenu {
focus: popup.focus
onClose: {
popup.close();
}
}
}
}
}
Row {
// top_left
id: topLeftButtons
height: childrenRect.height
width: childrenRect.width
spacing: Config.menuAreaButtonsSpacing // 10
anchors {
top: parent.top
left: parent.left
topMargin: Config.menuAreaButtonsMarginTop
leftMargin: Config.menuAreaButtonsMarginLeft
}
}
Row {
// top_center
id: topCenterButtons
height: childrenRect.height
width: childrenRect.width
spacing: Config.menuAreaButtonsSpacing // 10
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
topMargin: Config.menuAreaButtonsMarginTop
}
}
Row {
// top_right
id: topRightButtons
height: childrenRect.height
width: childrenRect.width
spacing: Config.menuAreaButtonsSpacing // 10
anchors {
top: parent.top
right: parent.right
topMargin: Config.menuAreaButtonsMarginTop
rightMargin: Config.menuAreaButtonsMarginRight
}
}
Column {
// center_left
id: centerLeftButtons
height: childrenRect.height
width: childrenRect.width
spacing: Config.menuAreaButtonsSpacing // 10
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
leftMargin: Config.menuAreaButtonsMarginLeft
}
}
Column {
// center_right
id: centerRightButtons
height: childrenRect.height
width: childrenRect.width
spacing: Config.menuAreaButtonsSpacing // 10
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: Config.menuAreaButtonsMarginRight
}
}
Row {
// bottom_left
id: bottomLeftButtons
height: childrenRect.height
width: childrenRect.width
spacing: Config.menuAreaButtonsSpacing // 10
anchors {
bottom: parent.bottom
left: parent.left
bottomMargin: Config.menuAreaButtonsMarginBottom
leftMargin: Config.menuAreaButtonsMarginLeft
}
}
Row {
// bottom_center
id: bottomCenterButtons
height: childrenRect.height
width: childrenRect.width
spacing: Config.menuAreaButtonsSpacing // 10
anchors {
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
bottomMargin: Config.menuAreaButtonsMarginBottom
}
}
Row {
// bottom_right
id: bottomRightButtons
height: childrenRect.height
width: childrenRect.width
spacing: Config.menuAreaButtonsSpacing // 10
anchors {
bottom: parent.bottom
right: parent.right
bottomMargin: Config.menuAreaButtonsMarginBottom
rightMargin: Config.menuAreaButtonsMarginRight
}
}
property var createdObjects: []
Component.onCompleted: {
var menus = Config.sortMenuButtons();
for (var i = 0; i < menus.length; i++) {
var pos;
switch (menus[i].position) {
case "top-left":
pos = topLeftButtons;
break;
case "top-center":
pos = topCenterButtons;
break;
case "top-right":
pos = topRightButtons;
break;
case "center-left":
pos = centerLeftButtons;
break;
case "center-right":
pos = centerRightButtons;
break;
case "bottom-left":
pos = bottomLeftButtons;
break;
case "bottom-center":
pos = bottomCenterButtons;
break;
case "bottom-right":
pos = bottomRightButtons;
break;
}
var createdObject;
if (menus[i].name === "session")
createdObject = sessionMenuComponent.createObject(pos, {});
else if (menus[i].name === "layout")
createdObject = layoutMenuComponent.createObject(pos, {});
else if (menus[i].name === "keyboard")
createdObject = keyboardMenuComponent.createObject(pos, {});
else if (menus[i].name === "power")
createdObject = powerMenuComponent.createObject(pos, {});
if (createdObject) {
createdObjects.push(createdObject);
}
}
}
Component.onDestruction: {
for (var i = 0; i < createdObjects.length; i++) {
if (createdObjects[i]) {
createdObjects[i].destroy();
}
}
createdObjects = [];
}
function calculatePopupPos(direction, align, popup, button) {
var popupMargin = Config.menuAreaPopupsMargin;
var x = 0, y = 0;
if (direction === "up") {
y = -popup.height - popupMargin;
if (align === "start") {
x = 0;
} else if (align === "end") {
x = -popup.width + button.width;
} else {
x = (button.width - popup.width) / 2;
}
} else if (direction === "down") {
y = button.height + popupMargin;
if (align === "start") {
x = 0;
} else if (align === "end") {
x = -popup.width + button.width;
} else {
x = (button.width - popup.width) / 2;
}
} else if (direction === "left") {
x = -popup.width - popupMargin;
if (align === "start") {
y = 0;
} else if (align === "end") {
y = -popup.height + button.height;
} else {
y = (button.height - popup.height) / 2;
}
} else {
x = button.width + popupMargin;
if (align === "start") {
y = 0;
} else if (align === "end") {
y = -popup.height + button.height;
} else {
y = (button.height - popup.height) / 2;
}
}
return [x, y];
}
}