mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
NSectionEditor: added ability to move Desktop widgets from one screen to another.
This commit is contained in:
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Mittlere Sektion",
|
||||
"move-to-left-section": "Linke Sektion",
|
||||
"move-to-right-section": "Rechte Sektion",
|
||||
"move-to-section": "Gehe zu {section}",
|
||||
"mute": "Stummschalten",
|
||||
"next-media": "Nächster Titel",
|
||||
"next-month": "Nächster Monat",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Center section",
|
||||
"move-to-left-section": "Left section",
|
||||
"move-to-right-section": "Right section",
|
||||
"move-to-section": "Move to {section}",
|
||||
"mute": "Mute",
|
||||
"next-media": "Next track",
|
||||
"next-month": "Next month",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Sección central",
|
||||
"move-to-left-section": "Sección izquierda",
|
||||
"move-to-right-section": "Sección derecha",
|
||||
"move-to-section": "Mover a {section}",
|
||||
"mute": "Silenciar",
|
||||
"next-media": "Siguiente pista",
|
||||
"next-month": "Mes siguiente",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Section centrale",
|
||||
"move-to-left-section": "Section de gauche",
|
||||
"move-to-right-section": "Section de droite",
|
||||
"move-to-section": "Aller à {section}",
|
||||
"mute": "Muet / Couper le son",
|
||||
"next-media": "Piste suivante",
|
||||
"next-month": "Mois suivant",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Középső szakasz",
|
||||
"move-to-left-section": "Bal oldali szakasz",
|
||||
"move-to-right-section": "Jobb oldali szakasz",
|
||||
"move-to-section": "Ugrás a(z) {section} szakaszhoz",
|
||||
"mute": "Némítás",
|
||||
"next-media": "Következő zene",
|
||||
"next-month": "Következő hónap",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "中央セクション",
|
||||
"move-to-left-section": "左セクション",
|
||||
"move-to-right-section": "右セクション",
|
||||
"move-to-section": "{section} に移動",
|
||||
"mute": "ミュート",
|
||||
"next-media": "次のトラック",
|
||||
"next-month": "翌月",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Navenda beşê",
|
||||
"move-to-left-section": "Beşa çepê",
|
||||
"move-to-right-section": "Beşa rastê",
|
||||
"move-to-section": "Here'ke {section} here.",
|
||||
"mute": "Bêdeng bike",
|
||||
"next-media": "Strana pêş",
|
||||
"next-month": "Meha bê",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Middelste sectie",
|
||||
"move-to-left-section": "Linker sectie",
|
||||
"move-to-right-section": "Rechter sectie",
|
||||
"move-to-section": "Ga naar {section}",
|
||||
"mute": "Dempen",
|
||||
"next-media": "Volgende track",
|
||||
"next-month": "Volgende maand",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Sekcja środkowa",
|
||||
"move-to-left-section": "Sekcja lewa",
|
||||
"move-to-right-section": "Sekcja prawa",
|
||||
"move-to-section": "Przejdź do {sekcja}",
|
||||
"mute": "Wycisz",
|
||||
"next-media": "Następny utwór",
|
||||
"next-month": "Następny miesiąc",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Seção central",
|
||||
"move-to-left-section": "Seção esquerda",
|
||||
"move-to-right-section": "Seção direita",
|
||||
"move-to-section": "Mover para {section}",
|
||||
"mute": "Silenciar",
|
||||
"next-media": "Próxima faixa",
|
||||
"next-month": "Próximo mês",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Центральная секция",
|
||||
"move-to-left-section": "Левая секция",
|
||||
"move-to-right-section": "Правая секция",
|
||||
"move-to-section": "Перейти к {section}",
|
||||
"mute": "Отключить звук",
|
||||
"next-media": "Следующий трек",
|
||||
"next-month": "Следующий месяц",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Orta bölüm",
|
||||
"move-to-left-section": "Sol bölüm",
|
||||
"move-to-right-section": "Sağ bölüm",
|
||||
"move-to-section": "{section} bölümüne git.",
|
||||
"mute": "Sessiz",
|
||||
"next-media": "Sonraki parça",
|
||||
"next-month": "Sonraki ay",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "Центральна секція",
|
||||
"move-to-left-section": "Ліва секція",
|
||||
"move-to-right-section": "Права секція",
|
||||
"move-to-section": "Перейти до {section}",
|
||||
"mute": "Вимкнути звук",
|
||||
"next-media": "Наступний трек",
|
||||
"next-month": "Наступний місяць",
|
||||
|
||||
@@ -2879,6 +2879,7 @@
|
||||
"move-to-center-section": "中央部分",
|
||||
"move-to-left-section": "左侧部分",
|
||||
"move-to-right-section": "右侧部分",
|
||||
"move-to-section": "移至{section}",
|
||||
"mute": "静音",
|
||||
"next-media": "下一首",
|
||||
"next-month": "下个月",
|
||||
|
||||
@@ -67,6 +67,34 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Helper to get screen names array
|
||||
function getScreenNames() {
|
||||
var names = [];
|
||||
for (var i = 0; i < Quickshell.screens.length; i++) {
|
||||
names.push(Quickshell.screens[i].name);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
// Helper to get screen labels map (just screen names, NSectionEditor adds "Move to" prefix)
|
||||
function getScreenLabels() {
|
||||
var labels = {};
|
||||
for (var i = 0; i < Quickshell.screens.length; i++) {
|
||||
var screen = Quickshell.screens[i];
|
||||
labels[screen.name] = screen.name;
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
// Helper to get screen icons map
|
||||
function getScreenIcons() {
|
||||
var icons = {};
|
||||
for (var i = 0; i < Quickshell.screens.length; i++) {
|
||||
icons[Quickshell.screens[i].name] = "device-desktop";
|
||||
}
|
||||
return icons;
|
||||
}
|
||||
|
||||
// One NSectionEditor per monitor
|
||||
Repeater {
|
||||
model: Settings.data.desktopWidgets.enabled ? Quickshell.screens : []
|
||||
@@ -88,11 +116,14 @@ ColumnLayout {
|
||||
widgetRegistry: DesktopWidgetRegistry
|
||||
widgetModel: getWidgetsForMonitor(modelData.name)
|
||||
availableWidgets: root.availableWidgetsModel
|
||||
availableSections: [] // No sections to move between - hides move menu items
|
||||
availableSections: root.getScreenNames()
|
||||
sectionLabels: root.getScreenLabels()
|
||||
sectionIcons: root.getScreenIcons()
|
||||
draggable: false // Desktop widgets are positioned by X,Y, not list order
|
||||
maxWidgets: -1
|
||||
onAddWidget: (widgetId, section) => _addWidgetToMonitor(modelData.name, widgetId)
|
||||
onRemoveWidget: (section, index) => _removeWidgetFromMonitor(modelData.name, index)
|
||||
onMoveWidget: (fromSection, index, toSection) => _moveWidgetToMonitor(fromSection, index, toSection)
|
||||
onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsForMonitor(modelData.name, index, settings)
|
||||
onOpenPluginSettingsRequested: manifest => pluginSettingsDialog.openPluginSettings(manifest)
|
||||
}
|
||||
@@ -251,4 +282,30 @@ ColumnLayout {
|
||||
setWidgetsForMonitor(monitorName, newArray);
|
||||
}
|
||||
}
|
||||
|
||||
function _moveWidgetToMonitor(fromMonitor, index, toMonitor) {
|
||||
Logger.i("DesktopWidgetsTab", "Moving widget from", fromMonitor, "index", index, "to", toMonitor);
|
||||
var sourceWidgets = getWidgetsForMonitor(fromMonitor);
|
||||
if (index < 0 || index >= sourceWidgets.length) {
|
||||
Logger.e("DesktopWidgetsTab", "Invalid index", index, "for monitor", fromMonitor);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the widget to move
|
||||
var newSourceWidgets = sourceWidgets.slice();
|
||||
var widget = Object.assign({}, newSourceWidgets.splice(index, 1)[0]);
|
||||
|
||||
// Reset position and scale to ensure widget is accessible on new screen
|
||||
widget.x = 100;
|
||||
widget.y = 100;
|
||||
widget.scale = 1.0;
|
||||
|
||||
// Add to destination monitor
|
||||
var destWidgets = getWidgetsForMonitor(toMonitor).slice();
|
||||
destWidgets.push(widget);
|
||||
|
||||
// Update both monitors
|
||||
setWidgetsForMonitor(fromMonitor, newSourceWidgets);
|
||||
setWidgetsForMonitor(toMonitor, destWidgets);
|
||||
}
|
||||
}
|
||||
|
||||
+47
-27
@@ -15,9 +15,27 @@ NBox {
|
||||
property var widgetModel: []
|
||||
property var availableWidgets: []
|
||||
property var availableSections: ["left", "center", "right"]
|
||||
property var sectionLabels: ({}) // Map of sectionId -> display label
|
||||
property var sectionIcons: ({}) // Map of sectionId -> icon name
|
||||
property int maxWidgets: -1 // -1 means unlimited
|
||||
property bool draggable: true // Enable/disable drag reordering
|
||||
|
||||
// Get display label for a section
|
||||
function getSectionLabel(sectionId) {
|
||||
if (sectionLabels && sectionLabels[sectionId]) {
|
||||
return sectionLabels[sectionId];
|
||||
}
|
||||
return sectionId; // Fallback to section ID
|
||||
}
|
||||
|
||||
// Get icon for a section
|
||||
function getSectionIcon(sectionId) {
|
||||
if (sectionIcons && sectionIcons[sectionId]) {
|
||||
return sectionIcons[sectionId];
|
||||
}
|
||||
return "arrow-right"; // Default fallback icon
|
||||
}
|
||||
|
||||
property var widgetRegistry: null
|
||||
property string settingsDialogComponent: "BarWidgetSettingsDialog.qml"
|
||||
|
||||
@@ -281,38 +299,40 @@ NBox {
|
||||
id: contextMenu
|
||||
parent: Overlay.overlay
|
||||
width: 240 * Style.uiScaleRatio
|
||||
model: [
|
||||
{
|
||||
"label": I18n.tr("tooltips.move-to-left-section"),
|
||||
"action": "left",
|
||||
"icon": "arrow-bar-to-left",
|
||||
"visible": root.availableSections.includes("left") && root.sectionId !== "left"
|
||||
},
|
||||
{
|
||||
"label": I18n.tr("tooltips.move-to-center-section"),
|
||||
"action": "center",
|
||||
"icon": "layout-columns",
|
||||
"visible": root.availableSections.includes("center") && root.sectionId !== "center"
|
||||
},
|
||||
{
|
||||
"label": I18n.tr("tooltips.move-to-right-section"),
|
||||
"action": "right",
|
||||
"icon": "arrow-bar-to-right",
|
||||
"visible": root.availableSections.includes("right") && root.sectionId !== "right"
|
||||
},
|
||||
{
|
||||
"label": I18n.tr("tooltips.remove-widget"),
|
||||
"action": "remove",
|
||||
"icon": "trash",
|
||||
"visible": true
|
||||
model: {
|
||||
var items = [];
|
||||
// Add move options for each available section (except current)
|
||||
for (var i = 0; i < root.availableSections.length; i++) {
|
||||
var section = root.availableSections[i];
|
||||
if (section !== root.sectionId) {
|
||||
var label = root.getSectionLabel(section);
|
||||
// Capitalize first letter
|
||||
var capitalizedLabel = label.charAt(0).toUpperCase() + label.slice(1);
|
||||
items.push({
|
||||
"label": I18n.tr("tooltips.move-to-section", {
|
||||
"section": capitalizedLabel
|
||||
}),
|
||||
"action": section,
|
||||
"icon": root.getSectionIcon(section),
|
||||
"visible": true
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
// Add remove option
|
||||
items.push({
|
||||
"label": I18n.tr("tooltips.remove-widget"),
|
||||
"action": "remove",
|
||||
"icon": "trash",
|
||||
"visible": true
|
||||
});
|
||||
return items;
|
||||
}
|
||||
|
||||
onTriggered: action => {
|
||||
if (action === "remove") {
|
||||
root.removeWidget(root.sectionId, index);
|
||||
root.removeWidget(root.sectionId, widgetItem.index);
|
||||
} else {
|
||||
root.moveWidget(root.sectionId, index, action);
|
||||
root.moveWidget(root.sectionId, widgetItem.index, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user