mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge branch 'desktop-widgets'
This commit is contained in:
@@ -527,6 +527,7 @@
|
||||
"close-app": "{app} schließen",
|
||||
"connect-vpn": "Mit {name} verbinden",
|
||||
"cycle-visualizer": "Zyklus-Visualisierer",
|
||||
"delete": "Löschen",
|
||||
"disable-bluetooth": "Bluetooth deaktivieren",
|
||||
"disable-dnd": "'Nicht stören' deaktivieren",
|
||||
"disable-wifi": "WLAN deaktivieren",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Widget hinzufügen",
|
||||
"button": {
|
||||
"label": "Bearbeitungsmodus aktivieren"
|
||||
},
|
||||
"controls-explanation": "Linke Maustaste: Widget verschieben\nRechte Maustaste: Widget Größe ändern",
|
||||
"controls-explanation": "Linksklick & Ziehen: Widget verschieben oder Größe ändern.\nRechtsklick: Kontextmenü-Optionen öffnen.",
|
||||
"description": "Aktiviere den Bearbeitungsmodus, um Desktop-Widgets zu verschieben und neu zu positionieren. Im aktivierten Zustand zeigen Widgets eine Ziehumrandung und können neu positioniert werden.",
|
||||
"exit-button": "Bearbeitungsmodus verlassen",
|
||||
"grid-snap": {
|
||||
"label": "Raster einrasten"
|
||||
},
|
||||
"label": "Bearbeitungsmodus"
|
||||
"label": "Bearbeitungsmodus",
|
||||
"open-settings": "Einstellungen öffnen"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Desktop-Widgets vollständig aktivieren oder deaktivieren.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Elemente in einem Raster statt in einer Liste anzeigen.",
|
||||
"label": "Rasteransicht"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Verwende native System-Icons anstelle von Tabler-Icons.",
|
||||
"label": "Native Icons verwenden"
|
||||
},
|
||||
"position": {
|
||||
"description": "Wählen Sie, wo das Starter-Panel erscheint.",
|
||||
"label": "Position"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "Wenn aktiviert, erscheinen häufig gestartete Apps zuerst in der Liste.",
|
||||
"label": "Nach Häufigkeit sortieren"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Verwende native System-Icons anstelle von Tabler-Icons.",
|
||||
"label": "Native Icons verwenden"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Befehl zum Starten eines Terminals. Z.B. 'kitty -e' oder 'gnome-terminal --'.",
|
||||
"label": "Terminalbefehl"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "Close {app}",
|
||||
"connect-vpn": "Connect to {name}",
|
||||
"cycle-visualizer": "Cycle visualizer",
|
||||
"delete": "Delete",
|
||||
"disable-bluetooth": "Disable Bluetooth",
|
||||
"disable-dnd": "Disable Do Not Disturb",
|
||||
"disable-wifi": "Disable Wi-Fi",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Add widget",
|
||||
"button": {
|
||||
"label": "Enter edit mode"
|
||||
},
|
||||
"controls-explanation": "Left Mouse Button: Move widget\nRight Mouse Button: Resize widget",
|
||||
"controls-explanation": "Left-click & drag: Move or resize the widget.\nRight-click: Open the context menu options.",
|
||||
"description": "Enable edit mode to move and reposition desktop widgets. When enabled, widgets show a drag outline and can be repositioned.",
|
||||
"exit-button": "Exit edit mode",
|
||||
"grid-snap": {
|
||||
"label": "Grid snap"
|
||||
},
|
||||
"label": "Edit mode"
|
||||
"label": "Edit mode",
|
||||
"open-settings": "Open settings"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Enable or disable desktop widgets entirely.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Display items in a grid layout instead of a list.",
|
||||
"label": "Grid view"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Use native system icons instead of Tabler icons.",
|
||||
"label": "Use native icons"
|
||||
},
|
||||
"position": {
|
||||
"description": "Choose where the launcher panel appears.",
|
||||
"label": "Position"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "When enabled, frequently launched apps appear first in the list.",
|
||||
"label": "Sort by most used"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Use native system icons instead of Tabler icons.",
|
||||
"label": "Use native icons"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Command to launch a terminal. E.g., 'kitty -e' or 'gnome-terminal --'.",
|
||||
"label": "Terminal command"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "Cerrar {app}",
|
||||
"connect-vpn": "Conectarse a {name}",
|
||||
"cycle-visualizer": "Visualizador de ciclos",
|
||||
"delete": "Borrar",
|
||||
"disable-bluetooth": "Desactivar Bluetooth",
|
||||
"disable-dnd": "Desactivar No molestar",
|
||||
"disable-wifi": "Desactivar Wi-Fi",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Añadir widget",
|
||||
"button": {
|
||||
"label": "Entrar en modo de edición"
|
||||
},
|
||||
"controls-explanation": "Botón izquierdo del ratón: Mover widget\nBotón derecho del ratón: Redimensionar widget",
|
||||
"controls-explanation": "Clic izquierdo y arrastrar: Mover o redimensionar el widget.\nClic derecho: Abrir las opciones del menú contextual.",
|
||||
"description": "Habilita el modo de edición para mover y cambiar la posición de los widgets del escritorio. Cuando está habilitado, los widgets muestran un contorno de arrastre y se pueden reposicionar.",
|
||||
"exit-button": "Salir del modo de edición",
|
||||
"grid-snap": {
|
||||
"label": "Ajustar a cuadrícula"
|
||||
},
|
||||
"label": "Modo de edición"
|
||||
"label": "Modo de edición",
|
||||
"open-settings": "Abrir ajustes"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Activar o desactivar los widgets de escritorio por completo.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Mostrar elementos en una cuadrícula en lugar de una lista.",
|
||||
"label": "Vista de cuadrícula"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Usa iconos nativos del sistema en lugar de iconos Tabler.",
|
||||
"label": "Usar iconos nativos"
|
||||
},
|
||||
"position": {
|
||||
"description": "Elige dónde aparece el panel del lanzador.",
|
||||
"label": "Posición"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "Cuando está activado, las aplicaciones más utilizadas aparecen primero en la lista.",
|
||||
"label": "Ordenar por más usados"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Usa iconos nativos del sistema en lugar de iconos Tabler.",
|
||||
"label": "Usar iconos nativos"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Comando para iniciar un terminal. Por ejemplo, 'kitty -e' o 'gnome-terminal --'.",
|
||||
"label": "Comando de terminal"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "Fermer {app}",
|
||||
"connect-vpn": "Se connecter à {name}",
|
||||
"cycle-visualizer": "Visualiseur de cycle",
|
||||
"delete": "Supprimer",
|
||||
"disable-bluetooth": "Désactiver le Bluetooth",
|
||||
"disable-dnd": "Désactiver le mode Ne pas déranger",
|
||||
"disable-wifi": "Désactiver le Wi-Fi",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Ajouter un widget",
|
||||
"button": {
|
||||
"label": "Entrer en mode édition"
|
||||
},
|
||||
"controls-explanation": "Bouton gauche de la souris : Déplacer le widget\nBouton droit de la souris : Redimensionner le widget",
|
||||
"controls-explanation": "Clic gauche et glisser-déposer : Déplacer ou redimensionner le widget.\nClic droit : Ouvrir les options du menu contextuel.",
|
||||
"description": "Activer le mode édition pour déplacer et repositionner les widgets du bureau. Une fois activé, les widgets affichent un contour de glissement et peuvent être repositionnés.",
|
||||
"exit-button": "Quitter le mode édition",
|
||||
"grid-snap": {
|
||||
"label": "Aligner sur la grille"
|
||||
},
|
||||
"label": "Mode édition"
|
||||
"label": "Mode édition",
|
||||
"open-settings": "Ouvrir les paramètres"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Activer ou désactiver complètement les widgets du bureau.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Afficher les éléments dans une grille au lieu d'une liste.",
|
||||
"label": "Vue grille"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Utiliser les icônes natives du système au lieu des icônes Tabler.",
|
||||
"label": "Utiliser les icônes natives"
|
||||
},
|
||||
"position": {
|
||||
"description": "Choisissez où le panneau du lanceur apparaît.",
|
||||
"label": "Position"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "Lorsque cette option est activée, les applications fréquemment lancées apparaissent en premier dans la liste.",
|
||||
"label": "Trier par les plus utilisés"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Utiliser les icônes natives du système au lieu des icônes Tabler.",
|
||||
"label": "Utiliser les icônes natives"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Commande pour lancer un terminal. Ex: 'kitty -e' ou 'gnome-terminal --'.",
|
||||
"label": "Commande du terminal"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "{app} を閉じる",
|
||||
"connect-vpn": "{name} に接続",
|
||||
"cycle-visualizer": "ビジュアライザーを切り替える",
|
||||
"delete": "削除 (Sakujo)",
|
||||
"disable-bluetooth": "Bluetooth を無効化",
|
||||
"disable-dnd": "おやすみモードを無効化",
|
||||
"disable-wifi": "Wi-Fi を無効化",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "ウィジェットを追加",
|
||||
"button": {
|
||||
"label": "編集モードに入る"
|
||||
},
|
||||
"controls-explanation": "左クリック: ウィジェットを移動\n右クリック: ウィジェットのサイズを変更",
|
||||
"controls-explanation": "左クリックでドラッグ:ウィジェットの移動またはサイズ変更。\n右クリック:コンテキストメニューオプションを開く。",
|
||||
"description": "編集モードを有効にして、デスクトップウィジェットの移動や配置変更を行います。有効にするとウィジェットに枠線が表示され、位置を変更できるようになります。",
|
||||
"exit-button": "編集モードを終了",
|
||||
"grid-snap": {
|
||||
"label": "グリッドにスナップ"
|
||||
},
|
||||
"label": "編集モード"
|
||||
"label": "編集モード",
|
||||
"open-settings": "設定を開く"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "デスクトップウィジェット全体を有効または無効にします。",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "リスト形式の代わりに、グリッド(格子状)レイアウトで項目を表示します。",
|
||||
"label": "グリッド表示"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Tablerアイコンではなく、ネイティブのシステムアイコンを使用します。",
|
||||
"label": "ネイティブアイコンを使用"
|
||||
},
|
||||
"position": {
|
||||
"description": "ランチャーパネルの表示位置を選択します。",
|
||||
"label": "表示位置"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "有効にすると、よく使うアプリがリストの上位に表示されます。",
|
||||
"label": "使用頻度順に並べ替え"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Tablerアイコンではなく、ネイティブのシステムアイコンを使用します。",
|
||||
"label": "ネイティブアイコンを使用"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "ターミナルを起動するためのコマンド(例: 'kitty -e' or 'gnome-terminal --')。",
|
||||
"label": "ターミナル起動コマンド"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "Sluit {app}",
|
||||
"connect-vpn": "Verbinding maken met {name}",
|
||||
"cycle-visualizer": "Cyclusvisualisatie",
|
||||
"delete": "Verwijderen",
|
||||
"disable-bluetooth": "Bluetooth uitschakelen",
|
||||
"disable-dnd": "Niet Storen uitschakelen",
|
||||
"disable-wifi": "Wi-Fi uitschakelen",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Widget toevoegen",
|
||||
"button": {
|
||||
"label": "Ga naar de bewerkingsmodus"
|
||||
},
|
||||
"controls-explanation": "Linkermuisknop: Widget verplaatsen\nRechtermuisknop: Widget vergroten/verkleinen",
|
||||
"controls-explanation": "Linksklikken en slepen: Widget verplaatsen of het formaat wijzigen.\nRechtermuisknop: Het contextmenu openen.",
|
||||
"description": "Schakel de bewerkingsmodus in om desktopwidgets te verplaatsen en te herpositioneren. In de ingeschakelde modus tonen widgets een sleepomtrek en kunnen ze worden verplaatst.",
|
||||
"exit-button": "Bewerkingsmodus verlaten",
|
||||
"grid-snap": {
|
||||
"label": "Raster uitlijnen"
|
||||
},
|
||||
"label": "Bewerkingsmodus"
|
||||
"label": "Bewerkingsmodus",
|
||||
"open-settings": "Instellingen openen"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Desktopwidgets volledig in- of uitschakelen.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Items in een raster weergeven in plaats van een lijst.",
|
||||
"label": "Rasterweergave"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Gebruik native systeemiconen in plaats van Tabler-iconen.",
|
||||
"label": "Gebruik native iconen"
|
||||
},
|
||||
"position": {
|
||||
"description": "Kies waar het launcher-paneel verschijnt.",
|
||||
"label": "Positie"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "Indien ingeschakeld, verschijnen vaak gestarte apps bovenaan in de lijst.",
|
||||
"label": "Sorteren op meest gebruikt"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Gebruik native systeemiconen in plaats van Tabler-iconen.",
|
||||
"label": "Gebruik native iconen"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Commando om een terminal te starten. Bijv. 'kitty -e' of 'gnome-terminal --'.",
|
||||
"label": "Terminalcommando"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "Fechar {app}",
|
||||
"connect-vpn": "Conectar-se a {name}",
|
||||
"cycle-visualizer": "Visualizador de ciclo",
|
||||
"delete": "Apagar",
|
||||
"disable-bluetooth": "Desativar Bluetooth",
|
||||
"disable-dnd": "Desativar o Não Perturbe",
|
||||
"disable-wifi": "Desativar Wi-Fi",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Adicionar widget",
|
||||
"button": {
|
||||
"label": "Entrar no modo de edição"
|
||||
},
|
||||
"controls-explanation": "Botão esquerdo do mouse: Mover widget\nBotão direito do mouse: Redimensionar widget",
|
||||
"controls-explanation": "Clique esquerdo e arraste: Mover ou redimensionar o widget.\nClique direito: Abrir as opções do menu de contexto.",
|
||||
"description": "Ative o modo de edição para mover e reposicionar widgets da área de trabalho. Quando ativado, os widgets exibem um contorno de arrastar e podem ser reposicionados.",
|
||||
"exit-button": "Sair do modo de edição",
|
||||
"grid-snap": {
|
||||
"label": "Alinhar à grade"
|
||||
},
|
||||
"label": "Modo de edição"
|
||||
"label": "Modo de edição",
|
||||
"open-settings": "Abrir configurações"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Ativar ou desativar widgets da área de trabalho completamente.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Exibir itens em uma grade em vez de uma lista.",
|
||||
"label": "Visualização em grade"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Use ícones nativos do sistema em vez de ícones Tabler.",
|
||||
"label": "Usar ícones nativos"
|
||||
},
|
||||
"position": {
|
||||
"description": "Escolha onde o painel do lançador aparece.",
|
||||
"label": "Posição"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "Quando ativado, os aplicativos mais usados aparecem primeiro na lista.",
|
||||
"label": "Ordenar por mais usados"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Use ícones nativos do sistema em vez de ícones Tabler.",
|
||||
"label": "Usar ícones nativos"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Comando para iniciar um terminal. Ex: 'kitty -e' ou 'gnome-terminal --'.",
|
||||
"label": "Comando do terminal"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "Закрыть {app}",
|
||||
"connect-vpn": "Подключиться к {name}",
|
||||
"cycle-visualizer": "Визуализатор циклов",
|
||||
"delete": "Удалить",
|
||||
"disable-bluetooth": "Отключить Bluetooth",
|
||||
"disable-dnd": "Отключить режим \"Не беспокоить\"",
|
||||
"disable-wifi": "Отключить Wi-Fi",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Добавить виджет",
|
||||
"button": {
|
||||
"label": "Войти в режим редактирования"
|
||||
},
|
||||
"controls-explanation": "Левая кнопка мыши: Перемещать виджет\nПравая кнопка мыши: Изменять размер виджета",
|
||||
"controls-explanation": "Левый клик и перетаскивание: Переместить или изменить размер виджета.\nПравый клик: Открыть контекстное меню.",
|
||||
"description": "Включите режим редактирования, чтобы перемещать и изменять положение виджетов рабочего стола. В этом режиме виджеты отображаются с контуром перетаскивания и могут быть перемещены.",
|
||||
"exit-button": "Выйти из режима редактирования",
|
||||
"grid-snap": {
|
||||
"label": "Привязка к сетке"
|
||||
},
|
||||
"label": "Режим редактирования"
|
||||
"label": "Режим редактирования",
|
||||
"open-settings": "Открыть настройки"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Включить или отключить виджеты рабочего стола полностью.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Показывать элементы в виде сетки вместо списка.",
|
||||
"label": "Вид сетки"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Использовать нативные системные иконки вместо иконок Tabler.",
|
||||
"label": "Использовать нативные иконки"
|
||||
},
|
||||
"position": {
|
||||
"description": "Выберите, где появляется панель запуска.",
|
||||
"label": "Положение"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "Если включено, часто запускаемые приложения появляются в списке первыми.",
|
||||
"label": "Сортировать по частоте использования"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Использовать нативные системные иконки вместо иконок Tabler.",
|
||||
"label": "Использовать нативные иконки"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Команда для запуска терминала. Например, 'kitty -e' или 'gnome-terminal --'.",
|
||||
"label": "Команда терминала"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "{app}'i kapat",
|
||||
"connect-vpn": "{name} bağlantısına bağlan",
|
||||
"cycle-visualizer": "Döngü görselleştirici",
|
||||
"delete": "Sil",
|
||||
"disable-bluetooth": "Bluetooth'u kapat",
|
||||
"disable-dnd": "Rahatsız Etmeyin'i Kapat",
|
||||
"disable-wifi": "Kablosuz Bağlantıyı kapat",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Araç ekle",
|
||||
"button": {
|
||||
"label": "Düzenleme moduna gir"
|
||||
},
|
||||
"controls-explanation": "Sol fare tuşu: Araç taşı\nSağ fare tuşu: Araç yeniden boyutlandır",
|
||||
"controls-explanation": "Sol tıklayıp sürükleyin: Bileşeni taşıyın veya yeniden boyutlandırın.\nSağ tıklayın: Bağlam menüsü seçeneklerini açın.",
|
||||
"description": "Masaüstü araçlarını taşımak ve yeniden konumlandırmak için düzenleme modunu etkinleştirin. Etkinleştirildiğinde, araçlar bir sürükleme ana hattı gösterir ve yeniden konumlandırılabilir.",
|
||||
"exit-button": "Düzenleme modundan çık",
|
||||
"grid-snap": {
|
||||
"label": "Izgaraya hizala"
|
||||
},
|
||||
"label": "Düzenleme modu"
|
||||
"label": "Düzenleme modu",
|
||||
"open-settings": "Ayarları aç"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Masaüstü araçlarını tamamen etkinleştir veya devre dışı bırak.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Öğeleri liste yerine ızgara düzeninde görüntüle.",
|
||||
"label": "Izgara görünümü"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Tabler simgeleri yerine yerel sistem simgelerini kullanın.",
|
||||
"label": "Yerel simgeleri kullan"
|
||||
},
|
||||
"position": {
|
||||
"description": "Başlatıcı panelinin nerede görüneceğini seçin.",
|
||||
"label": "Konum"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "Etkinleştirildiğinde, sıkça başlatılan uygulamalar listede ilk olarak görünür.",
|
||||
"label": "En çok kullanılana göre sırala"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Tabler simgeleri yerine yerel sistem simgelerini kullanın.",
|
||||
"label": "Yerel simgeleri kullan"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Bir terminal başlatmak için komut. Örn., 'kitty -e' veya 'gnome-terminal --'.",
|
||||
"label": "Terminal komutu"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "Закрити {app}",
|
||||
"connect-vpn": "Підключитися до {name}",
|
||||
"cycle-visualizer": "Візуалізатор циклів",
|
||||
"delete": "Видалити",
|
||||
"disable-bluetooth": "Вимкнути Bluetooth",
|
||||
"disable-dnd": "Вимкнути режим \"Не турбувати\"",
|
||||
"disable-wifi": "Вимкнути Wi-Fi",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "Додати віджет",
|
||||
"button": {
|
||||
"label": "Увійти в режим редагування"
|
||||
},
|
||||
"controls-explanation": "Ліва кнопка миші: Переміщувати віджет\nПрава кнопка миші: Змінювати розмір віджета",
|
||||
"controls-explanation": "Клацання лівою кнопкою миші та перетягування: Перемістити або змінити розмір віджета.\nКлацання правою кнопкою миші: Відкрити контекстне меню з опціями.",
|
||||
"description": "Увімкніть режим редагування, щоб переміщувати та змінювати розташування віджетів робочого столу. У ввімкненому стані віджети відображають контур перетягування, і їх можна переміщувати.",
|
||||
"exit-button": "Вийти з режиму редагування",
|
||||
"grid-snap": {
|
||||
"label": "Прив'язка до сітки"
|
||||
},
|
||||
"label": "Режим редагування"
|
||||
"label": "Режим редагування",
|
||||
"open-settings": "Відкрити налаштування"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Увімкнути або вимкнути віджети робочого столу повністю.",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "Показувати елементи у вигляді сітки замість списку.",
|
||||
"label": "Режим сітки"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Використовувати нативні системні іконки замість іконок Tabler.",
|
||||
"label": "Використовувати нативні іконки"
|
||||
},
|
||||
"position": {
|
||||
"description": "Виберіть, де з'являється панель лаунчера.",
|
||||
"label": "Положення"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "Коли увімкнено, часто використовувані застосунки з'являються першими в списку.",
|
||||
"label": "Сортувати за використанням"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "Використовувати нативні системні іконки замість іконок Tabler.",
|
||||
"label": "Використовувати нативні іконки"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "Команда для запуску терміналу. Напр., 'kitty -e' або 'gnome-terminal --'.",
|
||||
"label": "Команда терміналу"
|
||||
|
||||
@@ -527,6 +527,7 @@
|
||||
"close-app": "关闭 {app}",
|
||||
"connect-vpn": "连接 {name}",
|
||||
"cycle-visualizer": "切换可视化器样式",
|
||||
"delete": "删除",
|
||||
"disable-bluetooth": "禁用蓝牙",
|
||||
"disable-dnd": "关闭勿扰模式",
|
||||
"disable-wifi": "禁用Wi-Fi",
|
||||
@@ -1407,16 +1408,18 @@
|
||||
}
|
||||
},
|
||||
"edit-mode": {
|
||||
"add-widget": "添加小部件",
|
||||
"button": {
|
||||
"label": "进入编辑模式"
|
||||
},
|
||||
"controls-explanation": "鼠标左键:移动小组件\n鼠标右键:调整小组件大小",
|
||||
"controls-explanation": "左键点击并拖动:移动或调整小部件大小。\n右键点击:打开上下文菜单选项。",
|
||||
"description": "启用编辑模式以移动和重新定位桌面小组件。启用后,小组件会显示拖动轮廓,并且可以重新定位。",
|
||||
"exit-button": "退出编辑模式",
|
||||
"grid-snap": {
|
||||
"label": "网格对齐"
|
||||
},
|
||||
"label": "编辑模式"
|
||||
"label": "编辑模式",
|
||||
"open-settings": "打开设置"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "完全启用或禁用桌面小部件。",
|
||||
@@ -1758,6 +1761,10 @@
|
||||
"description": "以网格布局而非列表显示项目。",
|
||||
"label": "网格视图"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "使用本地系统图标而不是 Tabler 图标。",
|
||||
"label": "使用本地图标"
|
||||
},
|
||||
"position": {
|
||||
"description": "选择启动器面板出现的位置。",
|
||||
"label": "位置"
|
||||
@@ -1774,10 +1781,6 @@
|
||||
"description": "启用后,经常启动的应用程序将显示在列表首位。",
|
||||
"label": "按使用频率排序"
|
||||
},
|
||||
"icon-mode": {
|
||||
"description": "使用本地系统图标而不是 Tabler 图标。",
|
||||
"label": "使用本地图标"
|
||||
},
|
||||
"terminal-command": {
|
||||
"description": "启动终端的命令。例如,'kitty -e'或'gnome-terminal --'。",
|
||||
"label": "终端命令"
|
||||
|
||||
@@ -418,7 +418,6 @@
|
||||
},
|
||||
"desktopWidgets": {
|
||||
"enabled": false,
|
||||
"editMode": false,
|
||||
"gridSnap": false,
|
||||
"monitorWidgets": []
|
||||
}
|
||||
|
||||
@@ -652,7 +652,6 @@ Singleton {
|
||||
// desktop widgets
|
||||
property JsonObject desktopWidgets: JsonObject {
|
||||
property bool enabled: false
|
||||
property bool editMode: false
|
||||
property bool gridSnap: false
|
||||
property list<var> monitorWidgets: []
|
||||
// Format: [{ "name": "DP-1", "widgets": [...] }, { "name": "HDMI-1", "widgets": [...] }]
|
||||
|
||||
@@ -4,6 +4,7 @@ import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Modules.Panels.Settings
|
||||
import qs.Services.Compositor
|
||||
import qs.Services.Noctalia
|
||||
import qs.Services.Power
|
||||
@@ -70,6 +71,57 @@ Variants {
|
||||
Logger.d("DesktopWidgets", "Created panel window for", screen?.name);
|
||||
}
|
||||
|
||||
// Add a new widget to the current screen
|
||||
function addWidgetToCurrentScreen(widgetId) {
|
||||
var monitorName = window.screen.name;
|
||||
var newWidget = {
|
||||
"id": widgetId
|
||||
};
|
||||
|
||||
// Load default metadata if available
|
||||
var metadata = DesktopWidgetRegistry.widgetMetadata[widgetId];
|
||||
if (metadata) {
|
||||
Object.keys(metadata).forEach(function (key) {
|
||||
if (key !== "allowUserSettings") {
|
||||
newWidget[key] = metadata[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Place at screen center
|
||||
newWidget.x = (window.screen.width / 2) - 100;
|
||||
newWidget.y = (window.screen.height / 2) - 100;
|
||||
newWidget.scale = 1.0;
|
||||
|
||||
// Get current widgets and add new one
|
||||
var monitorWidgets = Settings.data.desktopWidgets.monitorWidgets || [];
|
||||
var newMonitorWidgets = monitorWidgets.slice();
|
||||
var found = false;
|
||||
|
||||
for (var i = 0; i < newMonitorWidgets.length; i++) {
|
||||
if (newMonitorWidgets[i].name === monitorName) {
|
||||
var widgets = (newMonitorWidgets[i].widgets || []).slice();
|
||||
widgets.push(newWidget);
|
||||
newMonitorWidgets[i] = {
|
||||
"name": monitorName,
|
||||
"widgets": widgets
|
||||
};
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
newMonitorWidgets.push({
|
||||
"name": monitorName,
|
||||
"widgets": [newWidget]
|
||||
});
|
||||
}
|
||||
|
||||
Settings.data.desktopWidgets.monitorWidgets = newMonitorWidgets;
|
||||
Logger.i("DesktopWidgets", "Added widget", widgetId, "to", monitorName);
|
||||
}
|
||||
|
||||
Item {
|
||||
id: widgetsContainer
|
||||
anchors.fill: parent
|
||||
@@ -78,7 +130,7 @@ Variants {
|
||||
// Using Loader to properly unload Canvas when not needed
|
||||
Loader {
|
||||
id: gridOverlayLoader
|
||||
active: Settings.data.desktopWidgets.editMode && Settings.data.desktopWidgets.enabled && Settings.data.desktopWidgets.gridSnap
|
||||
active: DesktopWidgetRegistry.editMode && Settings.data.desktopWidgets.enabled && Settings.data.desktopWidgets.gridSnap
|
||||
anchors.fill: parent
|
||||
z: -1 // Behind widgets but above background
|
||||
asynchronous: false
|
||||
@@ -197,6 +249,10 @@ Variants {
|
||||
gridOverlay.requestPaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: DesktopWidgetRegistry
|
||||
function onEditModeChanged() {
|
||||
if (gridOverlayLoader.active) {
|
||||
gridOverlay.requestPaint();
|
||||
@@ -245,140 +301,188 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
// Background for edit mode controls
|
||||
// Edit mode controls panel
|
||||
Rectangle {
|
||||
id: editModeControlsBackground
|
||||
visible: Settings.data.desktopWidgets.editMode && Settings.data.desktopWidgets.enabled
|
||||
id: editModeControlsPanel
|
||||
visible: DesktopWidgetRegistry.editMode && Settings.data.desktopWidgets.enabled
|
||||
|
||||
readonly property string barPos: Settings.data.bar.position || "top"
|
||||
readonly property bool barFloating: Settings.data.bar.floating || false
|
||||
// Calculate offset from bar based on position and floating state
|
||||
|
||||
readonly property int barOffsetTop: {
|
||||
if (barPos !== "top")
|
||||
return Style.marginXL * Style.uiScaleRatio;
|
||||
return Style.marginM;
|
||||
const floatMarginV = barFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0;
|
||||
return Style.barHeight + floatMarginV + Style.marginM + (Style.marginXL * Style.uiScaleRatio);
|
||||
return Style.barHeight + floatMarginV + Style.marginM;
|
||||
}
|
||||
readonly property int barOffsetRight: {
|
||||
if (barPos !== "right")
|
||||
return Style.marginXL * Style.uiScaleRatio;
|
||||
return Style.marginM;
|
||||
const floatMarginH = barFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0;
|
||||
return Style.barHeight + floatMarginH + Style.marginM + (Style.marginXL * Style.uiScaleRatio);
|
||||
return Style.barHeight + floatMarginH + Style.marginM;
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
topMargin: barOffsetTop
|
||||
rightMargin: barOffsetRight
|
||||
// Internal state for drag tracking (session-only, resets on restart)
|
||||
QtObject {
|
||||
id: panelInternal
|
||||
property bool isDragging: false
|
||||
property real dragOffsetX: 0
|
||||
property real dragOffsetY: 0
|
||||
// Default position: top-right corner accounting for bar
|
||||
property real baseX: widgetsContainer.width - editModeControlsPanel.width - editModeControlsPanel.barOffsetRight
|
||||
property real baseY: editModeControlsPanel.barOffsetTop
|
||||
}
|
||||
|
||||
// Calculate width to accommodate all controls
|
||||
width: {
|
||||
var buttonWidth = editModeButton.visible ? editModeButton.implicitWidth : 0;
|
||||
var explanationWidth = controlsExplanation.visible ? controlsExplanation.width : 0;
|
||||
var checkboxWidth = gridSnapCheckbox.visible ? gridSnapCheckbox.implicitWidth : 0;
|
||||
return Math.max(buttonWidth, explanationWidth, checkboxWidth, 200) + (Style.marginXL * 2);
|
||||
// Reset position when bar position changes
|
||||
Connections {
|
||||
target: Settings.data.bar
|
||||
function onPositionChanged() {
|
||||
panelInternal.baseX = widgetsContainer.width - editModeControlsPanel.width - editModeControlsPanel.barOffsetRight;
|
||||
panelInternal.baseY = editModeControlsPanel.barOffsetTop;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate height to cover all controls with spacing
|
||||
height: {
|
||||
var buttonHeight = editModeButton.visible ? editModeButton.height : 0;
|
||||
var explanationHeight = controlsExplanation.visible ? controlsExplanation.height : 0;
|
||||
var checkboxHeight = gridSnapCheckbox.visible ? gridSnapCheckbox.height : 0;
|
||||
return buttonHeight + Style.marginXL + explanationHeight + Style.marginXL + checkboxHeight + (Style.marginXL * 2);
|
||||
}
|
||||
x: panelInternal.isDragging ? panelInternal.dragOffsetX : panelInternal.baseX
|
||||
y: panelInternal.isDragging ? panelInternal.dragOffsetY : panelInternal.baseY
|
||||
|
||||
width: controlsLayout.implicitWidth + (Style.marginXL * 2)
|
||||
height: controlsLayout.implicitHeight + (Style.marginXL * 2)
|
||||
|
||||
color: Qt.rgba(Color.mSurface.r, Color.mSurface.g, Color.mSurface.b, 0.85)
|
||||
radius: Style.radiusL
|
||||
border {
|
||||
width: 1
|
||||
color: Qt.alpha(Color.mOutline, 0.2)
|
||||
width: Style.borderS
|
||||
color: Color.mOutline
|
||||
}
|
||||
z: 9999
|
||||
}
|
||||
|
||||
// Exit edit mode button
|
||||
NButton {
|
||||
id: editModeButton
|
||||
visible: Settings.data.desktopWidgets.editMode && Settings.data.desktopWidgets.enabled
|
||||
// Drag area for relocating the panel
|
||||
MouseArea {
|
||||
id: dragArea
|
||||
anchors.fill: parent
|
||||
cursorShape: panelInternal.isDragging ? Qt.ClosedHandCursor : Qt.OpenHandCursor
|
||||
|
||||
readonly property string barPos: Settings.data.bar.position || "top"
|
||||
readonly property bool barFloating: Settings.data.bar.floating || false
|
||||
// Calculate offset from bar based on position and floating state
|
||||
readonly property int barOffsetTop: {
|
||||
if (barPos !== "top")
|
||||
return Style.marginXL * Style.uiScaleRatio;
|
||||
const floatMarginV = barFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0;
|
||||
return Style.barHeight + floatMarginV + Style.marginM + (Style.marginXL * Style.uiScaleRatio);
|
||||
}
|
||||
readonly property int barOffsetRight: {
|
||||
if (barPos !== "right")
|
||||
return Style.marginXL * Style.uiScaleRatio;
|
||||
const floatMarginH = barFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0;
|
||||
return Style.barHeight + floatMarginH + Style.marginM + (Style.marginXL * Style.uiScaleRatio);
|
||||
property point pressPos: Qt.point(0, 0)
|
||||
|
||||
onPressed: mouse => {
|
||||
pressPos = mapToItem(widgetsContainer, mouse.x, mouse.y);
|
||||
panelInternal.dragOffsetX = editModeControlsPanel.x;
|
||||
panelInternal.dragOffsetY = editModeControlsPanel.y;
|
||||
panelInternal.isDragging = true;
|
||||
}
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
if (panelInternal.isDragging && pressed) {
|
||||
var currentPos = mapToItem(widgetsContainer, mouse.x, mouse.y);
|
||||
var deltaX = currentPos.x - pressPos.x;
|
||||
var deltaY = currentPos.y - pressPos.y;
|
||||
|
||||
var newX = panelInternal.baseX + deltaX;
|
||||
var newY = panelInternal.baseY + deltaY;
|
||||
|
||||
// Boundary clamping
|
||||
newX = Math.max(0, Math.min(newX, widgetsContainer.width - editModeControlsPanel.width));
|
||||
newY = Math.max(0, Math.min(newY, widgetsContainer.height - editModeControlsPanel.height));
|
||||
|
||||
panelInternal.dragOffsetX = newX;
|
||||
panelInternal.dragOffsetY = newY;
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (panelInternal.isDragging) {
|
||||
panelInternal.baseX = panelInternal.dragOffsetX;
|
||||
panelInternal.baseY = panelInternal.dragOffsetY;
|
||||
panelInternal.isDragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
onCanceled: {
|
||||
panelInternal.isDragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: editModeControlsBackground.top
|
||||
right: editModeControlsBackground.right
|
||||
topMargin: Style.marginXL
|
||||
rightMargin: Style.marginXL
|
||||
}
|
||||
text: I18n.tr("settings.desktop-widgets.edit-mode.exit-button")
|
||||
icon: "logout"
|
||||
//backgroundColor: Color.mSurface
|
||||
//textColor: Color.mOnSurface
|
||||
//hoverColor: Color.mSurfaceVariant
|
||||
outlined: false
|
||||
fontSize: Style.fontSizeM * 1.1
|
||||
iconSize: Style.fontSizeL * 1.1
|
||||
z: 10000
|
||||
onClicked: Settings.data.desktopWidgets.editMode = false
|
||||
}
|
||||
ColumnLayout {
|
||||
id: controlsLayout
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: Style.marginXL
|
||||
}
|
||||
spacing: Style.marginL
|
||||
|
||||
// Controls explanation text
|
||||
NText {
|
||||
id: controlsExplanation
|
||||
visible: Settings.data.desktopWidgets.editMode && Settings.data.desktopWidgets.enabled
|
||||
anchors {
|
||||
top: editModeButton.bottom
|
||||
right: editModeControlsBackground.right
|
||||
topMargin: Style.marginXL
|
||||
rightMargin: Style.marginXL
|
||||
}
|
||||
text: I18n.tr("settings.desktop-widgets.edit-mode.controls-explanation")
|
||||
pointSize: Style.fontSizeS
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignRight
|
||||
wrapMode: Text.WordWrap
|
||||
width: Math.min(implicitWidth, 300 * Style.uiScaleRatio)
|
||||
z: 10000
|
||||
}
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
spacing: Style.marginS
|
||||
|
||||
// Grid snap checkbox
|
||||
RowLayout {
|
||||
id: gridSnapCheckbox
|
||||
visible: Settings.data.desktopWidgets.editMode && Settings.data.desktopWidgets.enabled
|
||||
anchors {
|
||||
top: controlsExplanation.bottom
|
||||
right: editModeControlsBackground.right
|
||||
topMargin: Style.marginXL
|
||||
rightMargin: Style.marginXL
|
||||
}
|
||||
spacing: Style.marginS
|
||||
z: 10000
|
||||
NIconButton {
|
||||
id: addWidgetButton
|
||||
icon: "layout-grid-add"
|
||||
tooltipText: I18n.tr("settings.desktop-widgets.edit-mode.add-widget")
|
||||
onClicked: {
|
||||
var popupMenuWindow = PanelService.getPopupMenuWindow(window.screen);
|
||||
if (popupMenuWindow) {
|
||||
// Build menu items from registry
|
||||
var items = [];
|
||||
var widgets = DesktopWidgetRegistry.widgets;
|
||||
for (var id in widgets) {
|
||||
items.push({
|
||||
action: id,
|
||||
text: DesktopWidgetRegistry.getWidgetDisplayName(id),
|
||||
icon: "layout-grid-add"
|
||||
});
|
||||
}
|
||||
var globalPos = addWidgetButton.mapToItem(null, 0, addWidgetButton.height + Style.marginS);
|
||||
popupMenuWindow.showDynamicContextMenu(items, globalPos.x, globalPos.y, function (widgetId) {
|
||||
addWidgetToCurrentScreen(widgetId);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.desktop-widgets.edit-mode.grid-snap.label")
|
||||
pointSize: Style.fontSizeS
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
NIconButton {
|
||||
icon: "grid-4x4"
|
||||
tooltipText: I18n.tr("settings.desktop-widgets.edit-mode.grid-snap.label")
|
||||
colorBg: Settings.data.desktopWidgets.gridSnap ? Color.mPrimary : Color.mSurfaceVariant
|
||||
colorFg: Settings.data.desktopWidgets.gridSnap ? Color.mOnPrimary : Color.mPrimary
|
||||
onClicked: Settings.data.desktopWidgets.gridSnap = !Settings.data.desktopWidgets.gridSnap
|
||||
}
|
||||
|
||||
NCheckbox {
|
||||
checked: Settings.data.desktopWidgets.gridSnap
|
||||
onToggled: checked => Settings.data.desktopWidgets.gridSnap = checked
|
||||
NIconButton {
|
||||
icon: "settings"
|
||||
tooltipText: I18n.tr("settings.desktop-widgets.edit-mode.open-settings")
|
||||
onClicked: {
|
||||
if (Settings.data.ui.settingsPanelMode === "window") {
|
||||
SettingsPanelService.toggleWindow(SettingsPanel.Tab.DesktopWidgets);
|
||||
} else {
|
||||
var settingsPanel = PanelService.getPanel("settingsPanel", screenLoader.modelData);
|
||||
if (settingsPanel) {
|
||||
settingsPanel.requestedTab = SettingsPanel.Tab.DesktopWidgets;
|
||||
settingsPanel.toggle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NButton {
|
||||
text: I18n.tr("settings.desktop-widgets.edit-mode.exit-button")
|
||||
icon: "logout"
|
||||
outlined: false
|
||||
fontSize: Style.fontSizeS
|
||||
iconSize: Style.fontSizeM
|
||||
onClicked: DesktopWidgetRegistry.editMode = false
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.maximumWidth: 300 * Style.uiScaleRatio
|
||||
text: I18n.tr("settings.desktop-widgets.edit-mode.controls-explanation")
|
||||
pointSize: Style.fontSizeS
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignRight
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ import QtQuick
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Services.Noctalia
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -26,6 +29,7 @@ Item {
|
||||
|
||||
readonly property real scaleSensitivity: 0.0015
|
||||
readonly property real scaleUpdateThreshold: 0.015
|
||||
readonly property real cornerScaleSensitivity: 0.0003 // Much lower sensitivity for corner handles
|
||||
|
||||
// Grid size ensures lines pass through screen center on both axes
|
||||
readonly property int gridSize: {
|
||||
@@ -133,6 +137,105 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
function removeWidget() {
|
||||
if (widgetIndex < 0 || !screen || !screen.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
var monitorWidgets = Settings.data.desktopWidgets.monitorWidgets || [];
|
||||
var newMonitorWidgets = monitorWidgets.slice();
|
||||
|
||||
for (var i = 0; i < newMonitorWidgets.length; i++) {
|
||||
if (newMonitorWidgets[i].name === screen.name) {
|
||||
var widgets = (newMonitorWidgets[i].widgets || []).slice();
|
||||
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||
widgets.splice(widgetIndex, 1);
|
||||
newMonitorWidgets[i] = Object.assign({}, newMonitorWidgets[i], {
|
||||
"widgets": widgets
|
||||
});
|
||||
Settings.data.desktopWidgets.monitorWidgets = newMonitorWidgets;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openWidgetSettings() {
|
||||
if (!widgetData || !widgetData.id || !screen) {
|
||||
return;
|
||||
}
|
||||
|
||||
var widgetId = widgetData.id;
|
||||
var hasSettings = false;
|
||||
|
||||
// Check if widget has settings
|
||||
if (DesktopWidgetRegistry.isPluginWidget(widgetId)) {
|
||||
var pluginId = widgetId.replace("plugin:", "");
|
||||
var manifest = PluginRegistry.getPluginManifest(pluginId);
|
||||
if (manifest && manifest.entryPoints && manifest.entryPoints.settings) {
|
||||
hasSettings = true;
|
||||
}
|
||||
} else {
|
||||
hasSettings = DesktopWidgetRegistry.widgetSettingsMap[widgetId] !== undefined;
|
||||
}
|
||||
|
||||
if (!hasSettings) {
|
||||
Logger.w("DraggableDesktopWidget", "Widget does not have settings:", widgetId);
|
||||
return;
|
||||
}
|
||||
|
||||
var popupMenuWindow = PanelService.getPopupMenuWindow(screen);
|
||||
if (!popupMenuWindow) {
|
||||
Logger.e("DraggableDesktopWidget", "No popup menu window found for screen");
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide the dynamic context menu (popup window stays open for the dialog)
|
||||
if (popupMenuWindow.hideDynamicMenu) {
|
||||
popupMenuWindow.hideDynamicMenu();
|
||||
}
|
||||
|
||||
var component = Qt.createComponent(Quickshell.shellDir + "/Modules/Panels/Settings/DesktopWidgets/DesktopWidgetSettingsDialog.qml");
|
||||
|
||||
function instantiateAndOpen() {
|
||||
var dialog = component.createObject(popupMenuWindow.dialogParent, {
|
||||
"widgetIndex": widgetIndex,
|
||||
"widgetData": widgetData,
|
||||
"widgetId": widgetId,
|
||||
"sectionId": screen.name
|
||||
});
|
||||
|
||||
if (dialog) {
|
||||
dialog.updateWidgetSettings.connect((sec, idx, settings) => {
|
||||
root.updateWidgetData(settings);
|
||||
});
|
||||
popupMenuWindow.hasDialog = true;
|
||||
dialog.closed.connect(() => {
|
||||
popupMenuWindow.hasDialog = false;
|
||||
popupMenuWindow.close();
|
||||
dialog.destroy();
|
||||
});
|
||||
dialog.open();
|
||||
} else {
|
||||
Logger.e("DraggableDesktopWidget", "Failed to create widget settings dialog");
|
||||
}
|
||||
}
|
||||
|
||||
if (component.status === Component.Ready) {
|
||||
instantiateAndOpen();
|
||||
} else if (component.status === Component.Error) {
|
||||
Logger.e("DraggableDesktopWidget", "Error loading settings dialog component:", component.errorString());
|
||||
} else {
|
||||
component.statusChanged.connect(() => {
|
||||
if (component.status === Component.Ready) {
|
||||
instantiateAndOpen();
|
||||
} else if (component.status === Component.Error) {
|
||||
Logger.e("DraggableDesktopWidget", "Error loading settings dialog component:", component.errorString());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
x: internal.isDragging ? internal.dragOffsetX : internal.baseX
|
||||
y: internal.isDragging ? internal.dragOffsetY : internal.baseY
|
||||
|
||||
@@ -173,10 +276,10 @@ Item {
|
||||
id: decorationRect
|
||||
anchors.fill: parent
|
||||
anchors.margins: -Style.marginS
|
||||
color: Settings.data.desktopWidgets.editMode ? Qt.rgba(Color.mPrimary.r, Color.mPrimary.g, Color.mPrimary.b, 0.1) : Color.transparent
|
||||
border.color: (Settings.data.desktopWidgets.editMode || internal.isDragging) ? (internal.isDragging ? Color.mOutline : Color.mPrimary) : Color.transparent
|
||||
border.width: Settings.data.desktopWidgets.editMode ? 3 : (internal.isDragging ? 2 : 0)
|
||||
radius: Style.radiusL + Style.marginS
|
||||
color: DesktopWidgetRegistry.editMode ? Qt.rgba(Color.mPrimary.r, Color.mPrimary.g, Color.mPrimary.b, 0.1) : Color.transparent
|
||||
border.color: (DesktopWidgetRegistry.editMode || internal.isDragging) ? (internal.isDragging ? Color.mOutline : Color.mPrimary) : Color.transparent
|
||||
border.width: DesktopWidgetRegistry.editMode ? 3 : 0
|
||||
radius: Style.radiusL
|
||||
z: -1
|
||||
}
|
||||
|
||||
@@ -210,26 +313,59 @@ Item {
|
||||
z: 1
|
||||
}
|
||||
|
||||
// Drag and Scale MouseArea - handles both dragging (left-click) and scaling (right-click)
|
||||
// Context menu model and handler - menu is created dynamically in PopupMenuWindow
|
||||
property var contextMenuModel: {
|
||||
var hasSettings = false;
|
||||
if (widgetData && widgetData.id) {
|
||||
var widgetId = widgetData.id;
|
||||
if (DesktopWidgetRegistry.isPluginWidget(widgetId)) {
|
||||
var pluginId = widgetId.replace("plugin:", "");
|
||||
var manifest = PluginRegistry.getPluginManifest(pluginId);
|
||||
hasSettings = manifest && manifest.entryPoints && manifest.entryPoints.settings;
|
||||
} else {
|
||||
hasSettings = DesktopWidgetRegistry.widgetSettingsMap[widgetId] !== undefined;
|
||||
}
|
||||
}
|
||||
|
||||
var items = [];
|
||||
if (hasSettings) {
|
||||
items.push({
|
||||
"label": I18n.tr("context-menu.widget-settings"),
|
||||
"action": "widget-settings",
|
||||
"icon": "settings"
|
||||
});
|
||||
}
|
||||
items.push({
|
||||
"label": I18n.tr("context-menu.delete"),
|
||||
"action": "delete",
|
||||
"icon": "trash"
|
||||
});
|
||||
return items;
|
||||
}
|
||||
|
||||
function handleContextMenuAction(action) {
|
||||
if (action === "widget-settings") {
|
||||
// Don't close - openWidgetSettings will use the popup window for the dialog
|
||||
root.openWidgetSettings();
|
||||
return true; // Signal that we're handling close ourselves
|
||||
} else if (action === "delete") {
|
||||
root.removeWidget();
|
||||
return false; // Let caller close the popup
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Drag MouseArea - handles dragging (left-click)
|
||||
MouseArea {
|
||||
id: interactionArea
|
||||
id: dragArea
|
||||
anchors.fill: parent
|
||||
z: 1000
|
||||
visible: Settings.data.desktopWidgets.editMode
|
||||
cursorShape: {
|
||||
if (internal.isDragging)
|
||||
return Qt.ClosedHandCursor;
|
||||
if (internal.isScaling)
|
||||
return Qt.SizeAllCursor;
|
||||
// Change cursor based on which button user is likely to press
|
||||
// Right mouse button for scaling, left for dragging
|
||||
return Qt.OpenHandCursor;
|
||||
}
|
||||
visible: DesktopWidgetRegistry.editMode
|
||||
cursorShape: internal.isDragging ? Qt.ClosedHandCursor : Qt.OpenHandCursor
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
acceptedButtons: Qt.LeftButton
|
||||
|
||||
property point pressPos: Qt.point(0, 0)
|
||||
property real initialScale: 1.0
|
||||
|
||||
onPressed: mouse => {
|
||||
// Prevent starting new operation if one is already in progress
|
||||
@@ -238,21 +374,10 @@ Item {
|
||||
}
|
||||
|
||||
pressPos = Qt.point(mouse.x, mouse.y);
|
||||
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
internal.operationType = "drag";
|
||||
internal.dragOffsetX = root.x;
|
||||
internal.dragOffsetY = root.y;
|
||||
internal.isDragging = true;
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
internal.operationType = "scale";
|
||||
internal.isScaling = true;
|
||||
internal.initialWidth = root.width;
|
||||
internal.initialHeight = root.height;
|
||||
internal.initialMousePos = Qt.point(mouse.x, mouse.y);
|
||||
internal.initialScale = root.widgetScale;
|
||||
internal.lastScale = root.widgetScale;
|
||||
}
|
||||
internal.operationType = "drag";
|
||||
internal.dragOffsetX = root.x;
|
||||
internal.dragOffsetY = root.y;
|
||||
internal.isDragging = true;
|
||||
}
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
@@ -263,7 +388,6 @@ Item {
|
||||
var deltaX = globalCurrentPos.x - globalPressPos.x;
|
||||
var deltaY = globalCurrentPos.y - globalPressPos.y;
|
||||
|
||||
// Calculate new position based on original position when drag started
|
||||
var newX = internal.dragOffsetX + deltaX;
|
||||
var newY = internal.dragOffsetY + deltaY;
|
||||
|
||||
@@ -287,24 +411,6 @@ Item {
|
||||
|
||||
internal.dragOffsetX = newX;
|
||||
internal.dragOffsetY = newY;
|
||||
} else if (internal.isScaling && pressed && internal.operationType === "scale") {
|
||||
var dx = mouse.x - internal.initialMousePos.x;
|
||||
var dy = mouse.y - internal.initialMousePos.y;
|
||||
|
||||
// Use primary direction of movement to determine scale change
|
||||
var primaryMovement = (Math.abs(dx) > Math.abs(dy)) ? dx : dy;
|
||||
|
||||
// Scale change relative to initial widget size ensures consistent behavior
|
||||
var scaleChange = primaryMovement * root.scaleSensitivity;
|
||||
|
||||
// Add to last applied scale (not initial) to allow smooth continuous scaling
|
||||
var newScale = Math.max(minScale, Math.min(maxScale, internal.lastScale + scaleChange));
|
||||
|
||||
// Apply smoothing threshold to prevent rapid changes
|
||||
if (Math.abs(root.widgetScale - newScale) > root.scaleUpdateThreshold && !isNaN(newScale) && newScale > 0) {
|
||||
root.widgetScale = newScale;
|
||||
internal.lastScale = newScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,23 +426,185 @@ Item {
|
||||
internal.centerX = internal.baseX + root.width / 2;
|
||||
internal.isDragging = false;
|
||||
internal.operationType = "";
|
||||
} else if (internal.isScaling && internal.operationType === "scale") {
|
||||
root.updateWidgetData({
|
||||
"scale": root.widgetScale
|
||||
});
|
||||
|
||||
internal.isScaling = false;
|
||||
internal.operationType = "";
|
||||
internal.lastScale = root.widgetScale;
|
||||
}
|
||||
}
|
||||
|
||||
onCanceled: {
|
||||
internal.isDragging = false;
|
||||
internal.isScaling = false;
|
||||
internal.operationType = "";
|
||||
// Sync lastScale when operation is canceled to prevent drift
|
||||
internal.lastScale = root.widgetScale;
|
||||
}
|
||||
}
|
||||
|
||||
// Right-click MouseArea for context menu
|
||||
MouseArea {
|
||||
id: contextMenuArea
|
||||
anchors.fill: parent
|
||||
z: 1001
|
||||
visible: DesktopWidgetRegistry.editMode
|
||||
acceptedButtons: Qt.RightButton
|
||||
hoverEnabled: true
|
||||
|
||||
onPressed: mouse => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
var popupMenuWindow = PanelService.getPopupMenuWindow(root.screen);
|
||||
if (popupMenuWindow) {
|
||||
// Map click position to screen coordinates
|
||||
var globalPos = root.mapToItem(null, mouse.x, mouse.y);
|
||||
// Use dynamic context menu (created in PopupMenuWindow's Top layer)
|
||||
// This ensures input events work correctly for desktop widgets (Bottom layer)
|
||||
popupMenuWindow.showDynamicContextMenu(root.contextMenuModel, globalPos.x, globalPos.y, root.handleContextMenuAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Corner handles for scaling - using Repeater to avoid code duplication
|
||||
readonly property real cornerHandleSize: 8
|
||||
readonly property real outlineMargin: Style.marginS
|
||||
readonly property color colorHandle: Color.mSecondary
|
||||
|
||||
// Corner handle model: defines position, opposite corner, cursor, and triangle points for each corner
|
||||
// xMult/yMult: multipliers for position (0 = left/top edge, 1 = right/bottom edge)
|
||||
// oppXMult/oppYMult: multipliers for opposite corner calculation
|
||||
// cursor: resize cursor type (FDiag for TL-BR diagonal, BDiag for TR-BL diagonal)
|
||||
// points: triangle vertices as [x, y] pairs normalized to cornerHandleSize
|
||||
readonly property var cornerHandleModel: [
|
||||
{
|
||||
xMult: 0,
|
||||
yMult: 0,
|
||||
oppXMult: 1,
|
||||
oppYMult: 1,
|
||||
cursor: Qt.SizeFDiagCursor,
|
||||
points: [[0, 0], [1, 0], [0, 1]]
|
||||
},
|
||||
{
|
||||
xMult: 1,
|
||||
yMult: 0,
|
||||
oppXMult: 0,
|
||||
oppYMult: 1,
|
||||
cursor: Qt.SizeBDiagCursor,
|
||||
points: [[1, 0], [1, 1], [0, 0]]
|
||||
},
|
||||
{
|
||||
xMult: 0,
|
||||
yMult: 1,
|
||||
oppXMult: 1,
|
||||
oppYMult: 0,
|
||||
cursor: Qt.SizeBDiagCursor,
|
||||
points: [[0, 1], [0, 0], [1, 1]]
|
||||
},
|
||||
{
|
||||
xMult: 1,
|
||||
yMult: 1,
|
||||
oppXMult: 0,
|
||||
oppYMult: 0,
|
||||
cursor: Qt.SizeFDiagCursor,
|
||||
points: [[1, 1], [1, 0], [0, 1]]
|
||||
}
|
||||
]
|
||||
|
||||
Repeater {
|
||||
model: root.cornerHandleModel
|
||||
|
||||
delegate: Canvas {
|
||||
id: cornerHandle
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
visible: DesktopWidgetRegistry.editMode && !internal.isDragging
|
||||
x: modelData.xMult * (root.width + outlineMargin) - (modelData.xMult === 0 ? outlineMargin : cornerHandleSize)
|
||||
y: modelData.yMult * (root.height + outlineMargin) - (modelData.yMult === 0 ? outlineMargin : cornerHandleSize)
|
||||
width: cornerHandleSize
|
||||
height: cornerHandleSize
|
||||
z: 2000
|
||||
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.reset();
|
||||
ctx.fillStyle = colorHandle;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(modelData.points[0][0] * cornerHandleSize, modelData.points[0][1] * cornerHandleSize);
|
||||
ctx.lineTo(modelData.points[1][0] * cornerHandleSize, modelData.points[1][1] * cornerHandleSize);
|
||||
ctx.lineTo(modelData.points[2][0] * cornerHandleSize, modelData.points[2][1] * cornerHandleSize);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
Component.onCompleted: requestPaint()
|
||||
onVisibleChanged: if (visible)
|
||||
requestPaint()
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onWidthChanged() {
|
||||
if (cornerHandle.visible)
|
||||
cornerHandle.requestPaint();
|
||||
}
|
||||
function onHeightChanged() {
|
||||
if (cornerHandle.visible)
|
||||
cornerHandle.requestPaint();
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: scaleMouseArea
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
cursorShape: cornerHandle.modelData.cursor
|
||||
property point pressPos: Qt.point(0, 0)
|
||||
// Capture opposite corner at press time to avoid feedback loop during scaling
|
||||
property real oppositeCornerX: 0
|
||||
property real oppositeCornerY: 0
|
||||
property real initialDistance: 0
|
||||
|
||||
onPressed: mouse => {
|
||||
if (internal.operationType !== "") {
|
||||
return;
|
||||
}
|
||||
pressPos = mapToItem(root.parent, mouse.x, mouse.y);
|
||||
// Calculate and store opposite corner position using initial scale
|
||||
oppositeCornerX = root.x + cornerHandle.modelData.oppXMult * root.width * root.widgetScale;
|
||||
oppositeCornerY = root.y + cornerHandle.modelData.oppYMult * root.height * root.widgetScale;
|
||||
initialDistance = Math.sqrt(Math.pow(pressPos.x - oppositeCornerX, 2) + Math.pow(pressPos.y - oppositeCornerY, 2));
|
||||
internal.operationType = "scale";
|
||||
internal.isScaling = true;
|
||||
internal.initialScale = root.widgetScale;
|
||||
internal.lastScale = root.widgetScale;
|
||||
}
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
if (internal.isScaling && pressed && internal.operationType === "scale" && initialDistance > 0) {
|
||||
var currentPos = mapToItem(root.parent, mouse.x, mouse.y);
|
||||
// Use the fixed opposite corner position captured at press time
|
||||
var currentDistance = Math.sqrt(Math.pow(currentPos.x - oppositeCornerX, 2) + Math.pow(currentPos.y - oppositeCornerY, 2));
|
||||
|
||||
var scaleRatio = currentDistance / initialDistance;
|
||||
var newScale = Math.max(minScale, Math.min(maxScale, internal.initialScale * scaleRatio));
|
||||
|
||||
if (!isNaN(newScale) && newScale > 0) {
|
||||
root.widgetScale = newScale;
|
||||
internal.lastScale = newScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: mouse => {
|
||||
if (internal.isScaling && internal.operationType === "scale") {
|
||||
root.updateWidgetData({
|
||||
"scale": root.widgetScale
|
||||
});
|
||||
internal.isScaling = false;
|
||||
internal.operationType = "";
|
||||
internal.lastScale = root.widgetScale;
|
||||
}
|
||||
}
|
||||
|
||||
onCanceled: {
|
||||
internal.isScaling = false;
|
||||
internal.operationType = "";
|
||||
internal.lastScale = root.widgetScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Modules.DesktopWidgets
|
||||
import qs.Services.Media
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
import qs.Widgets.AudioSpectrum
|
||||
|
||||
@@ -22,7 +23,7 @@ DraggableDesktopWidget {
|
||||
// State
|
||||
readonly property bool shouldHideIdle: (hideMode === "idle") && !isPlaying
|
||||
readonly property bool shouldHideEmpty: !hasPlayer && hideMode === "hidden"
|
||||
readonly property bool isHidden: (shouldHideIdle || shouldHideEmpty) && !Settings.data.desktopWidgets.editMode
|
||||
readonly property bool isHidden: (shouldHideIdle || shouldHideEmpty) && !DesktopWidgetRegistry.editMode
|
||||
visible: !isHidden
|
||||
|
||||
// CavaService registration for visualizer
|
||||
|
||||
@@ -3,6 +3,7 @@ import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
// Generic full-screen popup window for menus and context menus
|
||||
// This is a top-level PanelWindow (sibling to MainScreen, not nested inside it)
|
||||
@@ -20,6 +21,9 @@ PanelWindow {
|
||||
// Expose the trayMenu Loader directly (for backward compatibility)
|
||||
readonly property alias trayMenuLoader: trayMenuLoader
|
||||
|
||||
// Dynamic context menu callback for items in other windows (e.g., desktop widgets)
|
||||
property var dynamicMenuCallback: null
|
||||
|
||||
anchors.top: true
|
||||
anchors.left: true
|
||||
anchors.right: true
|
||||
@@ -55,6 +59,26 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic context menu - created as child of this window (Top layer) so input works correctly
|
||||
// Used for items in other windows like desktop widgets (bottom layer)
|
||||
NPopupContextMenu {
|
||||
id: dynamicMenu
|
||||
visible: false
|
||||
screen: root.screen
|
||||
|
||||
onTriggered: (action, item) => {
|
||||
if (root.dynamicMenuCallback) {
|
||||
// Callback returns true if it will handle closing (e.g., opening a dialog)
|
||||
var handled = root.dynamicMenuCallback(action);
|
||||
if (!handled) {
|
||||
root.close();
|
||||
}
|
||||
} else {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function open() {
|
||||
visible = true;
|
||||
}
|
||||
@@ -67,6 +91,35 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// Show a dynamic context menu with model and callback at screen coordinates
|
||||
// Used for items in other window layers (e.g., desktop widgets in bottom layer)
|
||||
function showDynamicContextMenu(model, screenX, screenY, callback) {
|
||||
dynamicMenu.model = model;
|
||||
dynamicMenuCallback = callback;
|
||||
|
||||
// Use the anchor point item for positioning at absolute coordinates
|
||||
dynamicMenu.anchorItem = anchorPoint;
|
||||
anchorPoint.x = screenX;
|
||||
anchorPoint.y = screenY;
|
||||
|
||||
contentItem = dynamicMenu;
|
||||
dynamicMenu.visible = true;
|
||||
open();
|
||||
}
|
||||
|
||||
// Invisible anchor point for dynamic menu positioning
|
||||
Item {
|
||||
id: anchorPoint
|
||||
width: 1
|
||||
height: 1
|
||||
}
|
||||
|
||||
// Hide just the dynamic menu without closing the popup window
|
||||
// Used when transitioning from context menu to a dialog
|
||||
function hideDynamicMenu() {
|
||||
dynamicMenu.visible = false;
|
||||
}
|
||||
|
||||
function close() {
|
||||
visible = false;
|
||||
// Call close/hide method on current content
|
||||
@@ -77,6 +130,9 @@ PanelWindow {
|
||||
contentItem.close();
|
||||
}
|
||||
}
|
||||
// Hide dynamic menu
|
||||
dynamicMenu.visible = false;
|
||||
dynamicMenuCallback = null;
|
||||
// Restore TrayMenu as default content
|
||||
if (trayMenuLoader.item) {
|
||||
contentItem = trayMenuLoader.item;
|
||||
|
||||
@@ -45,11 +45,11 @@ ColumnLayout {
|
||||
NButton {
|
||||
visible: Settings.data.desktopWidgets.enabled
|
||||
Layout.fillWidth: true
|
||||
text: Settings.data.desktopWidgets.editMode ? I18n.tr("settings.desktop-widgets.edit-mode.exit-button") : I18n.tr("settings.desktop-widgets.edit-mode.button.label")
|
||||
text: DesktopWidgetRegistry.editMode ? I18n.tr("settings.desktop-widgets.edit-mode.exit-button") : I18n.tr("settings.desktop-widgets.edit-mode.button.label")
|
||||
icon: "edit"
|
||||
onClicked: {
|
||||
Settings.data.desktopWidgets.editMode = !Settings.data.desktopWidgets.editMode;
|
||||
if (Settings.data.desktopWidgets.editMode && Settings.data.ui.settingsPanelMode !== "window") {
|
||||
DesktopWidgetRegistry.editMode = !DesktopWidgetRegistry.editMode;
|
||||
if (DesktopWidgetRegistry.editMode && Settings.data.ui.settingsPanelMode !== "window") {
|
||||
var item = root.parent;
|
||||
while (item) {
|
||||
if (item.closeRequested !== undefined) {
|
||||
|
||||
@@ -490,7 +490,7 @@ Item {
|
||||
Settings.data.desktopWidgets.enabled = true;
|
||||
}
|
||||
function edit() {
|
||||
Settings.data.desktopWidgets.editMode = !Settings.data.desktopWidgets.editMode;
|
||||
DesktopWidgetRegistry.editMode = !DesktopWidgetRegistry.editMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,14 @@ import QtQuick
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Modules.DesktopWidgets.Widgets
|
||||
import qs.Services.Noctalia
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
// Transient state - not persisted, resets on shell restart
|
||||
property bool editMode: false
|
||||
|
||||
// Signal emitted when plugin widgets are registered/unregistered
|
||||
signal pluginWidgetRegistryUpdated
|
||||
|
||||
@@ -111,6 +115,17 @@ Singleton {
|
||||
return Object.keys(pluginWidgets);
|
||||
}
|
||||
|
||||
// Get display name for a widget ID
|
||||
function getWidgetDisplayName(widgetId) {
|
||||
if (widgetId.startsWith("plugin:")) {
|
||||
var pluginId = widgetId.replace("plugin:", "");
|
||||
var manifest = PluginRegistry.getPluginManifest(pluginId);
|
||||
return manifest ? manifest.name : pluginId;
|
||||
}
|
||||
// Core widgets - return as-is (Clock, MediaPlayer, Weather)
|
||||
return widgetId;
|
||||
}
|
||||
|
||||
// Register a plugin desktop widget
|
||||
function registerPluginWidget(pluginId, component, metadata) {
|
||||
if (!pluginId || !component) {
|
||||
|
||||
@@ -118,6 +118,22 @@ PopupWindow {
|
||||
}
|
||||
anchor.rect.y: {
|
||||
if (anchorItem && screen) {
|
||||
// Check if using absolute positioning (small anchor point item)
|
||||
const isAbsolutePosition = anchorItem.width <= 1 && anchorItem.height <= 1;
|
||||
|
||||
if (isAbsolutePosition) {
|
||||
// For absolute positioning, show menu directly at anchor Y
|
||||
// Only adjust if menu would clip at bottom
|
||||
const anchorGlobalPos = anchorItem.mapToItem(null, 0, 0);
|
||||
const menuBottom = anchorGlobalPos.y + implicitHeight;
|
||||
|
||||
if (menuBottom > screen.height - Style.marginM) {
|
||||
// Position above the click point instead
|
||||
return -implicitHeight;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const anchorCenterY = anchorItem.height / 2;
|
||||
|
||||
// Calculate base Y position based on bar orientation
|
||||
|
||||
Reference in New Issue
Block a user