#!/usr/bin/env python3 # Steuerpanel: bleibt offen, bis das Fenster geschlossen wird. import os import shlex import subprocess import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk DIR = "/home/arbeit/projects/project-starter" ARBEIT = os.path.expanduser("~/arbeit") CLAUDE_PROMPT = ( "Verschaff dir kurz Projekt-Ueberblick (ddev, shopware 6). " "Lies dann /tmp/redmine-{nr}/data.json (enthaelt Redmine Issue + Briefing-Wiki) " "sowie ggf. Bilder unter /tmp/redmine-{nr}/. " "Liste die fuer das Ticket noetigen Features als knappe Bullet-Liste auf - " "vollstaendig, nichts weglassen, aber auch nicht aufgeblaeht. Simpel und kurz." ) def referenzprojekte(): namen = [e for e in os.listdir(ARBEIT) if os.path.isdir(os.path.join(ARBEIT, e, ".ddev"))] return sorted(namen, key=str.lower) def im_terminal(befehl, arbeitsverzeichnis=None): aufruf = ["gnome-terminal"] if arbeitsverzeichnis: aufruf += ["--working-directory", arbeitsverzeichnis] aufruf += ["--", "bash", "-c", befehl + "; exec bash"] subprocess.Popen(aufruf) class Panel(Gtk.Window): def __init__(self): super().__init__(title="Projekt Panel") self.set_border_width(8) self.connect("destroy", Gtk.main_quit) raster = Gtk.Grid(row_spacing=6, column_spacing=8) self.add(raster) raster.attach(Gtk.Label(label="Ticket-Nr", xalign=0), 0, 0, 1, 1) self.ticket = Gtk.Entry(hexpand=True, width_chars=30) raster.attach(self.ticket, 1, 0, 1, 1) raster.attach(Gtk.Label(label="Referenzprojekt", xalign=0), 0, 1, 1, 1) self.referenz = Gtk.ComboBoxText() for name in referenzprojekte(): self.referenz.append_text(name) self.referenz.set_active(0) raster.attach(self.referenz, 1, 1, 1, 1) knopfreihe = Gtk.Box(spacing=6, homogeneous=True) raster.attach(knopfreihe, 0, 2, 2, 1) for beschriftung, aktion in ( ("Ticketdaten abrufen", self.ticketdaten), ("Projekt setup", self.projekt_setup), ("Terminal starten", self.terminal_starten), ("DB anpassen", self.db_anpassen), ): knopf = Gtk.Button(label=beschriftung) knopf.connect("clicked", aktion) knopfreihe.pack_start(knopf, True, True, 0) def fehler(self, text): dialog = Gtk.MessageDialog(transient_for=self, modal=True, message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK, text=text) dialog.run() dialog.destroy() def ticket_nr(self): nr = self.ticket.get_text().strip() if not nr: self.fehler("Ticket-Nr fehlt.") return None return nr def ticketdaten(self, _knopf): nr = self.ticket_nr() if nr: im_terminal(f"{shlex.quote(DIR + '/ticket-daten')} {shlex.quote(nr)}") def projekt_setup(self, _knopf): nr = self.ticket_nr() if not nr: return referenz = self.referenz.get_active_text() or "" pfad = os.path.join(ARBEIT, referenz) if not os.path.isdir(os.path.join(pfad, ".ddev")): self.fehler(f"Kein ddev-Projekt: {pfad}") return im_terminal(f"{shlex.quote(DIR + '/ticket-setup')} " f"{shlex.quote(nr)} {shlex.quote(pfad)}") def terminal_starten(self, _knopf): nr = self.ticket_nr() if not nr: return ziel = os.path.join(ARBEIT, "tickets", nr) if not os.path.isdir(ziel): self.fehler(f"{ziel} gibt es noch nicht. Erst Projekt setup.") return prompt = CLAUDE_PROMPT.format(nr=nr) im_terminal(f"claude {shlex.quote(prompt)}", arbeitsverzeichnis=ziel) def db_anpassen(self, _knopf): referenz = self.referenz.get_active_text() or "" pfad = os.path.join(ARBEIT, referenz) if not os.path.isdir(os.path.join(pfad, ".ddev")): self.fehler(f"Kein ddev-Projekt: {pfad}") return im_terminal(f"{shlex.quote(DIR + '/db-anpassen')} {shlex.quote(pfad)}") panel = Panel() panel.show_all() Gtk.main()