SessionMenuTab: add setting for large button layout

This commit is contained in:
Ly-sec
2025-12-16 20:10:28 +01:00
parent d4f39c6b75
commit 762e828382
16 changed files with 449 additions and 119 deletions
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Verfügbare Parameter"
}
},
"screen-lock": {
"description": "Befehl, der ausgeführt wird, wenn der Bildschirm gesperrt wird.",
"label": "Bildschirm gesperrt",
"placeholder": "z.B. notify-send \"Bildschirm\" \"Gesperrt\""
},
"screen-unlock": {
"description": "Befehl, der ausgeführt wird, wenn der Bildschirm entsperrt wird.",
"label": "Bildschirm entsperrt",
"placeholder": "z.B. notify-send \"Bildschirm\" \"Entsperrt\""
},
"system-hooks": {
"enable": {
"description": "Alle Hook-Befehle aktivieren oder deaktivieren.",
@@ -1642,16 +1652,6 @@
"description": "Befehl, der ausgeführt wird, wenn sich das Hintergrundbild ändert.",
"label": "Hintergrundbild geändert",
"placeholder": "z.B. notify-send \"Hintergrundbild\" \"Geändert\""
},
"screen-lock": {
"description": "Befehl, der ausgeführt wird, wenn der Bildschirm gesperrt wird.",
"label": "Bildschirm gesperrt",
"placeholder": "z.B. notify-send \"Bildschirm\" \"Gesperrt\""
},
"screen-unlock": {
"description": "Befehl, der ausgeführt wird, wenn der Bildschirm entsperrt wird.",
"label": "Bildschirm entsperrt",
"placeholder": "z.B. notify-send \"Bildschirm\" \"Entsperrt\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "Allgemein"
}
},
"large-buttons-style": {
"description": "Das Sitzungsmenü mit großen Schaltflächen in einem Rasterlayout anzeigen.",
"label": "Stil: Große Schaltflächen"
},
"position": {
"description": "Wählen Sie, wo das Sitzungsmenü-Panel beim Öffnen erscheint.",
"label": "Position"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Available parameters"
}
},
"screen-lock": {
"description": "Command to be executed when the screen is locked.",
"label": "Screen locked",
"placeholder": "e.g., notify-send \"Screen\" \"Locked\""
},
"screen-unlock": {
"description": "Command to be executed when the lock screen is unlocked.",
"label": "Screen unlocked",
"placeholder": "e.g., notify-send \"Screen\" \"Unlocked\""
},
"system-hooks": {
"enable": {
"description": "Enable or disable all hook commands.",
@@ -1642,16 +1652,6 @@
"description": "Command to be executed when wallpaper changes.",
"label": "Wallpaper changed",
"placeholder": "e.g., notify-send \"Wallpaper\" \"Changed\""
},
"screen-lock": {
"description": "Command to be executed when the screen is locked.",
"label": "Screen locked",
"placeholder": "e.g., notify-send \"Screen\" \"Locked\""
},
"screen-unlock": {
"description": "Command to be executed when the lock screen is unlocked.",
"label": "Screen unlocked",
"placeholder": "e.g., notify-send \"Screen\" \"Unlocked\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "General"
}
},
"large-buttons-style": {
"description": "Display the session menu with large buttons in a grid layout.",
"label": "Large buttons style"
},
"position": {
"description": "Choose where the session menu panel appears when opened.",
"label": "Position"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Parámetros disponibles"
}
},
"screen-lock": {
"description": "Comando a ejecutar cuando se bloquea la pantalla.",
"label": "Pantalla bloqueada",
"placeholder": "ej., notify-send \"Pantalla\" \"Bloqueada\""
},
"screen-unlock": {
"description": "Comando a ejecutar cuando se desbloquea la pantalla.",
"label": "Pantalla desbloqueada",
"placeholder": "ej., notify-send \"Pantalla\" \"Desbloqueada\""
},
"system-hooks": {
"enable": {
"description": "Activa o desactiva todos los comandos de hooks.",
@@ -1642,16 +1652,6 @@
"description": "Comando a ejecutar cuando cambia el fondo de pantalla.",
"label": "Fondo de pantalla cambiado",
"placeholder": "ej., notify-send \"Fondo de pantalla\" \"Cambiado\""
},
"screen-lock": {
"description": "Comando a ejecutar cuando se bloquea la pantalla.",
"label": "Pantalla bloqueada",
"placeholder": "ej., notify-send \"Pantalla\" \"Bloqueada\""
},
"screen-unlock": {
"description": "Comando a ejecutar cuando se desbloquea la pantalla.",
"label": "Pantalla desbloqueada",
"placeholder": "ej., notify-send \"Pantalla\" \"Desbloqueada\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "General"
}
},
"large-buttons-style": {
"description": "Mostrar el menú de sesión con botones grandes en un diseño de cuadrícula.",
"label": "Estilo de botones grandes"
},
"position": {
"description": "Elige dónde aparece el panel del Menú de sesión cuando se abre.",
"label": "Posición"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Paramètres disponibles"
}
},
"screen-lock": {
"description": "Commande à exécuter lorsque l'écran est verrouillé.",
"label": "Écran verrouillé",
"placeholder": "ex: notify-send \"Écran\" \"Verrouillé\""
},
"screen-unlock": {
"description": "Commande à exécuter lorsque l'écran est déverrouillé.",
"label": "Écran déverrouillé",
"placeholder": "ex: notify-send \"Écran\" \"Déverrouillé\""
},
"system-hooks": {
"enable": {
"description": "Activer ou désactiver toutes les commandes de hook.",
@@ -1642,16 +1652,6 @@
"description": "Commande à exécuter lorsque le fond d'écran change.",
"label": "Fond d'écran changé",
"placeholder": "ex: notify-send \"Fond d'écran\" \"Changé\""
},
"screen-lock": {
"description": "Commande à exécuter lorsque l'écran est verrouillé.",
"label": "Écran verrouillé",
"placeholder": "ex: notify-send \"Écran\" \"Verrouillé\""
},
"screen-unlock": {
"description": "Commande à exécuter lorsque l'écran est déverrouillé.",
"label": "Écran déverrouillé",
"placeholder": "ex: notify-send \"Écran\" \"Déverrouillé\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "Général"
}
},
"large-buttons-style": {
"description": "Afficher le menu de session avec de grands boutons dans une disposition en grille.",
"label": "Style boutons larges"
},
"position": {
"description": "Choisissez où le panneau du Menu de session apparaît lorsqu'il est ouvert.",
"label": "Position"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "利用可能なパラメータ(引数)"
}
},
"screen-lock": {
"description": "画面がロックされた際に実行されるコマンド。",
"label": "画面ロック時",
"placeholder": "例: notify-send \"Screen\" \"Locked\""
},
"screen-unlock": {
"description": "ロック画面が解除された際に実行されるコマンド。",
"label": "画面ロック解除時",
"placeholder": "例: notify-send \"Screen\" \"Unlocked\""
},
"system-hooks": {
"enable": {
"description": "すべてのフックコマンドの有効・無効を切り替えます。",
@@ -1642,16 +1652,6 @@
"description": "壁紙が変更された際に実行されるコマンド。",
"label": "壁紙変更時",
"placeholder": "例: notify-send \"Wallpaper\" \"Changed\""
},
"screen-lock": {
"description": "画面がロックされた際に実行されるコマンド。",
"label": "画面ロック時",
"placeholder": "例: notify-send \"Screen\" \"Locked\""
},
"screen-unlock": {
"description": "ロック画面が解除された際に実行されるコマンド。",
"label": "画面ロック解除時",
"placeholder": "例: notify-send \"Screen\" \"Unlocked\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "一般"
}
},
"large-buttons-style": {
"description": "セッションメニューを大きなボタンでグリッドレイアウトで表示する。",
"label": "大きなボタンのスタイル"
},
"position": {
"description": "セッションメニューパネルの表示位置を選択します。",
"label": "表示位置"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Beschikbare parameters"
}
},
"screen-lock": {
"description": "Commando dat wordt uitgevoerd wanneer het scherm wordt vergrendeld.",
"label": "Scherm vergrendeld",
"placeholder": "bijv. notify-send \"Scherm\" \"Vergrendeld\""
},
"screen-unlock": {
"description": "Commando dat wordt uitgevoerd wanneer het scherm wordt ontgrendeld.",
"label": "Scherm ontgrendeld",
"placeholder": "bijv. notify-send \"Scherm\" \"Ontgrendeld\""
},
"system-hooks": {
"enable": {
"description": "Schakel alle hook-commando's in of uit.",
@@ -1642,16 +1652,6 @@
"description": "Commando dat wordt uitgevoerd wanneer de achtergrond verandert.",
"label": "Achtergrond gewijzigd",
"placeholder": "bijv. notify-send \"Achtergrond\" \"Gewijzigd\""
},
"screen-lock": {
"description": "Commando dat wordt uitgevoerd wanneer het scherm wordt vergrendeld.",
"label": "Scherm vergrendeld",
"placeholder": "bijv. notify-send \"Scherm\" \"Vergrendeld\""
},
"screen-unlock": {
"description": "Commando dat wordt uitgevoerd wanneer het scherm wordt ontgrendeld.",
"label": "Scherm ontgrendeld",
"placeholder": "bijv. notify-send \"Scherm\" \"Ontgrendeld\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "Algemeen"
}
},
"large-buttons-style": {
"description": "Toon het sessiemenu met grote knoppen in een rasterindeling.",
"label": "Stijl met grote knoppen"
},
"position": {
"description": "Kies waar het Sessiemenu-paneel verschijnt wanneer het wordt geopend.",
"label": "Positie"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Parâmetros Disponíveis"
}
},
"screen-lock": {
"description": "Comando a ser executado quando a tela é bloqueada.",
"label": "Tela bloqueada",
"placeholder": "ex., notify-send \"Tela\" \"Bloqueada\""
},
"screen-unlock": {
"description": "Comando a ser executado quando a tela é desbloqueada.",
"label": "Tela desbloqueada",
"placeholder": "ex., notify-send \"Tela\" \"Desbloqueada\""
},
"system-hooks": {
"enable": {
"description": "Ativa ou desativa todos os comandos de hook.",
@@ -1642,16 +1652,6 @@
"description": "Comando a ser executado quando o papel de parede muda.",
"label": "Papel de parede alterado",
"placeholder": "ex., notify-send \"Papel de parede\" \"Alterado\""
},
"screen-lock": {
"description": "Comando a ser executado quando a tela é bloqueada.",
"label": "Tela bloqueada",
"placeholder": "ex., notify-send \"Tela\" \"Bloqueada\""
},
"screen-unlock": {
"description": "Comando a ser executado quando a tela é desbloqueada.",
"label": "Tela desbloqueada",
"placeholder": "ex., notify-send \"Tela\" \"Desbloqueada\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "Geral"
}
},
"large-buttons-style": {
"description": "Exibir o menu de sessão com botões grandes em um layout de grade.",
"label": "Estilo de botões grandes"
},
"position": {
"description": "Escolha onde o painel do Menu de sessão aparece quando aberto.",
"label": "Posição"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Доступные параметры"
}
},
"screen-lock": {
"description": "Команда для выполнения при блокировке экрана.",
"label": "Экран заблокирован",
"placeholder": "например, notify-send \"Экран\" \"Заблокирован\""
},
"screen-unlock": {
"description": "Команда для выполнения при разблокировке экрана.",
"label": "Экран разблокирован",
"placeholder": "например, notify-send \"Экран\" \"Разблокирован\""
},
"system-hooks": {
"enable": {
"description": "Включить или отключить все команды хуков.",
@@ -1642,16 +1652,6 @@
"description": "Команда для выполнения при смене обоев.",
"label": "Обои изменены",
"placeholder": "например, notify-send \"Wallpaper\" \"Changed\""
},
"screen-lock": {
"description": "Команда для выполнения при блокировке экрана.",
"label": "Экран заблокирован",
"placeholder": "например, notify-send \"Экран\" \"Заблокирован\""
},
"screen-unlock": {
"description": "Команда для выполнения при разблокировке экрана.",
"label": "Экран разблокирован",
"placeholder": "например, notify-send \"Экран\" \"Разблокирован\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "Общие"
}
},
"large-buttons-style": {
"description": "Отобразить меню сеанса с большими кнопками в виде сетки.",
"label": "Стиль \"крупные кнопки\""
},
"position": {
"description": "Выберите, где появляется панель меню сеанса при открытии.",
"label": "Позиция"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Kullanılabilir Parametreler"
}
},
"screen-lock": {
"description": "Ekran kilitlendiğinde çalıştırılacak komut.",
"label": "Ekran kilitlendi",
"placeholder": "örn., notify-send \"Ekran\" \"Kilitlendi\""
},
"screen-unlock": {
"description": "Ekran kilidi açıldığında çalıştırılacak komut.",
"label": "Ekran kilidi açıldı",
"placeholder": "örn., notify-send \"Ekran\" \"Açıldı\""
},
"system-hooks": {
"enable": {
"description": "Tüm kanca komutlarını etkinleştirin veya devre dışı bırakın.",
@@ -1642,16 +1652,6 @@
"description": "Duvar kâğıdı değiştiğinde çalıştırılacak komut.",
"label": "Duvar kâğıdı değişti",
"placeholder": "örn., notify-send \"Duvar Kâğıdı\" \"Değişti\""
},
"screen-lock": {
"description": "Ekran kilitlendiğinde çalıştırılacak komut.",
"label": "Ekran kilitlendi",
"placeholder": "örn., notify-send \"Ekran\" \"Kilitlendi\""
},
"screen-unlock": {
"description": "Ekran kilidi açıldığında çalıştırılacak komut.",
"label": "Ekran kilidi açıldı",
"placeholder": "örn., notify-send \"Ekran\" \"Açıldı\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "Genel"
}
},
"large-buttons-style": {
"description": "Oturum menüsünü büyük butonlarla ızgara düzeninde görüntüle.",
"label": "Büyük düğme stili"
},
"position": {
"description": "Oturum Menüsü panelinin açıldığında nerede görüneceğini seçin.",
"label": "Konum"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "Доступні параметри"
}
},
"screen-lock": {
"description": "Команда для виконання при блокуванні екрана.",
"label": "Екран заблоковано",
"placeholder": "напр., notify-send \"Екран\" \"Заблоковано\""
},
"screen-unlock": {
"description": "Команда для виконання при розблокуванні екрана.",
"label": "Екран розблоковано",
"placeholder": "напр., notify-send \"Екран\" \"Розблоковано\""
},
"system-hooks": {
"enable": {
"description": "Увімкнути або вимкнути всі команди хуків.",
@@ -1642,16 +1652,6 @@
"description": "Команда для виконання при зміні шпалер.",
"label": "Шпалери змінено",
"placeholder": "напр., notify-send \"Шпалери\" \"Змінено\""
},
"screen-lock": {
"description": "Команда для виконання при блокуванні екрана.",
"label": "Екран заблоковано",
"placeholder": "напр., notify-send \"Екран\" \"Заблоковано\""
},
"screen-unlock": {
"description": "Команда для виконання при розблокуванні екрана.",
"label": "Екран розблоковано",
"placeholder": "напр., notify-send \"Екран\" \"Розблоковано\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "Загальні"
}
},
"large-buttons-style": {
"description": "Відобразити меню сеансу великими кнопками у вигляді сітки.",
"label": "Стиль великих кнопок"
},
"position": {
"description": "Виберіть, де з'являється панель меню сеансу при відкритті.",
"label": "Позиція"
+14 -10
View File
@@ -1622,6 +1622,16 @@
"label": "可用参数"
}
},
"screen-lock": {
"description": "屏幕锁定时执行的命令。",
"label": "屏幕已锁定",
"placeholder": "例如:notify-send \"屏幕\" \"已锁定\""
},
"screen-unlock": {
"description": "屏幕解锁时执行的命令。",
"label": "屏幕已解锁",
"placeholder": "例如:notify-send \"屏幕\" \"已解锁\""
},
"system-hooks": {
"enable": {
"description": "启用或禁用所有钩子命令。",
@@ -1642,16 +1652,6 @@
"description": "壁纸更改时执行的命令。",
"label": "壁纸已更改",
"placeholder": "例如:notify-send \"壁纸\" \"已更改\""
},
"screen-lock": {
"description": "屏幕锁定时执行的命令。",
"label": "屏幕已锁定",
"placeholder": "例如:notify-send \"屏幕\" \"已锁定\""
},
"screen-unlock": {
"description": "屏幕解锁时执行的命令。",
"label": "屏幕已解锁",
"placeholder": "例如:notify-send \"屏幕\" \"已解锁\""
}
},
"launcher": {
@@ -2172,6 +2172,10 @@
"label": "常规"
}
},
"large-buttons-style": {
"description": "以网格布局显示带有大按钮的会话菜单。",
"label": "大按钮样式"
},
"position": {
"description": "选择会话菜单面板打开时出现的位置。",
"label": "位置"
+1
View File
@@ -282,6 +282,7 @@
"countdownDuration": 10000,
"position": "center",
"showHeader": true,
"largeButtonsStyle": false,
"powerOptions": [
{
"action": "lock",
+1
View File
@@ -477,6 +477,7 @@ Singleton {
property int countdownDuration: 10000
property string position: "center"
property bool showHeader: true
property bool largeButtonsStyle: false
property list<var> powerOptions: [
{
"action": "lock",
@@ -132,7 +132,7 @@ Item {
PanelBackground {
panel: root.windowRoot.sessionMenuPanelPlaceholder
shapeContainer: backgroundsShape
backgroundColor: panelBackgroundColor
backgroundColor: Settings.data.sessionMenu.largeButtonsStyle ? Color.transparent : panelBackgroundColor
}
// Settings
+284 -8
View File
@@ -15,8 +15,17 @@ import qs.Widgets
SmartPanel {
id: root
preferredWidth: Math.round(440 * Style.uiScaleRatio)
readonly property bool largeButtonsStyle: Settings.data.sessionMenu.largeButtonsStyle || false
// Make panel background transparent for large buttons style
panelBackgroundColor: largeButtonsStyle ? Color.transparent : Color.mSurface
preferredWidth: largeButtonsStyle ? 0 : Math.round(440 * Style.uiScaleRatio)
preferredWidthRatio: largeButtonsStyle ? 1.0 : 0
preferredHeight: {
if (largeButtonsStyle) {
return 0; // Use ratio instead
}
var headerHeight = Settings.data.sessionMenu.showHeader ? Style.baseWidgetSize * 0.6 : 0;
var dividerHeight = Settings.data.sessionMenu.showHeader ? Style.marginS : 0;
@@ -30,16 +39,17 @@ SmartPanel {
return Math.round(baseHeight + buttonsHeight);
}
preferredHeightRatio: largeButtonsStyle ? 1.0 : 0
// Positioning
// Positioning - large buttons style is always centered and fullscreen
readonly property string panelPosition: Settings.data.sessionMenu.position
panelAnchorHorizontalCenter: panelPosition === "center" || panelPosition.endsWith("_center")
panelAnchorVerticalCenter: panelPosition === "center"
panelAnchorLeft: panelPosition !== "center" && panelPosition.endsWith("_left")
panelAnchorRight: panelPosition !== "center" && panelPosition.endsWith("_right")
panelAnchorBottom: panelPosition.startsWith("bottom_")
panelAnchorTop: panelPosition.startsWith("top_")
panelAnchorHorizontalCenter: largeButtonsStyle || panelPosition === "center" || panelPosition.endsWith("_center")
panelAnchorVerticalCenter: largeButtonsStyle || panelPosition === "center"
panelAnchorLeft: !largeButtonsStyle && panelPosition !== "center" && panelPosition.endsWith("_left")
panelAnchorRight: !largeButtonsStyle && panelPosition !== "center" && panelPosition.endsWith("_right")
panelAnchorBottom: !largeButtonsStyle && panelPosition.startsWith("bottom_")
panelAnchorTop: !largeButtonsStyle && panelPosition.startsWith("top_")
// SessionMenu handle it's own closing logic
property bool closeWithEscape: false
@@ -339,6 +349,10 @@ SmartPanel {
id: ui
color: Color.transparent
// For large buttons style, use full screen dimensions
readonly property var contentPreferredWidth: largeButtonsStyle ? (root.screen?.width || root.width || 0) : undefined
readonly property var contentPreferredHeight: largeButtonsStyle ? (root.screen?.height || root.height || 0) : undefined
// Navigation functions
function selectFirst() {
root.selectFirst();
@@ -360,7 +374,72 @@ SmartPanel {
root.activate();
}
// Timer text for large buttons style (above buttons) - positioned absolutely with background
Rectangle {
id: timerTextContainer
visible: largeButtonsStyle && timerActive
anchors.bottom: largeButtonsContainer.top
anchors.horizontalCenter: largeButtonsContainer.horizontalCenter
anchors.bottomMargin: Style.marginM
width: timerText.width + Style.marginXL * 2
height: timerText.height + Style.marginL * 2
radius: Style.radiusM
color: Qt.alpha(Color.mSurface, 0.9)
border.color: Color.mOutline
border.width: Style.borderS
z: 1000
NText {
id: timerText
anchors.centerIn: parent
text: I18n.tr("session-menu.action-in-seconds", {
"action": I18n.tr("session-menu." + pendingAction),
"seconds": Math.ceil(timeRemaining / 1000)
})
font.weight: Style.fontWeightBold
pointSize: Style.fontSizeL
color: Color.mOnSurface
}
}
// Large buttons style layout container
ColumnLayout {
id: largeButtonsContainer
visible: largeButtonsStyle
anchors.centerIn: parent
// Large buttons style layout (grid)
GridLayout {
id: largeButtonsGrid
Layout.alignment: Qt.AlignHCenter
columns: Math.min(3, Math.ceil(Math.sqrt(powerOptions.length)))
rowSpacing: Style.marginXL
columnSpacing: Style.marginXL
width: columns * 200 * Style.uiScaleRatio + (columns - 1) * Style.marginXL
height: Math.ceil(powerOptions.length / columns) * 200 * Style.uiScaleRatio + (Math.ceil(powerOptions.length / columns) - 1) * Style.marginXL
Repeater {
model: powerOptions
delegate: LargeButton {
Layout.preferredWidth: 200 * Style.uiScaleRatio
Layout.preferredHeight: 200 * Style.uiScaleRatio
icon: modelData.icon
title: modelData.title
isShutdown: modelData.isShutdown || false
isSelected: index === selectedIndex
onClicked: {
selectedIndex = index;
startTimer(modelData.action);
}
pending: timerActive && pendingAction === modelData.action
}
}
}
}
// Normal style layout
NBox {
visible: !largeButtonsStyle
anchors.fill: parent
anchors.margins: Style.marginL
@@ -437,6 +516,24 @@ SmartPanel {
}
}
}
// Background MouseArea for large buttons style - closes panel when clicking outside buttons
MouseArea {
visible: largeButtonsStyle
anchors.fill: parent
z: -1
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: mouse => {
// Only close if not clicking on a button
// The buttons are above this MouseArea, so clicks on them won't reach here
if (timerActive) {
// Cancel countdown if active
cancelTimer();
} else {
root.close();
}
}
}
}
// Custom power button component
@@ -567,4 +664,183 @@ SmartPanel {
onClicked: buttonRoot.clicked()
}
}
// Large buttons style button component
component LargeButton: Rectangle {
id: largeButtonRoot
property string icon: ""
property string title: ""
property bool pending: false
property bool isShutdown: false
property bool isSelected: false
signal clicked
property real hoverScale: (isSelected || mouseArea.containsMouse) ? 1.05 : 1.0
radius: Style.radiusL
color: {
if (pending) {
return Qt.alpha(Color.mPrimary, 1.0);
}
if (isSelected || mouseArea.containsMouse) {
return Qt.alpha(Color.mPrimary, 1.0);
}
return Qt.alpha(Color.mSurfaceVariant, 0.65);
}
border.width: pending ? Style.borderM : (isSelected || mouseArea.containsMouse ? Style.borderM : 0)
border.color: pending ? Color.mPrimary : (isSelected || mouseArea.containsMouse ? Qt.alpha(Color.mPrimary, 0.5) : Color.transparent)
// Scale transform for hover effect
transform: Scale {
origin.x: largeButtonRoot.width / 2
origin.y: largeButtonRoot.height / 2
xScale: hoverScale
yScale: hoverScale
}
// Subtle shadow/glow effect
layer.enabled: isSelected || mouseArea.containsMouse || pending
layer.effect: MultiEffect {
shadowEnabled: true
shadowBlur: 20
shadowOpacity: 0.3
shadowColor: pending ? Color.mPrimary : (isShutdown ? Color.mError : Color.mPrimary)
shadowHorizontalOffset: 0
shadowVerticalOffset: 0
}
Behavior on color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCirc
}
}
Behavior on border.width {
NumberAnimation {
duration: Style.animationFast
easing.type: Easing.OutCirc
}
}
Behavior on hoverScale {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutBack
easing.overshoot: 0.5
}
}
ColumnLayout {
anchors.centerIn: parent
anchors.margins: Style.marginL
spacing: Style.marginM
// Large icon with scale animation
NIcon {
id: iconElement
Layout.alignment: Qt.AlignHCenter
icon: largeButtonRoot.icon
color: {
if (largeButtonRoot.pending)
return Color.mOnPrimary;
if (largeButtonRoot.isShutdown && !largeButtonRoot.isSelected && !mouseArea.containsMouse)
return Color.mError;
if (largeButtonRoot.isSelected || mouseArea.containsMouse)
return Color.mOnPrimary;
return Color.mOnSurface;
}
pointSize: Style.fontSizeXXXL * 2
width: 80 * Style.uiScaleRatio
height: 80 * Style.uiScaleRatio
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
property real iconScale: (largeButtonRoot.isSelected || mouseArea.containsMouse) ? 1.1 : 1.0
transform: Scale {
origin.x: iconElement.width / 2
origin.y: iconElement.height / 2
xScale: iconElement.iconScale
yScale: iconElement.iconScale
}
Behavior on color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCirc
}
}
Behavior on iconScale {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.OutBack
easing.overshoot: 0.6
}
}
}
// Title text
NText {
Layout.alignment: Qt.AlignHCenter
text: largeButtonRoot.title
font.weight: (largeButtonRoot.isSelected || mouseArea.containsMouse) ? Style.fontWeightBold : Style.fontWeightMedium
pointSize: Style.fontSizeL
color: {
if (largeButtonRoot.pending)
return Color.mOnPrimary;
if (largeButtonRoot.isShutdown && !largeButtonRoot.isSelected && !mouseArea.containsMouse)
return Color.mError;
if (largeButtonRoot.isSelected || mouseArea.containsMouse)
return Color.mOnPrimary;
return Color.mOnSurface;
}
Behavior on color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCirc
}
}
Behavior on font.weight {
PropertyAnimation {
duration: Style.animationFast
}
}
}
// Pending indicator
Rectangle {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: -Style.marginM
width: 30
height: 30
radius: Math.min(Style.radiusL, width / 2)
color: Color.mPrimary
visible: largeButtonRoot.pending
NText {
anchors.centerIn: parent
text: Math.ceil(timeRemaining / 1000)
pointSize: Style.fontSizeM
font.weight: Style.fontWeightBold
color: Color.mOnPrimary
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: largeButtonRoot.clicked()
}
}
}
@@ -218,6 +218,14 @@ ColumnLayout {
onToggled: checked => Settings.data.sessionMenu.showHeader = checked
}
NToggle {
Layout.fillWidth: true
label: I18n.tr("settings.session-menu.large-buttons-style.label")
description: I18n.tr("settings.session-menu.large-buttons-style.description")
checked: Settings.data.sessionMenu.largeButtonsStyle
onToggled: checked => Settings.data.sessionMenu.largeButtonsStyle = checked
}
NToggle {
Layout.fillWidth: true
label: I18n.tr("settings.session-menu.enable-countdown.label")