fix(ui): reorder partition dialog, fix mount point selection, add threaded install with logs

This commit is contained in:
2026-02-03 21:06:16 +01:00
parent af86d357a4
commit 7d43b82ce1
2 changed files with 101 additions and 39 deletions

View File

@@ -476,10 +476,14 @@ class PartitioningPage(Adw.Bin):
dropdown = Gtk.DropDown.new_from_strings(options) dropdown = Gtk.DropDown.new_from_strings(options)
current_mp = data.get("mount_point") current_mp = data.get("mount_point")
# Ensure we have a valid string comparison
if not current_mp:
current_mp = "None"
if current_mp in options: if current_mp in options:
dropdown.set_selected(options.index(current_mp)) dropdown.set_selected(options.index(current_mp))
elif not current_mp: else:
dropdown.set_selected(options.index("None")) dropdown.set_selected(options.index("None"))
box.append(Gtk.Label(label=f"Mount point for {data['name']}:")) box.append(Gtk.Label(label=f"Mount point for {data['name']}:"))
box.append(dropdown) box.append(dropdown)
@@ -511,6 +515,13 @@ class PartitioningPage(Adw.Bin):
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12, margin_top=24, margin_bottom=24, margin_start=24, margin_end=24) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12, margin_top=24, margin_bottom=24, margin_start=24, margin_end=24)
win.set_content(box) win.set_content(box)
# Type dropdown
types = {"Root (Linux)": "8300", "EFI System": "ef00", "Swap": "8200"}
type_names = list(types.keys())
type_dropdown = Gtk.DropDown.new_from_strings(type_names)
box.append(Gtk.Label(label="Partition Type:"))
box.append(type_dropdown)
# Size entry # Size entry
size_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12) size_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
size_entry = Gtk.Entry(text=str(int(data["bytes"] / (1024*1024)))) size_entry = Gtk.Entry(text=str(int(data["bytes"] / (1024*1024))))
@@ -519,13 +530,6 @@ class PartitioningPage(Adw.Bin):
box.append(Gtk.Label(label="Size:")) box.append(Gtk.Label(label="Size:"))
box.append(size_box) box.append(size_box)
# Type dropdown
types = {"Root (Linux)": "8300", "EFI System": "ef00", "Swap": "8200"}
type_names = list(types.keys())
type_dropdown = Gtk.DropDown.new_from_strings(type_names)
box.append(Gtk.Label(label="Partition Type:"))
box.append(type_dropdown)
error_label = Gtk.Label(label="") error_label = Gtk.Label(label="")
error_label.add_css_class("error") error_label.add_css_class("error")
box.append(error_label) box.append(error_label)

View File

@@ -1,8 +1,10 @@
import gi import gi
import threading
import logging
gi.require_version("Gtk", "4.0") gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1") gi.require_version("Adw", "1")
from gi.repository import Adw, Gtk from gi.repository import Adw, Gtk, GLib
from .pages.additional_modules import ModulesPage from .pages.additional_modules import ModulesPage
from .pages.install_mode import InstallModePage from .pages.install_mode import InstallModePage
@@ -13,6 +15,16 @@ from .pages.user import UserPage
from .pages.welcome import WelcomePage from .pages.welcome import WelcomePage
class LogHandler(logging.Handler):
def __init__(self, callback):
super().__init__()
self.callback = callback
def emit(self, record):
msg = self.format(record)
GLib.idle_add(self.callback, msg)
class InstallerWindow(Adw.ApplicationWindow): class InstallerWindow(Adw.ApplicationWindow):
def __init__(self, mock_mode=False, *args, **kwargs): def __init__(self, mock_mode=False, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@@ -91,6 +103,8 @@ class InstallerWindow(Adw.ApplicationWindow):
self.stack.set_visible_child_name(self.page_ids[0]) self.stack.set_visible_child_name(self.page_ids[0])
self.update_buttons() self.update_buttons()
self.log_handler = None
def add_page(self, widget, name): def add_page(self, widget, name):
self.stack.add_named(widget, name) self.stack.add_named(widget, name)
self.page_ids.append(name) self.page_ids.append(name)
@@ -157,6 +171,28 @@ class InstallerWindow(Adw.ApplicationWindow):
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
box.append(spinner) box.append(spinner)
# Log view
self.log_buffer = Gtk.TextBuffer()
self.log_view = Gtk.TextView(buffer=self.log_buffer)
self.log_view.set_editable(False)
self.log_view.set_monospace(True)
self.log_view.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
scrolled = Gtk.ScrolledWindow()
scrolled.set_child(self.log_view)
scrolled.set_vexpand(True)
scrolled.set_size_request(-1, 200)
# Style the log view background
# css_provider = Gtk.CssProvider()
# css_provider.load_from_data(b"textview { background-color: #1e1e1e; color: #ffffff; }")
# self.log_view.get_style_context().add_provider(css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
expander = Gtk.Expander(label="Detailed Logs")
expander.set_child(scrolled)
box.append(expander)
prog_page.set_child(box) prog_page.set_child(box)
name = "progress_install" name = "progress_install"
@@ -166,7 +202,23 @@ class InstallerWindow(Adw.ApplicationWindow):
# Hide navigation buttons during install # Hide navigation buttons during install
self.bottom_bar.set_visible(False) self.bottom_bar.set_visible(False)
# Attach log handler
self.log_handler = LogHandler(self.append_log)
logging.getLogger().addHandler(self.log_handler)
logging.getLogger().setLevel(logging.INFO)
def append_log(self, msg):
end_iter = self.log_buffer.get_end_iter()
self.log_buffer.insert(end_iter, msg + "\n")
# Auto-scroll
mark = self.log_buffer.create_mark("end", end_iter, False)
self.log_view.scroll_to_mark(mark, 0.0, True, 0.0, 1.0)
def show_finish_page(self, message, success=True): def show_finish_page(self, message, success=True):
if self.log_handler:
logging.getLogger().removeHandler(self.log_handler)
self.log_handler = None
finish_page = Adw.StatusPage() finish_page = Adw.StatusPage()
finish_page.set_title(message) finish_page.set_title(message)
if success: if success:
@@ -189,6 +241,35 @@ class InstallerWindow(Adw.ApplicationWindow):
self.stack.add_named(finish_page, name) self.stack.add_named(finish_page, name)
self.stack.set_visible_child_name(name) self.stack.set_visible_child_name(name)
def run_installation(self, disk, mode, modules, user_info):
try:
from ..backend.disk import auto_partition_disk, mount_partitions
from ..backend.os_install import install_minimal_os, configure_system
# Step 1: Partitioning
logging.info("Step 1: Partitioning...")
parts = auto_partition_disk(disk)
# Step 2: Mounting
logging.info("Step 2: Mounting...")
mount_root = "/mnt"
mount_partitions(parts, mount_root)
# Step 3: OS Installation
logging.info("Step 3: OS Installation...")
install_minimal_os(mount_root)
# Step 4: Configure
logging.info("Step 4: Configuration...")
configure_system(mount_root, parts)
GLib.idle_add(self.show_finish_page, "Installation Successful!", True)
except Exception as e:
logging.error(f"Installation failed: {e}")
import traceback
traceback.print_exc()
GLib.idle_add(self.show_finish_page, f"Installation Failed: {e}", False)
def on_next_clicked(self, button): def on_next_clicked(self, button):
# Logic before transition # Logic before transition
current_page_name = self.page_ids[self.current_page_index] current_page_name = self.page_ids[self.current_page_index]
@@ -250,36 +331,13 @@ class InstallerWindow(Adw.ApplicationWindow):
# Show success in UI even in mock # Show success in UI even in mock
self.show_finish_page("Mock Installation Complete!") self.show_finish_page("Mock Installation Complete!")
else: else:
from ..backend.disk import auto_partition_disk, mount_partitions
from ..backend.os_install import install_minimal_os, configure_system
# Simple progress UI transition
self.show_progress_page("Installing Iridium OS...") self.show_progress_page("Installing Iridium OS...")
thread = threading.Thread(
# We should really run this in a thread to keep UI responsive, target=self.run_installation,
# but for "barely bootable" requirement and simplicity: args=(disk, mode, modules, user_info),
try: daemon=True
# Step 1: Partitioning )
print("Step 1: Partitioning...") thread.start()
parts = auto_partition_disk(disk)
# Step 2: Mounting
print("Step 2: Mounting...")
mount_root = "/mnt"
mount_partitions(parts, mount_root)
# Step 3: OS Installation
print("Step 3: OS Installation...")
install_minimal_os(mount_root)
# Step 4: Configure
print("Step 4: Configuration...")
configure_system(mount_root, parts)
self.show_finish_page("Installation Successful!")
except Exception as e:
print(f"Installation failed: {e}")
self.show_finish_page(f"Installation Failed: {e}", success=False)
return return