156 lines
5.1 KiB
Python
156 lines
5.1 KiB
Python
"""Workspaces page."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
import gi
|
|
|
|
gi.require_version("Gtk", "4.0")
|
|
gi.require_version("Adw", "1")
|
|
from gi.repository import Adw, Gtk
|
|
|
|
from nirimod.kdl_parser import KdlNode, set_child_arg
|
|
from nirimod import niri_ipc
|
|
from nirimod.pages.base import BasePage
|
|
|
|
|
|
class WorkspacesPage(BasePage):
|
|
def build(self) -> Gtk.Widget:
|
|
tb, header, _, content = self._make_toolbar_page("Workspaces")
|
|
self._content = content
|
|
|
|
add_btn = Gtk.Button(icon_name="list-add-symbolic")
|
|
add_btn.add_css_class("flat")
|
|
add_btn.connect("clicked", self._on_add)
|
|
header.pack_end(add_btn)
|
|
|
|
self._grp = Adw.PreferencesGroup(
|
|
title="Named Workspaces",
|
|
description="Named workspaces open immediately at niri startup",
|
|
)
|
|
content.append(self._grp)
|
|
self.refresh()
|
|
return tb
|
|
|
|
def refresh(self):
|
|
self._rebuild()
|
|
|
|
def _get_ws_nodes(self) -> list[KdlNode]:
|
|
return [n for n in self._nodes if n.name == "workspace"]
|
|
|
|
def _rebuild(self):
|
|
parent = self._grp.get_parent()
|
|
if parent is None:
|
|
return
|
|
|
|
def _on_outputs(outputs_data):
|
|
ws_nodes = self._get_ws_nodes()
|
|
outputs = [o.get("name", "") for o in outputs_data]
|
|
output_model = Gtk.StringList.new(["(any)"] + outputs)
|
|
|
|
new_grp = Adw.PreferencesGroup(
|
|
title="Named Workspaces", description=f"{len(ws_nodes)} workspace(s)"
|
|
)
|
|
for i, ws in enumerate(ws_nodes):
|
|
row = self._make_ws_row(ws, i, outputs, output_model)
|
|
new_grp.add(row)
|
|
parent.remove(self._grp)
|
|
parent.append(new_grp)
|
|
self._grp = new_grp
|
|
|
|
niri_ipc.get_outputs(_on_outputs)
|
|
|
|
def _make_ws_row(
|
|
self, ws: KdlNode, idx: int, outputs: list[str], output_model: Gtk.StringList
|
|
) -> Adw.ExpanderRow:
|
|
name = ws.args[0] if ws.args else f"workspace-{idx + 1}"
|
|
assigned_out = ws.child_arg("open-on-output") or ""
|
|
|
|
exp = Adw.ExpanderRow(title=name)
|
|
|
|
name_row = Adw.EntryRow(title="Name")
|
|
name_row.set_text(str(name))
|
|
name_row.set_show_apply_button(True)
|
|
name_row.connect("apply", lambda r, i=idx: self._rename_ws(i, r.get_text()))
|
|
exp.add_row(name_row)
|
|
|
|
out_row = Adw.ComboRow(title="Open on Output")
|
|
out_list = ["(any)"] + outputs
|
|
out_row.set_model(Gtk.StringList.new(out_list))
|
|
if assigned_out in outputs:
|
|
out_row.set_selected(out_list.index(assigned_out))
|
|
out_row.connect(
|
|
"notify::selected",
|
|
lambda r, _, i=idx, ol=out_list: self._set_ws_output(
|
|
i, ol[r.get_selected()]
|
|
),
|
|
)
|
|
exp.add_row(out_row)
|
|
|
|
del_btn = Gtk.Button(icon_name="user-trash-symbolic")
|
|
del_btn.add_css_class("flat")
|
|
del_btn.add_css_class("error")
|
|
del_btn.set_valign(Gtk.Align.CENTER)
|
|
del_btn.connect("clicked", lambda *_, i=idx: self._on_delete(i))
|
|
exp.add_suffix(del_btn)
|
|
|
|
return exp
|
|
|
|
def _on_add(self, *_):
|
|
dialog = Adw.AlertDialog(
|
|
heading="Add Workspace", body="Enter a name for the new workspace."
|
|
)
|
|
entry = Adw.EntryRow(title="Workspace Name")
|
|
grp = Adw.PreferencesGroup()
|
|
grp.add(entry)
|
|
dialog.set_extra_child(grp)
|
|
dialog.add_response("cancel", "Cancel")
|
|
dialog.add_response("add", "Add")
|
|
dialog.set_response_appearance("add", Adw.ResponseAppearance.SUGGESTED)
|
|
|
|
def _on_resp(d, r):
|
|
if r != "add":
|
|
return
|
|
name = entry.get_text().strip()
|
|
if not name:
|
|
return
|
|
node = KdlNode("workspace", args=[name])
|
|
ws_nodes = self._get_ws_nodes()
|
|
if ws_nodes:
|
|
last_idx = self._nodes.index(ws_nodes[-1])
|
|
self._nodes.insert(last_idx + 1, node)
|
|
else:
|
|
# If no workspaces, insert at the top
|
|
self._nodes.insert(0, node)
|
|
self._commit("add workspace")
|
|
self._rebuild()
|
|
|
|
dialog.connect("response", _on_resp)
|
|
dialog.present(self._win)
|
|
|
|
def _on_delete(self, idx: int):
|
|
ws_nodes = self._get_ws_nodes()
|
|
if 0 <= idx < len(ws_nodes):
|
|
self._nodes.remove(ws_nodes[idx])
|
|
self._commit("remove workspace")
|
|
self._rebuild()
|
|
|
|
def _rename_ws(self, idx: int, name: str):
|
|
ws_nodes = self._get_ws_nodes()
|
|
if 0 <= idx < len(ws_nodes) and name.strip():
|
|
ws_nodes[idx].args = [name.strip()]
|
|
self._commit("rename workspace")
|
|
self._rebuild()
|
|
|
|
def _set_ws_output(self, idx: int, output: str):
|
|
ws_nodes = self._get_ws_nodes()
|
|
if 0 <= idx < len(ws_nodes):
|
|
ws = ws_nodes[idx]
|
|
if output and output != "(any)":
|
|
set_child_arg(ws, "open-on-output", output)
|
|
else:
|
|
from nirimod.kdl_parser import remove_child
|
|
|
|
remove_child(ws, "open-on-output")
|
|
self._commit("workspace output")
|