Files
installer-gui/install_station/welcome_live.py
T
ericbsd 9db6c513c9 Add initial install_station Python package structure
- 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
2025-07-09 21:29:53 -03:00

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