(Init): Added shit
This commit is contained in:
155
nirimod/pages/workspaces.py
Normal file
155
nirimod/pages/workspaces.py
Normal file
@@ -0,0 +1,155 @@
|
||||
"""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")
|
||||
Reference in New Issue
Block a user