import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from models import ServiceType, HostType class HostItem: def __init__(self, host, open_service_callback): self.host = host self.open_service_callback = open_service_callback self.widget = self._create_widget() def _create_widget(self): # Clean horizontal layout without borders host_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=4) # Host header host_header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8) host_box.pack_start(host_header, False, False, 0) # Host type icon type_icons = { HostType.LINUX: "🐧", HostType.WINDOWS: "🪟", HostType.WINDOWS_SERVER: "🖥️", HostType.PROXMOX: "📦", HostType.ESXI: "📦", HostType.ROUTER: "🌐", HostType.SWITCH: "🔗" } icon = type_icons.get(self.host.host_type, "💻") icon_label = Gtk.Label(label=icon) host_header.pack_start(icon_label, False, False, 0) # Host details - compact single line details_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=1) host_header.pack_start(details_vbox, True, True, 0) # Host name with IP inline name_label = Gtk.Label() name_label.set_markup(f"{self.host.name} ({self.host.host_type.value}) - {self.host.ip_address}") name_label.set_halign(Gtk.Align.START) details_vbox.pack_start(name_label, False, False, 0) # Services section - compact button row if self.host.services: services_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=4) services_box.set_margin_start(16) # Indent services services_box.set_margin_top(4) host_box.pack_start(services_box, False, False, 0) for service in self.host.services: if service.service_type in [ServiceType.WEB_GUI, ServiceType.SSH, ServiceType.RDP]: # Only show launchable services service_btn = Gtk.Button(label=service.service_type.value) service_btn.get_style_context().add_class("suggested-action") service_btn.connect("clicked", lambda btn, s=service: self._on_service_clicked(s)) services_box.pack_start(service_btn, False, False, 0) # Sub-hosts (VMs) section if self.host.sub_hosts: subhost_label = Gtk.Label() subhost_label.set_markup(f"Virtual Machines ({len(self.host.sub_hosts)})") subhost_label.set_halign(Gtk.Align.START) subhost_label.set_margin_top(8) subhost_label.set_margin_start(16) host_box.pack_start(subhost_label, False, False, 0) subhosts_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=4) subhosts_box.set_margin_start(32) # Double indent for VMs host_box.pack_start(subhosts_box, False, False, 0) for subhost in self.host.sub_hosts: subhost_item = HostItem(subhost, self.open_service_callback) subhosts_box.pack_start(subhost_item.widget, False, False, 0) return host_box def _on_service_clicked(self, service): self.open_service_callback(service)