9db6c513c9
- Add install_station package with __init__.py and core modules - Include boot_manager.py for boot loader configuration (BootManager class with singleton pattern) - Add common.py with password strength validation utilities and ZFS dataset definitions - Add custom.py with Partitions class for disk partitioning management (1010 lines) - Establish foundation for GTK+ based GhostBSD installer application Modules added: - boot_manager: UEFI/BIOS boot manager selection with rEFInd and FreeBSD options - common: Password validation functions and deprecated decorator utility - custom: Comprehensive partition management with GTK+ interface
294 lines
11 KiB
Python
294 lines
11 KiB
Python
import gi
|
|
gi.require_version('Gtk', '3.0')
|
|
from gi.repository import Gtk, Gdk, GdkPixbuf
|
|
import gettext
|
|
from install_station.system_calls import language_dictionary
|
|
from install_station.interface_controller import Interface
|
|
from install_station.data import InstallationData
|
|
from install_station.window import Window
|
|
|
|
gettext.bindtextdomain('install-station', '/usr/local/share/locale')
|
|
gettext.textdomain('install-station')
|
|
_ = gettext.gettext
|
|
|
|
lang_dictionary = language_dictionary()
|
|
|
|
Messages = _("""To run GhostBSD without installing, select "Try GhostBSD."
|
|
|
|
To install GhostBSD on your computer hard disk drive, click "Install GhostBSD."
|
|
|
|
Note: Language selection only works when selecting "Try GhostBSD."
|
|
When installing GhostBSD, the installation program is only in English.""")
|
|
|
|
cssProvider = Gtk.CssProvider()
|
|
cssProvider.load_from_path('/usr/local/lib/install-station/ghostbsd-style.css')
|
|
screen = Gdk.Screen.get_default()
|
|
styleContext = Gtk.StyleContext()
|
|
styleContext.add_provider_for_screen(
|
|
screen,
|
|
cssProvider,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
|
|
|
|
class Welcome:
|
|
"""
|
|
Utility class for the welcome screen and initial mode selection following the utility class pattern.
|
|
|
|
This class provides a GTK+ interface for the initial GhostBSD welcome screen including:
|
|
- Language selection from available system languages
|
|
- Mode selection between "Install GhostBSD" and "Try GhostBSD"
|
|
- Visual elements with images and instructional text
|
|
- Integration with InstallationData for persistent configuration
|
|
|
|
The class follows a utility pattern with class methods and variables for state management,
|
|
designed to integrate with the Interface controller for navigation flow.
|
|
"""
|
|
# Class variables instead of instance variables
|
|
what = None
|
|
language = None
|
|
install_ghostbsd = None
|
|
try_ghostbsd = None
|
|
vbox1 = None
|
|
|
|
@classmethod
|
|
def language_selection(cls, tree_selection):
|
|
"""
|
|
Handle language selection from the treeview.
|
|
|
|
Extracts the selected language from the tree view and updates both
|
|
class variables and InstallationData with the language name and code.
|
|
Also updates the UI text to reflect the new language selection.
|
|
|
|
Args:
|
|
tree_selection: TreeSelection widget containing the user's language choice
|
|
"""
|
|
model, tree_iter = tree_selection.get_selected()
|
|
if tree_iter is not None:
|
|
value = model[tree_iter][0]
|
|
language_code = lang_dictionary[value]
|
|
cls.language = language_code
|
|
InstallationData.language = value
|
|
InstallationData.language_code = language_code
|
|
print(f"Language selected: {value} ({language_code})")
|
|
|
|
# Update gettext to use the new language
|
|
import os
|
|
os.environ['LANGUAGE'] = language_code
|
|
gettext.bindtextdomain('install-station', '/usr/local/share/locale')
|
|
gettext.textdomain('install-station')
|
|
|
|
# Update the UI text with new translations
|
|
cls.update_ui_text()
|
|
return
|
|
|
|
@classmethod
|
|
def update_ui_text(cls):
|
|
"""
|
|
Update all UI text elements with new translations after language change.
|
|
"""
|
|
# Reload the gettext function to pick up new locale
|
|
_ = gettext.gettext
|
|
|
|
# Update UI elements if they exist
|
|
if hasattr(cls, 'install_button') and cls.install_button:
|
|
cls.install_button.set_label(_('Install GhostBSD'))
|
|
|
|
if hasattr(cls, 'try_button') and cls.try_button:
|
|
cls.try_button.set_label(_('Try GhostBSD'))
|
|
|
|
if hasattr(cls, 'text_label') and cls.text_label:
|
|
cls.text_label.set_text(_("""To run GhostBSD without installing, select "Try GhostBSD."
|
|
|
|
|
|
To install GhostBSD on your computer hard disk drive, click "Install GhostBSD."
|
|
|
|
Note: Language selection only works when selecting "Try GhostBSD."
|
|
When installing GhostBSD, the installation program is only in English."""))
|
|
|
|
if hasattr(cls, 'language_column_header') and cls.language_column_header:
|
|
cls.language_column_header.set_text(_('Language'))
|
|
|
|
Window.set_title(_("Welcome to GhostBSD"))
|
|
|
|
@classmethod
|
|
def language_columns(cls, treeview):
|
|
"""
|
|
Configure the language selection treeview with appropriate columns.
|
|
|
|
Creates a single column with a "Language" header for displaying
|
|
available languages in the tree view.
|
|
|
|
Args:
|
|
treeview: TreeView widget to configure with language column
|
|
"""
|
|
cell = Gtk.CellRendererText()
|
|
column = Gtk.TreeViewColumn(None, cell, text=0)
|
|
column_header = Gtk.Label(label=_('Language'))
|
|
column_header.set_use_markup(True)
|
|
column_header.show()
|
|
column.set_widget(column_header)
|
|
# Store reference for updating
|
|
cls.language_column_header = column_header
|
|
column.set_sort_column_id(0)
|
|
treeview.append_column(column)
|
|
|
|
@classmethod
|
|
def save_selection(cls):
|
|
"""
|
|
Save the current language selection.
|
|
|
|
This method is maintained for compatibility but language selection
|
|
is now automatically saved to InstallationData when chosen.
|
|
"""
|
|
# Language is now saved in InstallationData automatically
|
|
pass
|
|
|
|
@classmethod
|
|
def install_system(cls, _widget):
|
|
"""
|
|
Handle "Install GhostBSD" button click.
|
|
|
|
Sets the installation mode to 'install' and navigates to the
|
|
installation workflow pages.
|
|
|
|
Args:
|
|
_widget: Button widget that triggered the action (unused)
|
|
"""
|
|
cls.what = 'install'
|
|
InstallationData.install_mode = 'install'
|
|
Interface.next_install_page()
|
|
|
|
@classmethod
|
|
def try_system(cls, _widget):
|
|
"""
|
|
Handle "Try GhostBSD" button click.
|
|
|
|
Sets the installation mode to 'try' and navigates to the
|
|
live system setup pages (typically network configuration).
|
|
|
|
Args:
|
|
_widget: Button widget that triggered the action (unused)
|
|
"""
|
|
cls.what = 'try'
|
|
InstallationData.install_mode = 'try'
|
|
Interface.next_setup_page()
|
|
|
|
@classmethod
|
|
def get_what(cls):
|
|
"""
|
|
Get the current installation mode.
|
|
|
|
Returns the installation mode from InstallationData if available,
|
|
otherwise falls back to the class variable.
|
|
|
|
Returns:
|
|
str: Current installation mode ('install' or 'try')
|
|
"""
|
|
return InstallationData.install_mode or cls.what
|
|
|
|
@classmethod
|
|
def initialize(cls):
|
|
"""
|
|
Initialize the welcome screen UI following the utility class pattern.
|
|
|
|
Creates the main interface including:
|
|
- Language selection tree view on the left side
|
|
- Install and Try buttons with images on the right side
|
|
- Instructional text explaining the options
|
|
- Grid-based layout with proper spacing and margins
|
|
|
|
This method is called automatically by get_model() when the interface is first accessed.
|
|
"""
|
|
cls.what = None
|
|
cls.language = None
|
|
cls.vbox1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=False, spacing=0)
|
|
cls.vbox1.show()
|
|
main_grid = Gtk.Grid()
|
|
cls.vbox1.pack_start(main_grid, True, True, 0)
|
|
sw = Gtk.ScrolledWindow()
|
|
sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
|
|
sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
|
store = Gtk.TreeStore(str)
|
|
for line in lang_dictionary:
|
|
store.append(None, [line])
|
|
treeview = Gtk.TreeView()
|
|
treeview.set_model(store)
|
|
treeview.set_rules_hint(True)
|
|
cls.language_columns(treeview)
|
|
tree_selection = treeview.get_selection()
|
|
tree_selection.set_mode(Gtk.SelectionMode.SINGLE)
|
|
tree_selection.connect("changed", cls.language_selection)
|
|
sw.add(treeview)
|
|
sw.show()
|
|
vbox2 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=False, spacing=0)
|
|
vbox2.set_border_width(10)
|
|
vbox2.show()
|
|
pix_buf1 = GdkPixbuf.Pixbuf().new_from_file_at_scale(
|
|
filename='/usr/local/lib/install-station/laptop.png',
|
|
width=190,
|
|
height=190,
|
|
preserve_aspect_ratio=True
|
|
)
|
|
image1 = Gtk.Image.new_from_pixbuf(pix_buf1)
|
|
image1.show()
|
|
pix_buf2 = GdkPixbuf.Pixbuf().new_from_file_at_scale(
|
|
filename='/usr/local/lib/install-station/disk.png',
|
|
width=120,
|
|
height=120,
|
|
preserve_aspect_ratio=True)
|
|
image2 = Gtk.Image.new_from_pixbuf(pix_buf2)
|
|
image2.show()
|
|
install_button = Gtk.Button(label=_('Install GhostBSD'), image=image1,
|
|
image_position=2)
|
|
install_button.set_always_show_image(True)
|
|
install_button.connect("clicked", cls.install_system)
|
|
try_button = Gtk.Button(label=_('Try GhostBSD'), image=image2,
|
|
image_position=2)
|
|
try_button.set_always_show_image(True)
|
|
try_button.connect("clicked", cls.try_system)
|
|
text_label = Gtk.Label(label=Messages)
|
|
text_label.set_line_wrap(True)
|
|
|
|
# Store references for updating
|
|
cls.install_button = install_button
|
|
cls.try_button = try_button
|
|
cls.text_label = text_label
|
|
right_grid = Gtk.Grid()
|
|
right_grid.set_row_spacing(10)
|
|
right_grid.set_column_spacing(2)
|
|
right_grid.set_column_homogeneous(True)
|
|
right_grid.set_row_homogeneous(True)
|
|
right_grid.set_margin_left(10)
|
|
right_grid.set_margin_right(10)
|
|
right_grid.set_margin_top(10)
|
|
right_grid.set_margin_bottom(10)
|
|
right_grid.attach(install_button, 1, 1, 1, 5)
|
|
right_grid.attach(try_button, 2, 1, 1, 5)
|
|
right_grid.attach(text_label, 1, 6, 2, 5)
|
|
main_grid.set_row_spacing(10)
|
|
main_grid.set_column_spacing(4)
|
|
main_grid.set_column_homogeneous(True)
|
|
main_grid.set_row_homogeneous(True)
|
|
main_grid.set_margin_left(10)
|
|
main_grid.set_margin_right(10)
|
|
main_grid.set_margin_top(10)
|
|
main_grid.set_margin_bottom(10)
|
|
main_grid.attach(sw, 1, 1, 1, 10)
|
|
main_grid.attach(right_grid, 2, 1, 3, 10)
|
|
main_grid.show()
|
|
|
|
@classmethod
|
|
def get_model(cls):
|
|
"""
|
|
Return the GTK widget model for the welcome screen interface.
|
|
|
|
Returns the main container widget that was created during initialization.
|
|
|
|
Returns:
|
|
Gtk.Box: The main container widget for the welcome screen interface
|
|
"""
|
|
if cls.vbox1 is None:
|
|
cls.initialize()
|
|
return cls.vbox1
|