81 lines
3.5 KiB
Python
81 lines
3.5 KiB
Python
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"<b>{self.host.name}</b> <small>({self.host.host_type.value}) - <tt>{self.host.ip_address}</tt></small>")
|
|
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"<b><small>Virtual Machines ({len(self.host.sub_hosts)})</small></b>")
|
|
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) |