SessionMenuTab: add keybind setting per entry

This commit is contained in:
Lysec
2026-02-06 12:50:45 +01:00
parent a6283d2962
commit 23e08a60d5
20 changed files with 317 additions and 54 deletions
+6 -1
View File
@@ -50,7 +50,7 @@
"device-label": "Akkugerät",
"display-mode-description": "Wählen Sie, wie der Akku in der Leiste angezeigt wird.",
"display-mode-graphic": "Grafischer Akku",
"display-mode-graphic-clean": "Grafische Batterie (ohne %)",
"display-mode-graphic-clean": "Grafischer Akku (ohne %)",
"display-mode-icon-always": "Symbol - Immer % anzeigen",
"display-mode-icon-hover": "Symbol - Beim Hover anzeigen",
"display-mode-icon-only": "Nur Symbol",
@@ -411,6 +411,7 @@
"installed": "Installiert",
"interface": "Schnittstelle",
"internet": "Internet",
"keybind": "Tastenbelegung",
"language": "Sprache",
"loading": "Wird geladen...",
"local": "Lokal",
@@ -448,6 +449,7 @@
"primary": "Primär",
"random": "Zufällig",
"reboot": "Neu starten",
"record": "Aufnahme starten",
"refresh": "Aktualisieren",
"required": "(erforderlich)",
"reset": "Zurücksetzen",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Interne Abmeldung (kein Befehl)",
"entry-settings-default-info-description": "Wenn kein benutzerdefinierter Befehl angegeben ist, wird der standardmäßige Systembefehl verwendet.",
"entry-settings-default-info-label": "Standardbefehl",
"entry-settings-keybind-description": "Weisen Sie eine Tastenkombination zu, um diese Aktion auszulösen, wenn das Sitzungsmenü geöffnet ist.",
"entry-settings-keybind-placeholder": "Drücke Aufnehmen, um eine Taste zuzuweisen...",
"entry-settings-keybind-recording": "Aufnahme läuft... Drücken Sie eine beliebige Tastenkombination",
"entry-settings-title": "Konfiguriere {entry}",
"entry-settings-tooltip": "Konfigurationsbefehl",
"general-desc": "Konfigurieren Sie das Verhalten und Erscheinungsbild des Sitzungsmenü-Panels.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Installed",
"interface": "Interface",
"internet": "Internet",
"keybind": "Keybind",
"language": "Language",
"loading": "Loading...",
"local": "Local",
@@ -448,6 +449,7 @@
"primary": "Primary",
"random": "Random",
"reboot": "Reboot",
"record": "Start recording",
"refresh": "Refresh",
"required": "(required)",
"reset": "Reset",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Internal logout (no command)",
"entry-settings-default-info-description": "If no custom command is specified, the default system command will be used.",
"entry-settings-default-info-label": "Default command",
"entry-settings-keybind-description": "Assign a key combination to trigger this action when the session menu is open.",
"entry-settings-keybind-placeholder": "Press Record to assign a key...",
"entry-settings-keybind-recording": "Recording... Press any key combination",
"entry-settings-title": "Configure {entry}",
"entry-settings-tooltip": "Configure command",
"general-desc": "Configure the session menu panel behavior and appearance.",
+7 -2
View File
@@ -411,6 +411,7 @@
"installed": "Instalado",
"interface": "Interfaz",
"internet": "Internet",
"keybind": "Atajo de teclado",
"language": "Idioma",
"loading": "Cargando...",
"local": "Local",
@@ -448,6 +449,7 @@
"primary": "Primario",
"random": "Aleatorio",
"reboot": "Reiniciar",
"record": "Iniciar grabación",
"refresh": "Refrescar",
"required": "(obligatorio)",
"reset": "Restablecer",
@@ -872,7 +874,7 @@
"shortcuts-title": "Widgets de accesos directos",
"system-monitor-disk-path-description": "Selecciona qué punto de montaje de disco debe monitorear la tarjeta del monitor del sistema en el centro de control.",
"system-monitor-disk-path-label": "Ruta del disco del monitor del sistema",
"title": "Centro de control"
"title": "Centro de Control"
},
"desktop-widgets": {
"clock-enabled-description": "Mostrar un widget de reloj en el escritorio.",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Cierre de sesión interno (sin comando)",
"entry-settings-default-info-description": "Si no se especifica un comando personalizado, se utilizará el comando predeterminado del sistema.",
"entry-settings-default-info-label": "Comando predeterminado",
"entry-settings-keybind-description": "Asigna una combinación de teclas para activar esta acción cuando el menú de sesión esté abierto.",
"entry-settings-keybind-placeholder": "Pulsa Grabar para asignar una tecla...",
"entry-settings-keybind-recording": "Grabando... Pulsa cualquier combinación de teclas",
"entry-settings-title": "Configurar {entry}",
"entry-settings-tooltip": "Configurar comando",
"general-desc": "Configurar el comportamiento y la apariencia del panel del menú de sesión.",
@@ -1503,7 +1508,7 @@
"bottom-center": "Inferior central",
"bottom-left": "Inferior izquierda",
"bottom-right": "Inferior derecha",
"center": "Centrar",
"center": "Centro",
"center-left": "Izquierda centrado",
"center-right": "Derecha centrado",
"close-to-bar": "Cerca del botón de la barra",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Installé",
"interface": "Interface",
"internet": "Internet",
"keybind": "Raccourci clavier",
"language": "Langue",
"loading": "Chargement...",
"local": "Local",
@@ -448,6 +449,7 @@
"primary": "Primaire",
"random": "Aléatoire",
"reboot": "Redémarrer",
"record": "Démarrer l'enregistrement",
"refresh": "Actualiser",
"required": "(requis)",
"reset": "Réinitialiser",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Déconnexion interne (sans commande)",
"entry-settings-default-info-description": "Si aucune commande personnalisée n'est spécifiée, la commande système par défaut sera utilisée.",
"entry-settings-default-info-label": "Commande par défaut",
"entry-settings-keybind-description": "Attribuez une combinaison de touches pour déclencher cette action lorsque le menu de session est ouvert.",
"entry-settings-keybind-placeholder": "Appuyez sur Enregistrer pour assigner une touche...",
"entry-settings-keybind-recording": "Enregistrement... Appuyez sur n'importe quelle combinaison de touches",
"entry-settings-title": "Configurer {entry}",
"entry-settings-tooltip": "Configurer la commande",
"general-desc": "Configurer le comportement et l'apparence du panneau du menu de session.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Telepítve",
"interface": "Felület",
"internet": "Internet",
"keybind": "Billentyűkombináció",
"language": "Nyelv",
"loading": "Betöltés...",
"local": "Helyi",
@@ -448,6 +449,7 @@
"primary": "Elsődleges",
"random": "Véletlen",
"reboot": "Újraindítás",
"record": "Felvétel indítása",
"refresh": "Frissítés",
"required": "(kötelező)",
"reset": "Visszaállítás",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Belső kijelentkezés (nincs parancs)",
"entry-settings-default-info-description": "Ha nincs megadva egyéni parancs, az alapértelmezett rendszerparancs kerül felhasználásra.",
"entry-settings-default-info-label": "Alapértelmezett parancs",
"entry-settings-keybind-description": "Rendeljen hozzá billentyűkombinációt ezen művelet elindításához, amikor a munkamenet menü nyitva van.",
"entry-settings-keybind-placeholder": "Nyomja meg a Felvétel gombot egy billentyű hozzárendeléséhez...",
"entry-settings-keybind-recording": "Felvétel... Nyomjon meg bármilyen billentyűkombinációt",
"entry-settings-title": "{entry} konfigurálása",
"entry-settings-tooltip": "Parancs konfigurálása",
"general-desc": "A munkamenet menüpanel viselkedésének és megjelenésének konfigurálása.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "インストール済み",
"interface": "インターフェース",
"internet": "インターネット",
"keybind": "キーバインド",
"language": "言語",
"loading": "読み込み中...",
"local": "ローカル",
@@ -448,6 +449,7 @@
"primary": "プライマリ",
"random": "ランダム",
"reboot": "再起動",
"record": "録画を開始",
"refresh": "更新",
"required": "(必須)",
"reset": "リセット",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "内部ログアウト(コマンドなし)",
"entry-settings-default-info-description": "カスタムコマンドが指定されていない場合、デフォルトのシステムコマンドが使用されます。",
"entry-settings-default-info-label": "デフォルトのコマンド",
"entry-settings-keybind-description": "セッションメニューが開いているときに、このアクションをトリガーするキーの組み合わせを割り当てます。",
"entry-settings-keybind-placeholder": "キーを割り当てるには、記録を押してください...",
"entry-settings-keybind-recording": "録音中... 任意のキーの組み合わせを押してください",
"entry-settings-title": "「{entry}」の設定",
"entry-settings-tooltip": "コマンドを設定",
"general-desc": "セッションメニューパネルの動作と外観を設定します。",
+5
View File
@@ -411,6 +411,7 @@
"installed": "설치됨",
"interface": "인터페이스",
"internet": "인터넷",
"keybind": "키 바인딩",
"language": "언어",
"loading": "로딩 중...",
"local": "로컬",
@@ -448,6 +449,7 @@
"primary": "첫번째",
"random": "랜덤",
"reboot": "재부팅",
"record": "녹화 시작",
"refresh": "새로고침",
"required": "(필수)",
"reset": "초기화",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "내부 로그아웃 (명령 없음)",
"entry-settings-default-info-description": "사용자 지정 명령이 지정되지 않은 경우 시스템 기본 명령이 사용됩니다.",
"entry-settings-default-info-label": "기본 명령",
"entry-settings-keybind-description": "세션 메뉴가 열려 있을 때 이 작업을 트리거할 키 조합을 할당합니다.",
"entry-settings-keybind-placeholder": "키를 할당하려면 기록을 누르세요...",
"entry-settings-keybind-recording": "녹음 중... 아무 키 조합이나 누르세요",
"entry-settings-title": "{entry} 구성",
"entry-settings-tooltip": "명령 구성",
"general-desc": "세션 메뉴 패널의 동작과 모양을 구성합니다.",
+6 -1
View File
@@ -50,7 +50,7 @@
"device-label": "Accuapparaat",
"display-mode-description": "Kies hoe de batterij wordt weergegeven in de balk.",
"display-mode-graphic": "Grafische accu",
"display-mode-graphic-clean": "Grafische batterij (geen %)",
"display-mode-graphic-clean": "Grafische accu (geen %)",
"display-mode-icon-always": "Pictogram - Altijd % tonen",
"display-mode-icon-hover": "Icoon - Tonen bij hover",
"display-mode-icon-only": "Alleen pictogram",
@@ -411,6 +411,7 @@
"installed": "Geïnstalleerd",
"interface": "Interface",
"internet": "Internet",
"keybind": "Toetsencombinatie",
"language": "Taal",
"loading": "Laden...",
"local": "Lokaal",
@@ -448,6 +449,7 @@
"primary": "Primair",
"random": "Willekeurig",
"reboot": "Herstarten",
"record": "Opname starten",
"refresh": "Vernieuwen",
"required": "(vereist)",
"reset": "Resetten",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Interne afmelding (geen commando)",
"entry-settings-default-info-description": "Als er geen aangepast commando is opgegeven, wordt het standaard systeemcommando gebruikt.",
"entry-settings-default-info-label": "Standaardopdracht",
"entry-settings-keybind-description": "Wijs een toetscombinatie toe om deze actie te activeren wanneer het sessiemenu geopend is.",
"entry-settings-keybind-placeholder": "Druk op Opnemen om een toets toe te wijzen...",
"entry-settings-keybind-recording": "Opname... Druk op een willekeurige toetscombinatie",
"entry-settings-title": "Configureer {entry}",
"entry-settings-tooltip": "Configureer opdracht",
"general-desc": "Configureer het gedrag en uiterlijk van het sessiemenupaneel.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Zainstalowano",
"interface": "Interfejs",
"internet": "Internet",
"keybind": "Skrót klawiszowy",
"language": "Język",
"loading": "Ładowanie...",
"local": "Lokalny",
@@ -448,6 +449,7 @@
"primary": "Podstawowy",
"random": "Losowy",
"reboot": "Restart",
"record": "Rozpocznij nagrywanie",
"refresh": "Odśwież",
"required": "(wymagane)",
"reset": "Zresetuj",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Wewnętrzne wylogowanie (brak polecenia)",
"entry-settings-default-info-description": "Jeśli nie podano własnego polecenia, zostanie użyte domyślne polecenie systemowe.",
"entry-settings-default-info-label": "Domyślne polecenie",
"entry-settings-keybind-description": "Przypisz kombinację klawiszy, aby wywołać tę akcję, gdy menu sesji jest otwarte.",
"entry-settings-keybind-placeholder": "Naciśnij Nagraj, aby przypisać klawisz...",
"entry-settings-keybind-recording": "Nagrywanie... Naciśnij dowolną kombinację klawiszy",
"entry-settings-title": "Konfiguruj {entry}",
"entry-settings-tooltip": "Konfiguruj polecenie",
"general-desc": "Konfiguruj zachowanie i wygląd panelu menu sesji.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Instalado",
"interface": "Interface",
"internet": "Internet",
"keybind": "Atalho de teclado",
"language": "Linguagem",
"loading": "Carregando...",
"local": "Local",
@@ -448,6 +449,7 @@
"primary": "Primário",
"random": "Aleatório",
"reboot": "Reiniciar",
"record": "Iniciar gravação",
"refresh": "Atualizar",
"required": "(obrigatório)",
"reset": "Reiniciar",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Logout interno (sem comando)",
"entry-settings-default-info-description": "Se nenhum comando personalizado for especificado, o comando padrão do sistema será usado.",
"entry-settings-default-info-label": "Comando padrão",
"entry-settings-keybind-description": "Atribua uma combinação de teclas para acionar esta ação quando o menu de sessão estiver aberto.",
"entry-settings-keybind-placeholder": "Pressione Gravar para atribuir uma tecla...",
"entry-settings-keybind-recording": "Gravando... Pressione qualquer combinação de teclas",
"entry-settings-title": "Configurar {entry}",
"entry-settings-tooltip": "Configurar comando",
"general-desc": "Configurar o comportamento e a aparência do painel do menu de sessão.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Установлено",
"interface": "Интерфейс",
"internet": "Интернет",
"keybind": "Привязка клавиш",
"language": "Язык",
"loading": "Загрузка...",
"local": "Местный",
@@ -448,6 +449,7 @@
"primary": "Основной",
"random": "Случайный",
"reboot": "Перезагрузить",
"record": "Начать запись",
"refresh": "Обновить",
"required": "(обязательно)",
"reset": "Сброс",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Внутренний выход из системы (без команды)",
"entry-settings-default-info-description": "Если не указана пользовательская команда, будет использована системная команда по умолчанию.",
"entry-settings-default-info-label": "Команда по умолчанию",
"entry-settings-keybind-description": "Назначьте комбинацию клавиш для вызова этого действия, когда меню сеанса открыто.",
"entry-settings-keybind-placeholder": "Нажмите Запись, чтобы назначить клавишу...",
"entry-settings-keybind-recording": "Запись... Нажмите любую комбинацию клавиш",
"entry-settings-title": "Настроить {entry}",
"entry-settings-tooltip": "Настроить команду",
"general-desc": "Настройка поведения и внешнего вида панели меню сеанса.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Installerad",
"interface": "Gränssnitt",
"internet": "Internet",
"keybind": "Tangentbindning",
"language": "Språk",
"loading": "Läser in...",
"local": "Lokal",
@@ -448,6 +449,7 @@
"primary": "Primär",
"random": "Slumpmässig",
"reboot": "Starta om",
"record": "Starta inspelning",
"refresh": "Uppdatera",
"required": "(krävs)",
"reset": "Återställ",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Intern utloggning (inget kommando)",
"entry-settings-default-info-description": "Om inget anpassat kommando anges kommer standardkommandot för systemet att användas.",
"entry-settings-default-info-label": "Standardkommando",
"entry-settings-keybind-description": "Tilldela en tangentkombination för att utlösa denna åtgärd när sessionsmenyn är öppen.",
"entry-settings-keybind-placeholder": "Tryck på Spela in för att tilldela en tangent...",
"entry-settings-keybind-recording": "Inspelning... Tryck på valfri tangentkombination",
"entry-settings-title": "Konfigurera {entry}",
"entry-settings-tooltip": "Konfigurera kommando",
"general-desc": "Konfigurera sessionens menypanels beteende och utseende.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Yüklendi",
"interface": "Arayüz",
"internet": "İnternet",
"keybind": "Tuş Ataması",
"language": "Dil",
"loading": "Yükleniyor...",
"local": "Yerel",
@@ -448,6 +449,7 @@
"primary": "Birincil",
"random": "Rastgele",
"reboot": "Yeniden başlat",
"record": "Kaydı Başlat",
"refresh": "Yenile",
"required": "(gerekli)",
"reset": "Sıfırla",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Dahili oturum kapatma (komut yok)",
"entry-settings-default-info-description": "Özel bir komut belirtilmezse, varsayılan sistem komutu kullanılır.",
"entry-settings-default-info-label": "Varsayılan komut",
"entry-settings-keybind-description": "Oturum menüsü açıkken bu eylemi tetiklemek için bir tuş kombinasyonu atayın.",
"entry-settings-keybind-placeholder": "Bir tuş atamak için Kaydet'e basın...",
"entry-settings-keybind-recording": "Kaydediliyor... Herhangi bir tuş kombinasyonuna basın",
"entry-settings-title": "{entry} yapılandır",
"entry-settings-tooltip": "Yapılandırma komutu",
"general-desc": "Oturum menüsü panelinin davranışını ve görünümünü yapılandırın.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "Встановлено",
"interface": "Інтерфейс",
"internet": "Інтернет",
"keybind": "Прив'язка клавіш",
"language": "Мова",
"loading": "Завантаження...",
"local": "Місцевий",
@@ -448,6 +449,7 @@
"primary": "Основний",
"random": "Випадковий",
"reboot": "Перезапустити",
"record": "Почати запис",
"refresh": "Оновити",
"required": "(обов'язково)",
"reset": "Скинути",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "Внутрішній вихід з системи (без команди)",
"entry-settings-default-info-description": "Якщо не вказано жодної власної команди, буде використано системну команду за замовчуванням.",
"entry-settings-default-info-label": "Команда за замовчуванням",
"entry-settings-keybind-description": "Призначте комбінацію клавіш для запуску цієї дії, коли меню сесії відкрито.",
"entry-settings-keybind-placeholder": "Натисніть Запис, щоб призначити клавішу...",
"entry-settings-keybind-recording": "Запис... Натисніть будь-яку комбінацію клавіш",
"entry-settings-title": "Налаштувати {entry}",
"entry-settings-tooltip": "Налаштувати команду",
"general-desc": "Налаштувати поведінку та зовнішній вигляд панелі меню сеансу.",
+5
View File
@@ -411,6 +411,7 @@
"installed": "已安装",
"interface": "界面",
"internet": "互联网",
"keybind": "按键绑定",
"language": "语言",
"loading": "正在加载...",
"local": "本地",
@@ -448,6 +449,7 @@
"primary": "主要的",
"random": "随机",
"reboot": "重启",
"record": "开始录制",
"refresh": "刷新",
"required": "(必要)",
"reset": "重置",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "内部注销(无命令)",
"entry-settings-default-info-description": "如果没有指定自定义命令,将使用默认的系统命令。",
"entry-settings-default-info-label": "默认命令",
"entry-settings-keybind-description": "当会话菜单打开时,分配一个按键组合来触发此操作。",
"entry-settings-keybind-placeholder": "按下录制以分配一个键...",
"entry-settings-keybind-recording": "录制中... 按任意组合键",
"entry-settings-title": "配置 {entry}",
"entry-settings-tooltip": "配置命令",
"general-desc": "配置会话菜单面板的行为和外观。",
+5
View File
@@ -411,6 +411,7 @@
"installed": "已安裝",
"interface": "介面",
"internet": "網際網路",
"keybind": "按鍵綁定",
"language": "語言",
"loading": "正在載入...",
"local": "本機",
@@ -448,6 +449,7 @@
"primary": "主要的",
"random": "隨機",
"reboot": "重新啟動",
"record": "開始錄製",
"refresh": "重新整理",
"required": "(必要)",
"reset": "重設",
@@ -1357,6 +1359,9 @@
"entry-settings-default-command-logout": "內建登出 (沒有指令)",
"entry-settings-default-info-description": "如果沒有指定自訂指令則使用系統的預設指令",
"entry-settings-default-info-label": "預設指令",
"entry-settings-keybind-description": "當會話選單打開時,分配一個按鍵組合來觸發此操作。",
"entry-settings-keybind-placeholder": "按下錄製以分配一個鍵...",
"entry-settings-keybind-recording": "錄製中... 按任意組合鍵",
"entry-settings-title": "設定{entry}",
"entry-settings-tooltip": "設定指令",
"general-desc": "設定工作階段選單的外觀和行為",
+8
View File
@@ -1391,6 +1391,14 @@
"tabLabel": "session-menu.title",
"subTab": null
},
{
"labelKey": "common.keybind",
"descriptionKey": "panels.session-menu.entry-settings-keybind-description",
"widget": "NTextInput",
"tab": 12,
"tabLabel": "session-menu.title",
"subTab": null
},
{
"labelKey": "panels.system-monitor.enable-dgpu-monitoring-label",
"descriptionKey": "panels.system-monitor.enable-dgpu-monitoring-description",
+74 -17
View File
@@ -134,7 +134,8 @@ SmartPanel {
"title": metadata.title,
"isShutdown": metadata.isShutdown,
"countdownEnabled": settingOption.countdownEnabled !== undefined ? settingOption.countdownEnabled : true,
"command": settingOption.command || ""
"command": settingOption.command || "",
"keybind": settingOption.keybind || ""
});
}
}
@@ -436,6 +437,51 @@ SmartPanel {
selectPreviousWrapped();
}
function checkKeybind(event) {
if (powerOptions.length === 0)
return;
// Construct key string in the same format as the recorder
// Ignore modifier keys by themselves
if (event.key === Qt.Key_Control || event.key === Qt.Key_Shift || event.key === Qt.Key_Alt || event.key === Qt.Key_Meta) {
return;
}
let keyStr = "";
if (event.modifiers & Qt.ControlModifier)
keyStr += "Ctrl+";
if (event.modifiers & Qt.AltModifier)
keyStr += "Alt+";
if (event.modifiers & Qt.ShiftModifier)
keyStr += "Shift+";
if (event.modifiers & Qt.MetaModifier)
keyStr += "Meta+";
let keyName = "";
if (event.text && event.text.length > 0 && event.text.charCodeAt(0) > 31) {
keyName = event.text.toUpperCase();
} else {
// Only checking text based keys for now as per recorder
return;
}
if (!keyName)
return;
const pressedKeybind = keyStr + keyName;
for (var i = 0; i < powerOptions.length; i++) {
const option = powerOptions[i];
if (option.keybind === pressedKeybind) {
selectedIndex = i;
startTimer(option.action);
event.accepted = true;
return;
}
}
}
// Number selection handler (kept for backward compatibility if needed, though keybinds might override common keys)
function onNumberPressed(number) {
if (!Settings.data.sessionMenu.showNumberLabels) {
return;
@@ -481,6 +527,10 @@ SmartPanel {
}
}
Keys.onPressed: event => {
root.checkKeybind(event);
}
HoverHandler {
id: globalHoverHandler
@@ -566,6 +616,7 @@ SmartPanel {
startTimer(modelData.action);
}
pending: timerActive && pendingAction === modelData.action
keybind: modelData.keybind || ""
}
}
}
@@ -647,6 +698,7 @@ SmartPanel {
startTimer(modelData.action);
}
pending: timerActive && pendingAction === modelData.action
keybind: modelData.keybind || ""
}
}
}
@@ -697,25 +749,27 @@ SmartPanel {
font.weight: Style.fontWeightBold
}
// Number indicator (keybind)
// Keybind/Number indicator (keybind)
Rectangle {
id: numberIndicatorRect
anchors.left: countdownText.visible ? countdownText.right : parent.left
anchors.leftMargin: countdownText.visible ? Style.marginXS : 0
anchors.verticalCenter: parent.verticalCenter
width: Style.marginXL
height: width
width: Math.max(Style.marginXL, labelText.implicitWidth + Style.marginM)
height: Style.marginXL
radius: Math.min(Style.radiusM, height / 2)
color: (buttonRoot.isSelected || buttonRoot.effectiveHover) ? Color.mPrimary : Qt.alpha(Color.mSurfaceVariant, 0.5)
color: (buttonRoot.isSelected || buttonRoot.effectiveHover) ? Color.mOnPrimary : Qt.alpha(Color.mSurfaceVariant, 0.5)
border.width: Style.borderS
border.color: (buttonRoot.isSelected || buttonRoot.effectiveHover) ? Color.mPrimary : Color.mOutline
visible: Settings.data.sessionMenu.showNumberLabels && buttonRoot.number > 0
border.color: (buttonRoot.isSelected || buttonRoot.effectiveHover) ? Color.mOnPrimary : Color.mOutline
visible: (Settings.data.sessionMenu.showNumberLabels && buttonRoot.number > 0) || buttonRoot.keybind !== ""
NText {
id: labelText
anchors.centerIn: parent
text: buttonRoot.number
text: buttonRoot.keybind !== "" ? buttonRoot.keybind : buttonRoot.number
pointSize: Style.fontSizeS
color: (buttonRoot.isSelected || buttonRoot.effectiveHover) ? Color.mOnPrimary : Color.mOnSurface
font.weight: Style.fontWeightBold
color: (buttonRoot.isSelected || buttonRoot.effectiveHover) ? Color.mPrimary : Color.mOnSurface
Behavior on color {
ColorAnimation {
@@ -733,6 +787,7 @@ SmartPanel {
property bool isShutdown: false
property bool isSelected: false
property int number: 0
property string keybind: ""
property int buttonIndex: -1
// Effective hover state that respects ignoreMouseHover
@@ -886,6 +941,7 @@ SmartPanel {
property bool isShutdown: false
property bool isSelected: false
property int number: 0
property string keybind: ""
property int buttonIndex: -1
// Effective hover state that respects ignoreMouseHover
@@ -1026,28 +1082,29 @@ SmartPanel {
}
}
// Number indicator in top-right corner
// Keybind/Number indicator in top-right corner
Rectangle {
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: Style.marginM
width: Style.fontSizeM * 2
height: width
width: Math.max(Style.fontSizeM * 2, largeNumberText.implicitWidth + Style.marginM)
height: Style.fontSizeM * 2
radius: Math.min(Style.radiusM, height / 2)
color: Qt.alpha(Color.mSurfaceVariant, 0.7)
color: (largeButtonRoot.isSelected || largeButtonRoot.effectiveHover) ? Color.mOnPrimary : Qt.alpha(Color.mSurfaceVariant, 0.7)
border.width: Style.borderS
border.color: Color.mOutline
visible: Settings.data.sessionMenu.showNumberLabels && largeButtonRoot.number > 0 && !largeButtonRoot.pending
border.color: (largeButtonRoot.isSelected || largeButtonRoot.effectiveHover) ? Color.mOnPrimary : Color.mOutline
visible: (Settings.data.sessionMenu.showNumberLabels && largeButtonRoot.number > 0 || largeButtonRoot.keybind !== "") && !largeButtonRoot.pending
z: 10
NText {
id: largeNumberText
anchors.centerIn: parent
text: largeButtonRoot.number
text: largeButtonRoot.keybind !== "" ? largeButtonRoot.keybind : largeButtonRoot.number
pointSize: Style.fontSizeM
font.weight: Style.fontWeightBold
color: {
if (largeButtonRoot.isSelected || largeButtonRoot.effectiveHover)
return Color.mOnPrimary;
return Color.mPrimary;
return Color.mOnSurface;
}
@@ -13,7 +13,7 @@ Popup {
property string entryId: ""
property string entryText: ""
signal updateEntryCommand(int index, string command)
signal updateEntryProperties(int index, var properties)
// Default commands mapping
readonly property var defaultCommands: {
@@ -38,11 +38,19 @@ Popup {
// Load command when popup opens
if (entryData) {
commandInput.text = entryData.command || "";
keybindInput.text = entryData.keybind || "";
}
// Request focus to ensure keyboard input works
forceActiveFocus();
}
function save() {
root.updateEntryProperties(root.entryIndex, {
"command": commandInput.text,
"keybind": keybindInput.text
});
}
background: Rectangle {
id: bgRect
@@ -78,7 +86,10 @@ Popup {
NIconButton {
icon: "close"
tooltipText: I18n.tr("common.close")
onClicked: root.close()
onClicked: {
root.save();
root.close();
}
}
}
@@ -96,16 +107,7 @@ Popup {
label: I18n.tr("common.command")
description: I18n.tr("panels.session-menu.entry-settings-command-description")
placeholderText: I18n.tr("panels.session-menu.entry-settings-command-placeholder")
onEditingFinished: {
// Auto-focus on Enter
applyButton.forceActiveFocus();
}
Keys.onReturnPressed: {
applyButton.clicked();
}
Keys.onEnterPressed: {
applyButton.clicked();
}
onTextChanged: root.save()
}
// Default command info
@@ -152,31 +154,146 @@ Popup {
}
}
// Action buttons
// Keybind input
RowLayout {
Layout.fillWidth: true
Layout.topMargin: Style.marginM
spacing: Style.marginM
spacing: Style.marginS
Item {
NTextInput {
id: keybindInput
Layout.fillWidth: true
label: I18n.tr("common.keybind")
description: I18n.tr("panels.session-menu.entry-settings-keybind-description")
placeholderText: listening ? I18n.tr("panels.session-menu.entry-settings-keybind-recording") : I18n.tr("panels.session-menu.entry-settings-keybind-placeholder")
inputIconName: listening ? "circle-dot" : ""
readOnly: true
property bool listening: false
// Clear text when starting to listen to show it's active
onListeningChanged: {
if (listening) {
text = "";
}
}
Keys.onPressed: event => {
if (!listening)
return;
// Ignore modifier keys by themselves
if (event.key === Qt.Key_Control || event.key === Qt.Key_Shift || event.key === Qt.Key_Alt || event.key === Qt.Key_Meta) {
return;
}
let keyStr = "";
if (event.modifiers & Qt.ControlModifier)
keyStr += "Ctrl+";
if (event.modifiers & Qt.AltModifier)
keyStr += "Alt+";
if (event.modifiers & Qt.ShiftModifier)
keyStr += "Shift+";
if (event.modifiers & Qt.MetaModifier)
keyStr += "Meta+";
let keyName = "";
if (event.text && event.text.length > 0 && event.text.charCodeAt(0) > 31) {
keyName = event.text.toUpperCase();
} else {
keyName = event.text.toUpperCase();
}
if (keyName) {
keybindInput.text = keyStr + keyName;
listening = false;
focusScope.focus = true;
root.save();
}
}
}
NButton {
id: closeButton
text: I18n.tr("common.close")
outlined: true
onClicked: root.close()
}
NIconButton {
id: clearButton
Layout.alignment: Qt.AlignBottom
Layout.bottomMargin: Math.round(4 * Style.uiScaleRatio)
visible: !keybindInput.listening && keybindInput.text !== ""
icon: "circle-x"
NButton {
id: applyButton
text: I18n.tr("common.apply")
icon: "check"
colorBg: "transparent"
colorBgHover: Qt.alpha(Color.mError, 0.1)
colorFg: Color.mOnSurfaceVariant
colorFgHover: Color.mError
border.width: 0
tooltipText: I18n.tr("common.clear")
onClicked: {
root.updateEntryCommand(root.entryIndex, commandInput.text);
keybindInput.text = "";
root.save();
}
}
NIconButton {
id: recordButton
Layout.alignment: Qt.AlignBottom
Layout.bottomMargin: Math.round(4 * Style.uiScaleRatio)
Layout.rightMargin: Style.marginS
icon: keybindInput.listening ? "x" : "circle-dot"
// Standard colors when not listening, distinctive when listening
colorBg: keybindInput.listening ? Color.mError : Color.mSurfaceVariant
colorFg: keybindInput.listening ? Color.mOnError : Color.mPrimary
colorBgHover: keybindInput.listening ? Color.mError : Color.mHover
colorFgHover: keybindInput.listening ? Color.mOnError : Color.mOnHover
// Match NButton radius
customRadius: Style.iRadiusS
border.width: 0
Behavior on colorBg {
ColorAnimation {
duration: Style.animationFast
}
}
SequentialAnimation {
id: recordingPulse
running: keybindInput.listening
loops: Animation.Infinite
NumberAnimation {
target: recordButton
property: "opacity"
from: 1.0
to: 0.6
duration: 500
easing.type: Easing.InOutSine
}
NumberAnimation {
target: recordButton
property: "opacity"
from: 0.6
to: 1.0
duration: 500
easing.type: Easing.InOutSine
}
}
tooltipText: keybindInput.listening ? I18n.tr("common.cancel") : I18n.tr("common.record")
onClicked: {
if (keybindInput.listening) {
keybindInput.listening = false;
focusScope.focus = true;
} else {
keybindInput.listening = true;
keybindInput.forceActiveFocus();
}
}
}
}
// Bottom spacer to maintain padding
Item {
Layout.preferredHeight: Style.marginS
}
}
}
@@ -58,7 +58,8 @@ ColumnLayout {
"action": entriesModel[i].id,
"enabled": entriesModel[i].enabled,
"countdownEnabled": entriesModel[i].countdownEnabled !== undefined ? entriesModel[i].countdownEnabled : true,
"command": entriesModel[i].command || ""
"command": entriesModel[i].command || "",
"keybind": entriesModel[i].keybind || ""
});
}
Settings.data.sessionMenu.powerOptions = toSave;
@@ -112,11 +113,9 @@ ColumnLayout {
if (dialog) {
root._activeDialog = dialog;
dialog.updateEntryCommand.connect((idx, command) => {
root.updateEntry(idx, {
"command": command
});
});
dialog.updateEntryProperties.connect((idx, properties) => {
root.updateEntry(idx, properties);
});
dialog.closed.connect(() => {
if (root._activeDialog === dialog) {
root._activeDialog = null;
@@ -159,6 +158,7 @@ ColumnLayout {
entry.countdownEnabled = settingEntry.countdownEnabled !== undefined ? settingEntry.countdownEnabled : true;
// Load custom command if defined
entry.command = settingEntry.command || "";
entry.keybind = settingEntry.keybind || "";
entriesModel.push(entry);
}
}
@@ -180,6 +180,7 @@ ColumnLayout {
entry.countdownEnabled = true;
// Default command to empty string for new entries
entry.command = "";
entry.keybind = "";
entriesModel.push(entry);
}
}