Compare commits

...

15 Commits

Author SHA1 Message Date
aae235e81f Format icons SVG files for better readability 2026-02-03 12:03:25 +01:00
759b4c4007 Use the icon 2026-02-03 01:26:30 +01:00
9958b9a65b Create org.iridium.Installer-symbolic.svg 2026-02-03 01:26:25 +01:00
1afdf99a6f Temporary (or probably permanent, you know how this works) icon 2026-02-03 01:17:48 +01:00
26757288c4 Add mock mode support and input validation 2026-02-02 20:19:36 +01:00
7a69d62782 Module titles 2026-02-02 20:15:40 +01:00
f691be219d Summary page 2026-02-02 20:05:11 +01:00
281f7488af Update README.md 2026-02-02 20:03:40 +01:00
931f701591 Center content vertically in user and welcome pages 2026-02-02 15:26:03 +01:00
52897a1dd0 Why the fuck was it in that order 2026-02-02 15:24:40 +01:00
2c7b9c5b1f Automatic usernames 2026-02-02 15:20:23 +01:00
658040c138 Better - force selection, gray out button 2026-02-02 15:08:03 +01:00
7c899b8e86 Can't continue without selecting disk 2026-02-02 15:03:30 +01:00
a098f20a38 English as the only language option 2026-02-02 14:59:35 +01:00
3bff26928a Create additional_modules.py 2026-02-02 14:59:20 +01:00
12 changed files with 554 additions and 52 deletions

View File

@@ -1,4 +1,17 @@
# Iridium OS Installer <div align="center">
<img src="data/icons/org.iridium.Installer.svg" alt="Iridium OS Installer Icon" width="128" height="128">
# Iridium OS Installer
</div>
> [!WARNING] > [!WARNING]
> For now this is only a mockup and not actually functional > For now this is only a mockup and not actually functional.
## What is Iridium Installer?
Iridium Installer is a modern, GTK4/Libadwaita based installer designed for Iridium OS. It aims to provide a simple and elegant installation experience.
## Features
- Modern UI using **GTK4** and **Libadwaita**
- Automatic and Manual partitioning modes
- User configuration
- Module selection

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<svg
height="16px"
viewBox="0 0 16 16"
width="16px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M 8 1 C 4.132812 1 1 4.132812 1 8 C 1 11.867188 4.132812 15 8 15 C 11.867188 15 15 11.867188 15 8 C 15 4.132812 11.867188 1 8 1 Z M 8 3 C 10.761719 3 13 5.238281 13 8 C 13 10.761719 10.761719 13 8 13 C 5.238281 13 3 10.761719 3 8 C 3 5.238281 5.238281 3 8 3 Z M 8 3"
fill="#2e3436"
/>
<path
d="M 8 5 C 6.34375 5 5 6.34375 5 8 C 5 9.65625 6.34375 11 8 11 C 9.65625 11 11 9.65625 11 8 C 11 6.34375 9.65625 5 8 5 Z M 8 6 C 9.105469 6 10 6.894531 10 8 C 10 9.105469 9.105469 10 8 10 C 6.894531 10 6 9.105469 6 8 C 6 6.894531 6.894531 6 8 6 Z M 8 6"
fill="#2e3436"
/>
</svg>

After

Width:  |  Height:  |  Size: 772 B

View File

@@ -0,0 +1,39 @@
<svg
width="128"
height="128"
viewBox="0 0 128 128"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<linearGradient id="circle-bg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#5E5C64" />
<stop offset="100%" stop-color="#3D3846" />
</linearGradient>
</defs>
<circle cx="64" cy="64" r="56" fill="url(#circle-bg)" />
<circle
cx="64"
cy="64"
r="40"
fill="none"
stroke="#F6D32D"
stroke-width="8"
stroke-dasharray="75 25"
stroke-linecap="round"
opacity="0.9"
/>
<circle
cx="64"
cy="64"
r="28"
fill="none"
stroke="#F5C211"
stroke-width="4"
stroke-dasharray="45 20"
stroke-linecap="round"
opacity="0.8"
/>
<circle cx="64" cy="64" r="10" fill="#F6D32D" />
</svg>

After

Width:  |  Height:  |  Size: 871 B

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Name=Iridium Installer
Comment=Install Iridium OS on your computer
Exec=iridium-installer
Icon=org.iridium.Installer
Type=Application
Categories=System;Settings;
StartupNotify=true
Terminal=false

View File

@@ -1,3 +1,4 @@
import argparse
import sys import sys
import gi import gi
@@ -11,21 +12,30 @@ from .ui.window import InstallerWindow
class IridiumInstallerApp(Adw.Application): class IridiumInstallerApp(Adw.Application):
def __init__(self): def __init__(self, mock_mode=False):
super().__init__( super().__init__(
application_id="org.iridium.Installer", application_id="org.iridium.Installer",
flags=Gio.ApplicationFlags.FLAGS_NONE, flags=Gio.ApplicationFlags.FLAGS_NONE,
) )
self.mock_mode = mock_mode
def do_activate(self): def do_activate(self):
win = self.props.active_window win = self.props.active_window
if not win: if not win:
win = InstallerWindow(application=self) win = InstallerWindow(application=self, mock_mode=self.mock_mode)
win.present() win.present()
def main(): def main():
app = IridiumInstallerApp() parser = argparse.ArgumentParser(description="Iridium OS Installer")
parser.add_argument(
"--mock",
action="store_true",
help="Run in mock mode (no actual changes to disk)",
)
args = parser.parse_args()
app = IridiumInstallerApp(mock_mode=args.mock)
return app.run(sys.argv) return app.run(sys.argv)

View File

@@ -0,0 +1,101 @@
import gi
gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
from gi.repository import Adw, Gtk
class ModulesPage(Adw.Bin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.nvidia_drivers = False
self.chromebook_audio = False
self.android_apps = False
self.module_titles = {
"nvidia_drivers": "Proprietary NVIDIA Drivers",
"chromebook_audio": "Chromebook Audio Fixes",
"android_apps": "Android Apps Support",
}
# Main Layout
clamp = Adw.Clamp()
clamp.set_maximum_size(600)
self.set_child(clamp)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.set_spacing(24)
box.set_valign(Gtk.Align.CENTER)
box.set_margin_top(24)
box.set_margin_bottom(24)
clamp.set_child(box)
# Title
title = Gtk.Label(label="Additional Modules")
title.add_css_class("title-1")
box.append(title)
descr = Gtk.Label(
label="Select additional components you would like to install. (Internet connection required)"
)
descr.set_wrap(True)
box.append(descr)
dont_worry = Gtk.Label(label="Don't worry, you can always install them later.")
dont_worry.set_wrap(True)
box.append(dont_worry)
# Preferences Group
self.modules_group = Adw.PreferencesGroup()
self.modules_group.set_title("Optional Features")
box.append(self.modules_group)
# NVIDIA Drivers
self.add_module_row(
self.module_titles["nvidia_drivers"],
"Install proprietary drivers for NVIDIA graphics cards for better performance.",
"nvidia_drivers",
)
# Chromebook Audio
self.add_module_row(
self.module_titles["chromebook_audio"],
"Install additional audio drivers for Chromebook devices.",
"chromebook_audio",
)
# Android Apps
self.add_module_row(
self.module_titles["android_apps"],
"Install Waydroid to run Android applications on Iridium OS.",
"android_apps",
)
def add_module_row(self, title, subtitle, attr_name):
row = Adw.ActionRow()
row.set_title(title)
row.set_subtitle(subtitle)
switch = Gtk.Switch()
switch.set_valign(Gtk.Align.CENTER)
# Set initial state
switch.set_active(getattr(self, attr_name))
# Connect signal
switch.connect("notify::active", self.on_switch_toggled, attr_name)
row.add_suffix(switch)
self.modules_group.add(row)
def on_switch_toggled(self, switch, gparam, attr_name):
setattr(self, attr_name, switch.get_active())
def get_modules(self):
enabled_modules = []
if self.nvidia_drivers:
enabled_modules.append(self.module_titles["nvidia_drivers"])
if self.chromebook_audio:
enabled_modules.append(self.module_titles["chromebook_audio"])
if self.android_apps:
enabled_modules.append(self.module_titles["android_apps"])
return enabled_modules

View File

@@ -6,10 +6,14 @@ import gi
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, GObject, Gtk
class StoragePage(Adw.Bin): class StoragePage(Adw.Bin):
__gsignals__ = {
"disk-selected": (GObject.SignalFlags.RUN_FIRST, None, (str,)),
}
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@@ -68,8 +72,7 @@ class StoragePage(Adw.Bin):
if not self.first_radio: if not self.first_radio:
radio = Gtk.CheckButton() radio = Gtk.CheckButton()
self.first_radio = radio self.first_radio = radio
# Default selection # No default selection to force user interaction, for safety reasons
self.selected_disk = dev
else: else:
radio = Gtk.CheckButton() radio = Gtk.CheckButton()
radio.set_group(self.first_radio) radio.set_group(self.first_radio)
@@ -87,6 +90,7 @@ class StoragePage(Adw.Bin):
def on_disk_toggled(self, button, device_name): def on_disk_toggled(self, button, device_name):
if button.get_active(): if button.get_active():
self.selected_disk = device_name self.selected_disk = device_name
self.emit("disk-selected", device_name)
def get_selected_disk(self): def get_selected_disk(self):
return self.selected_disk return self.selected_disk

View File

@@ -0,0 +1,85 @@
import gi
gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
from gi.repository import Adw, Gtk
class SummaryPage(Adw.Bin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.status_page = Adw.StatusPage()
self.status_page.set_title("Summary")
self.status_page.set_description("Review your choices before installing")
self.status_page.set_icon_name("document-save-symbolic")
self.set_child(self.status_page)
# Main content box
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.set_spacing(24)
clamp = Adw.Clamp()
clamp.set_maximum_size(600)
self.status_page.set_child(clamp)
content_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
content_box.set_spacing(24)
clamp.set_child(content_box)
# Storage and partitioning
self.storage_group = Adw.PreferencesGroup()
self.storage_group.set_title("Storage & Partitioning")
content_box.append(self.storage_group)
self.disk_row = Adw.ActionRow()
self.disk_row.set_title("Target Disk")
self.storage_group.add(self.disk_row)
self.mode_row = Adw.ActionRow()
self.mode_row.set_title("Partitioning Mode")
self.storage_group.add(self.mode_row)
# User configuration
self.user_group = Adw.PreferencesGroup()
self.user_group.set_title("User Configuration")
content_box.append(self.user_group)
self.fullname_row = Adw.ActionRow()
self.fullname_row.set_title("Full Name")
self.user_group.add(self.fullname_row)
self.username_row = Adw.ActionRow()
self.username_row.set_title("Username")
self.user_group.add(self.username_row)
self.hostname_row = Adw.ActionRow()
self.hostname_row.set_title("Hostname")
self.user_group.add(self.hostname_row)
# Software
self.software_group = Adw.PreferencesGroup()
self.software_group.set_title("Software")
content_box.append(self.software_group)
self.modules_row = Adw.ActionRow()
self.modules_row.set_title("Additional Modules")
self.software_group.add(self.modules_row)
def update_summary(self, disk_info, mode, partitions, user_info, modules):
# Update Disk
self.disk_row.set_subtitle(str(disk_info))
# Update Mode
self.mode_row.set_subtitle(mode.capitalize())
# Update User Info
self.fullname_row.set_subtitle(user_info.get("fullname", ""))
self.username_row.set_subtitle(user_info.get("username", ""))
self.hostname_row.set_subtitle(user_info.get("hostname", ""))
# Update Modules
if modules:
self.modules_row.set_subtitle(", ".join(modules))
else:
self.modules_row.set_subtitle("None")

View File

@@ -1,20 +1,29 @@
import re
import gi import gi
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, GObject, Gtk
class UserPage(Adw.Bin): class UserPage(Adw.Bin):
__gsignals__ = {
"validity-changed": (GObject.SignalFlags.RUN_FIRST, None, (bool,)),
}
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._is_valid = False
clamp = Adw.Clamp() clamp = Adw.Clamp()
clamp.set_maximum_size(500) clamp.set_maximum_size(500)
self.set_child(clamp) self.set_child(clamp)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.set_spacing(24) box.set_spacing(24)
box.set_valign(Gtk.Align.CENTER)
box.set_margin_top(24) box.set_margin_top(24)
box.set_margin_bottom(24) box.set_margin_bottom(24)
clamp.set_child(box) clamp.set_child(box)
@@ -29,18 +38,28 @@ class UserPage(Adw.Bin):
self.fullname_row = Adw.EntryRow() self.fullname_row = Adw.EntryRow()
self.fullname_row.set_title("Full Name") 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) group.add(self.fullname_row)
self.username_row = Adw.EntryRow() self.username_row = Adw.EntryRow()
self.username_row.set_title("Username") self.username_row.set_title("Username")
self.username_row.set_text("admin")
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) group.add(self.username_row)
self.password_row = Adw.PasswordEntryRow() self.password_row = Adw.PasswordEntryRow()
self.password_row.set_title("Password") self.password_row.set_title("Password")
self.password_row.connect("notify::text", self.on_input_changed)
group.add(self.password_row) group.add(self.password_row)
self.confirm_row = Adw.PasswordEntryRow() self.confirm_row = Adw.PasswordEntryRow()
self.confirm_row.set_title("Confirm Password") self.confirm_row.set_title("Confirm Password")
self.confirm_row.connect("notify::text", self.on_input_changed)
group.add(self.confirm_row) group.add(self.confirm_row)
# Hostname # Hostname
@@ -50,16 +69,117 @@ class UserPage(Adw.Bin):
self.hostname_row = Adw.EntryRow() self.hostname_row = Adw.EntryRow()
self.hostname_row.set_title("Hostname") self.hostname_row.set_title("Hostname")
self.hostname_row.set_text("iridium-pc") self.hostname_row.set_text("iridium")
self.hostname_row.connect("notify::text", self.on_input_changed)
host_group.add(self.hostname_row) host_group.add(self.hostname_row)
# Administrator self.username_manually_set = False
admin_group = Adw.PreferencesGroup()
admin_group.set_margin_top(12)
box.append(admin_group)
admin_row = Adw.SwitchRow() # Initial validation
admin_row.set_title("Make this user administrator") self.validate()
admin_row.set_subtitle("Add to sudoers group")
admin_row.set_active(True) def on_fullname_changed(self, entry, _pspec):
admin_group.add(admin_row) if self.username_manually_set:
return
username = entry.get_text().lower()
if username == "administrator":
username = "admin"
for sign in (
" ",
"-",
"_",
".",
",",
":",
";",
"!",
"?",
"/",
"\\",
"|",
"@",
"#",
"$",
"%",
"^",
"&",
"*",
"(",
")",
"[",
"]",
"{",
"}",
"'",
'"',
"`",
"~",
"<",
">",
"=",
"+",
):
username = username.replace(sign, "_")
self.username_row.handler_block(self.username_handler_id)
self.username_row.set_text(username)
self.username_row.handler_unblock(self.username_handler_id)
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(),
"username": self.username_row.get_text(),
"password": self.password_row.get_text(),
"hostname": self.hostname_row.get_text(),
}

View File

@@ -1,8 +1,10 @@
import os
import gi import gi
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, Gdk, Gtk
class WelcomePage(Adw.Bin): class WelcomePage(Adw.Bin):
@@ -12,6 +14,24 @@ class WelcomePage(Adw.Bin):
page = Adw.StatusPage() page = Adw.StatusPage()
page.set_title("Welcome to Iridium OS") page.set_title("Welcome to Iridium OS")
page.set_description("The installation will begin shortly") page.set_description("The installation will begin shortly")
# Load custom icon
icon_path = os.path.join(
os.path.dirname(__file__),
"..",
"..",
"..",
"data",
"icons",
"org.iridium.Installer.svg",
)
if os.path.exists(icon_path):
try:
paintable = Gdk.Texture.new_from_filename(icon_path)
page.set_paintable(paintable)
except Exception:
page.set_icon_name("system-software-install-symbolic")
else:
page.set_icon_name("system-software-install-symbolic") page.set_icon_name("system-software-install-symbolic")
# Content Box # Content Box
@@ -25,15 +45,9 @@ class WelcomePage(Adw.Bin):
# Language Dropdown # Language Dropdown
languages = [ languages = [
"English (US)", "English",
"Spanish",
"French",
"German",
"Japanese",
"Chinese (Simplified)",
] ]
dropdown = Gtk.DropDown.new_from_strings(languages) dropdown = Gtk.DropDown.new_from_strings(languages)
dropdown.set_margin_bottom(20)
box.append(dropdown) box.append(dropdown)
page.set_child(box) page.set_child(box)

View File

@@ -4,19 +4,24 @@ 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
from .pages.additional_modules import ModulesPage
from .pages.install_mode import InstallModePage from .pages.install_mode import InstallModePage
from .pages.partitioning import PartitioningPage, calculate_auto_partitions from .pages.partitioning import PartitioningPage, calculate_auto_partitions
from .pages.storage import StoragePage from .pages.storage import StoragePage
from .pages.summary import SummaryPage
from .pages.user import UserPage from .pages.user import UserPage
from .pages.welcome import WelcomePage from .pages.welcome import WelcomePage
class InstallerWindow(Adw.ApplicationWindow): class InstallerWindow(Adw.ApplicationWindow):
def __init__(self, *args, **kwargs): def __init__(self, mock_mode=False, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.mock_mode = mock_mode
self.set_default_size(900, 650) self.set_default_size(900, 650)
self.set_title("Iridium Installer") self.set_title("Iridium Installer" + (" (MOCK MODE)" if mock_mode else ""))
self.set_icon_name("org.iridium.Installer")
self.toolbar_view = Adw.ToolbarView() self.toolbar_view = Adw.ToolbarView()
self.set_content(self.toolbar_view) self.set_content(self.toolbar_view)
@@ -64,32 +69,58 @@ class InstallerWindow(Adw.ApplicationWindow):
# Initialize Pages # Initialize Pages
self.welcome_page = WelcomePage() self.welcome_page = WelcomePage()
self.storage_page = StoragePage() self.storage_page = StoragePage()
self.storage_page.connect("disk-selected", self.on_disk_selected)
self.install_mode_page = InstallModePage() self.install_mode_page = InstallModePage()
self.partitioning_page = PartitioningPage() self.partitioning_page = PartitioningPage()
self.modules_page = ModulesPage()
self.user_page = UserPage() self.user_page = UserPage()
self.user_page.connect("validity-changed", self.on_user_validity_changed)
self.summary_page = SummaryPage()
# Add Pages # Add Pages
self.add_page(self.welcome_page, "welcome") self.add_page(self.welcome_page, "welcome")
self.add_page(self.storage_page, "storage") self.add_page(self.storage_page, "storage")
self.add_page(self.install_mode_page, "install_mode") self.add_page(self.install_mode_page, "install_mode")
self.add_page(self.partitioning_page, "partitioning") self.add_page(self.partitioning_page, "partitioning")
self.add_page(self.modules_page, "modules")
self.add_page(self.user_page, "user") self.add_page(self.user_page, "user")
self.add_page(self.summary_page, "summary")
# Initialize view # Initialize view
if self.page_ids: if self.page_ids:
self.stack.set_visible_child_name(self.page_ids[0]) self.stack.set_visible_child_name(self.page_ids[0])
self.update_buttons()
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)
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): def update_buttons(self):
# Back button state # Back button state
self.back_button.set_sensitive(self.current_page_index > 0) self.back_button.set_sensitive(self.current_page_index > 0)
# Next button label/state # Next button label/state
if self.current_page_index == len(self.page_ids) - 1: current_page_name = self.page_ids[self.current_page_index]
self.next_button.set_label("Install")
# Forced selection logic
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" + (" (MOCK)" if self.mock_mode else "")
)
self.next_button.add_css_class("destructive-action") self.next_button.add_css_class("destructive-action")
self.next_button.remove_css_class("suggested-action") self.next_button.remove_css_class("suggested-action")
else: else:
@@ -99,19 +130,18 @@ class InstallerWindow(Adw.ApplicationWindow):
def on_back_clicked(self, button): def on_back_clicked(self, button):
current_page = self.page_ids[self.current_page_index] current_page = self.page_ids[self.current_page_index]
prev_page = self.page_ids[self.current_page_index - 1]
if current_page == "user": # Default: go back one page
next_prev_index = self.current_page_index - 1
if current_page == "modules":
mode = self.install_mode_page.get_mode() mode = self.install_mode_page.get_mode()
if mode == "automatic": if mode == "automatic":
# Skip partitioning # Skip partitioning (which is immediately before modules)
self.current_page_index = self.page_ids.index("install_mode") next_prev_index = self.page_ids.index("install_mode")
else:
self.current_page_index -= 1
else:
if self.current_page_index > 0:
self.current_page_index -= 1
if next_prev_index >= 0:
self.current_page_index = next_prev_index
self.stack.set_visible_child_name(self.page_ids[self.current_page_index]) self.stack.set_visible_child_name(self.page_ids[self.current_page_index])
self.update_buttons() self.update_buttons()
@@ -121,7 +151,6 @@ class InstallerWindow(Adw.ApplicationWindow):
if current_page_name == "storage": if current_page_name == "storage":
selected_disk = self.storage_page.get_selected_disk() selected_disk = self.storage_page.get_selected_disk()
if selected_disk:
self.partitioning_page.load_partitions(selected_disk) self.partitioning_page.load_partitions(selected_disk)
next_index = self.current_page_index + 1 next_index = self.current_page_index + 1
@@ -130,17 +159,17 @@ class InstallerWindow(Adw.ApplicationWindow):
mode = self.install_mode_page.get_mode() mode = self.install_mode_page.get_mode()
if mode == "automatic": if mode == "automatic":
# Skip partitioning page # Skip partitioning page
next_index = self.page_ids.index("user") next_index = self.page_ids.index("modules")
else: else:
# Go to partitioning page # Go to partitioning page
next_index = self.page_ids.index("partitioning") next_index = self.page_ids.index("partitioning")
if current_page_name == "user": if current_page_name == "user":
print("Install process triggered!") # Prepare summary instead of installing immediately
disk = self.storage_page.get_selected_disk() disk = self.storage_page.get_selected_disk()
print(f"Disk: {disk}")
mode = self.install_mode_page.get_mode() mode = self.install_mode_page.get_mode()
print(f"Mode: {mode}") modules = self.modules_page.get_modules()
user_info = self.user_page.get_user_info()
partitions_config = {} partitions_config = {}
if mode == "manual": if mode == "manual":
@@ -149,7 +178,42 @@ class InstallerWindow(Adw.ApplicationWindow):
partitions = calculate_auto_partitions(disk) partitions = calculate_auto_partitions(disk)
partitions_config = {"partitions": partitions} partitions_config = {"partitions": partitions}
print(f"Partitioning: {partitions_config}") # Update summary page
self.summary_page.update_summary(
disk_info=disk,
mode=mode,
partitions=partitions_config,
user_info=user_info,
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()
mode = self.install_mode_page.get_mode()
modules = self.modules_page.get_modules()
user_info = self.user_page.get_user_info()
partitions_config = {}
if mode == "manual":
partitions_config = self.partitioning_page.get_config()
elif mode == "automatic":
partitions = calculate_auto_partitions(disk)
partitions_config = {"partitions": partitions}
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 return
if next_index < len(self.page_ids): if next_index < len(self.page_ids):

31
run.sh
View File

@@ -1,5 +1,32 @@
#!/bin/bash #!/bin/bash
# Install icons to ~/.local/share/icons if not already installed
ICON_DIR="$HOME/.local/share/icons/hicolor/128x128/apps"
SYMBOLIC_DIR="$HOME/.local/share/icons/hicolor/symbolic/apps"
mkdir -p "$ICON_DIR"
mkdir -p "$SYMBOLIC_DIR"
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Copy main icon if not exists or if source is newer
if [ ! -f "$ICON_DIR/org.iridium.Installer.svg" ] || [ "${SCRIPT_DIR}/data/icons/org.iridium.Installer.svg" -nt "$ICON_DIR/org.iridium.Installer.svg" ]; then
cp "${SCRIPT_DIR}/data/icons/org.iridium.Installer.svg" "$ICON_DIR/"
echo "Installed 128x128 icon"
fi
# Copy symbolic icon if not exists or if source is newer
if [ ! -f "$SYMBOLIC_DIR/org.iridium.Installer-symbolic.svg" ] || [ "${SCRIPT_DIR}/data/icons/org.iridium.Installer-symbolic.svg" -nt "$SYMBOLIC_DIR/org.iridium.Installer-symbolic.svg" ]; then
cp "${SCRIPT_DIR}/data/icons/org.iridium.Installer-symbolic.svg" "$SYMBOLIC_DIR/org.iridium.Installer-symbolic.svg"
echo "Installed symbolic icon"
fi
# Update icon cache if gtk-update-icon-cache exists
if command -v gtk-update-icon-cache &> /dev/null; then
gtk-update-icon-cache -f -t "$HOME/.local/share/icons/hicolor" 2>/dev/null || true
fi
export GSETTINGS_SCHEMA_DIR=. export GSETTINGS_SCHEMA_DIR=.
echo "Starting Iridium Installer..." python3 -m iridium_installer.main "$@"
python3 -m iridium_installer.main