Add mock mode support and input validation
This commit is contained in:
@@ -1,14 +1,22 @@
|
||||
import re
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version("Gtk", "4.0")
|
||||
gi.require_version("Adw", "1")
|
||||
from gi.repository import Adw, Gtk
|
||||
from gi.repository import Adw, GObject, Gtk
|
||||
|
||||
|
||||
class UserPage(Adw.Bin):
|
||||
__gsignals__ = {
|
||||
"validity-changed": (GObject.SignalFlags.RUN_FIRST, None, (bool,)),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._is_valid = False
|
||||
|
||||
clamp = Adw.Clamp()
|
||||
clamp.set_maximum_size(500)
|
||||
self.set_child(clamp)
|
||||
@@ -32,6 +40,7 @@ class UserPage(Adw.Bin):
|
||||
self.fullname_row.set_title("Full Name")
|
||||
self.fullname_row.set_text("Administrator")
|
||||
self.fullname_row.connect("notify::text", self.on_fullname_changed)
|
||||
self.fullname_row.connect("notify::text", self.on_input_changed)
|
||||
group.add(self.fullname_row)
|
||||
|
||||
self.username_row = Adw.EntryRow()
|
||||
@@ -40,14 +49,17 @@ class UserPage(Adw.Bin):
|
||||
self.username_handler_id = self.username_row.connect(
|
||||
"notify::text", self.on_username_changed
|
||||
)
|
||||
self.username_row.connect("notify::text", self.on_input_changed)
|
||||
group.add(self.username_row)
|
||||
|
||||
self.password_row = Adw.PasswordEntryRow()
|
||||
self.password_row.set_title("Password")
|
||||
self.password_row.connect("notify::text", self.on_input_changed)
|
||||
group.add(self.password_row)
|
||||
|
||||
self.confirm_row = Adw.PasswordEntryRow()
|
||||
self.confirm_row.set_title("Confirm Password")
|
||||
self.confirm_row.connect("notify::text", self.on_input_changed)
|
||||
group.add(self.confirm_row)
|
||||
|
||||
# Hostname
|
||||
@@ -58,10 +70,14 @@ class UserPage(Adw.Bin):
|
||||
self.hostname_row = Adw.EntryRow()
|
||||
self.hostname_row.set_title("Hostname")
|
||||
self.hostname_row.set_text("iridium")
|
||||
self.hostname_row.connect("notify::text", self.on_input_changed)
|
||||
host_group.add(self.hostname_row)
|
||||
|
||||
self.username_manually_set = False
|
||||
|
||||
# Initial validation
|
||||
self.validate()
|
||||
|
||||
def on_fullname_changed(self, entry, _pspec):
|
||||
if self.username_manually_set:
|
||||
return
|
||||
@@ -113,6 +129,53 @@ class UserPage(Adw.Bin):
|
||||
def on_username_changed(self, entry, _pspec):
|
||||
self.username_manually_set = True
|
||||
|
||||
def on_input_changed(self, *args):
|
||||
self.validate()
|
||||
|
||||
def validate(self):
|
||||
valid = True
|
||||
|
||||
# Username validation
|
||||
username = self.username_row.get_text()
|
||||
if not username:
|
||||
valid = False
|
||||
self.username_row.add_css_class("error")
|
||||
elif not re.match(r"^[a-z_][a-z0-9_-]*$", username):
|
||||
valid = False
|
||||
self.username_row.add_css_class("error")
|
||||
else:
|
||||
self.username_row.remove_css_class("error")
|
||||
|
||||
# Password validation
|
||||
pw = self.password_row.get_text()
|
||||
confirm = self.confirm_row.get_text()
|
||||
|
||||
if not pw:
|
||||
valid = False
|
||||
# Don't show error for empty password initially, just invalidate
|
||||
# It looks a lot nicer like that
|
||||
|
||||
if pw != confirm:
|
||||
valid = False
|
||||
self.confirm_row.add_css_class("error")
|
||||
else:
|
||||
self.confirm_row.remove_css_class("error")
|
||||
|
||||
# Hostname validation
|
||||
hostname = self.hostname_row.get_text()
|
||||
if not hostname:
|
||||
valid = False
|
||||
self.hostname_row.add_css_class("error")
|
||||
else:
|
||||
self.hostname_row.remove_css_class("error")
|
||||
|
||||
if self._is_valid != valid:
|
||||
self._is_valid = valid
|
||||
self.emit("validity-changed", valid)
|
||||
|
||||
def is_valid(self):
|
||||
return self._is_valid
|
||||
|
||||
def get_user_info(self):
|
||||
return {
|
||||
"fullname": self.fullname_row.get_text(),
|
||||
|
||||
@@ -8,17 +8,19 @@ from .pages.additional_modules import ModulesPage
|
||||
from .pages.install_mode import InstallModePage
|
||||
from .pages.partitioning import PartitioningPage, calculate_auto_partitions
|
||||
from .pages.storage import StoragePage
|
||||
from .pages.summary import SummaryPage
|
||||
from .pages.user import UserPage
|
||||
from .pages.welcome import WelcomePage
|
||||
from .pages.summary import SummaryPage
|
||||
|
||||
|
||||
class InstallerWindow(Adw.ApplicationWindow):
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, mock_mode=False, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.mock_mode = mock_mode
|
||||
|
||||
self.set_default_size(900, 650)
|
||||
self.set_title("Iridium Installer")
|
||||
self.set_title("Iridium Installer" + (" (MOCK MODE)" if mock_mode else ""))
|
||||
|
||||
self.toolbar_view = Adw.ToolbarView()
|
||||
self.set_content(self.toolbar_view)
|
||||
@@ -71,6 +73,7 @@ class InstallerWindow(Adw.ApplicationWindow):
|
||||
self.partitioning_page = PartitioningPage()
|
||||
self.modules_page = ModulesPage()
|
||||
self.user_page = UserPage()
|
||||
self.user_page.connect("validity-changed", self.on_user_validity_changed)
|
||||
self.summary_page = SummaryPage()
|
||||
|
||||
# Add Pages
|
||||
@@ -94,6 +97,9 @@ class InstallerWindow(Adw.ApplicationWindow):
|
||||
def on_disk_selected(self, page, device_name):
|
||||
self.update_buttons()
|
||||
|
||||
def on_user_validity_changed(self, page, valid):
|
||||
self.update_buttons()
|
||||
|
||||
def update_buttons(self):
|
||||
# Back button state
|
||||
self.back_button.set_sensitive(self.current_page_index > 0)
|
||||
@@ -105,11 +111,15 @@ class InstallerWindow(Adw.ApplicationWindow):
|
||||
forced_selection = True
|
||||
if current_page_name == "storage":
|
||||
forced_selection = self.storage_page.get_selected_disk() is not None
|
||||
elif current_page_name == "user":
|
||||
forced_selection = self.user_page.is_valid()
|
||||
|
||||
self.next_button.set_sensitive(forced_selection)
|
||||
|
||||
if current_page_name == "summary":
|
||||
self.next_button.set_label("Install")
|
||||
self.next_button.set_label(
|
||||
"Install" + (" (MOCK)" if self.mock_mode else "")
|
||||
)
|
||||
self.next_button.add_css_class("destructive-action")
|
||||
self.next_button.remove_css_class("suggested-action")
|
||||
else:
|
||||
@@ -173,30 +183,36 @@ class InstallerWindow(Adw.ApplicationWindow):
|
||||
mode=mode,
|
||||
partitions=partitions_config,
|
||||
user_info=user_info,
|
||||
modules=modules
|
||||
modules=modules,
|
||||
)
|
||||
# Proceed to summary page (which is next_index after user)
|
||||
|
||||
|
||||
if current_page_name == "summary":
|
||||
# THIS IS THE REAL INSTALL TRIGGER
|
||||
print("Install process triggered!")
|
||||
disk = self.storage_page.get_selected_disk()
|
||||
print(f"Disk: {disk}")
|
||||
mode = self.install_mode_page.get_mode()
|
||||
print(f"Mode: {mode}")
|
||||
modules = self.modules_page.get_modules()
|
||||
print(f"Modules: {modules}")
|
||||
user_info = self.user_page.get_user_info()
|
||||
print(f"User: {user_info}")
|
||||
|
||||
# Recalculate or retrieve partitions just to be safe/consistent
|
||||
|
||||
partitions_config = {}
|
||||
if mode == "manual":
|
||||
partitions_config = self.partitioning_page.get_config()
|
||||
elif mode == "automatic":
|
||||
partitions = calculate_auto_partitions(disk)
|
||||
partitions_config = {"partitions": partitions}
|
||||
print(f"Partitioning: {partitions_config}")
|
||||
|
||||
if self.mock_mode:
|
||||
print("!!! MOCK MODE ENABLED - NO CHANGES WILL BE MADE !!!")
|
||||
print(f"Target Disk: {disk}")
|
||||
print(f"Mode: {mode}")
|
||||
print(f"Modules: {modules}")
|
||||
print(f"User: {user_info}")
|
||||
print(f"Partition Config: {partitions_config}")
|
||||
print("Simulation complete.")
|
||||
else:
|
||||
print("NOT IMPLEMENTED")
|
||||
|
||||
return
|
||||
|
||||
if next_index < len(self.page_ids):
|
||||
|
||||
Reference in New Issue
Block a user