Rework ZFS page UI layout and swap sizing

Redesign the ZFS configuration page with a two-column layout (settings
on the left, disk list on the right), add a user-editable swap size
field that defaults to actual RAM size, make the pool name always
editable, and simplify pool type values to plain identifiers (stripe,
mirror, raidz1/2/3). Consolidate duplicated next-button sensitivity
logic into _update_next_button(), replace deprecated Gtk.STOCK icons
with icon names, encrypt swap when GELI is enabled, and bump version
to 0.4.
This commit is contained in:
ericbsd
2026-05-13 08:11:34 -03:00
parent 6035e6355f
commit 4d4c54671e
4 changed files with 220 additions and 241 deletions
+3 -2
View File
@@ -7,6 +7,7 @@ import re
from time import sleep from time import sleep
from subprocess import Popen, PIPE, STDOUT, call from subprocess import Popen, PIPE, STDOUT, call
from install_station.data import query, zfs_datasets, InstallationData from install_station.data import query, zfs_datasets, InstallationData
from install_station.system_calls import get_ram_size_mb
# Define required file paths # Define required file paths
@@ -779,7 +780,7 @@ class AutoFreeSpace:
InstallationData.slice = main_slice.replace(drive, "") InstallationData.slice = main_slice.replace(drive, "")
root_size = int(main_size) root_size = int(main_size)
swap_size = 2048 swap_size = get_ram_size_mb()
root_size -= swap_size root_size -= swap_size
part_list = disk_db[drive]['partitions'][main_slice]['partition-list'] part_list = disk_db[drive]['partitions'][main_slice]['partition-list']
@@ -861,7 +862,7 @@ class AutoFreeSpace:
InstallationData.disk = drive InstallationData.disk = drive
InstallationData.scheme = 'partscheme=GPT' InstallationData.scheme = 'partscheme=GPT'
root_size = int(main_size) root_size = int(main_size)
swap_size = 2048 swap_size = get_ram_size_mb()
root_size -= int(swap_size) root_size -= int(swap_size)
if self.bios_type == "UEFI" and efi_exist is False: if self.bios_type == "UEFI" and efi_exist is False:
boot_size = 256 boot_size = 256
+15
View File
@@ -258,6 +258,21 @@ def timezone_dictionary() -> dict[str, list[str]]:
return dictionary return dictionary
def get_ram_size_mb() -> int:
"""Query the system RAM size in megabytes using sysctl.
Returns:
System RAM size in MB
"""
output = Popen(
'sysctl -n hw.realmem',
shell=True,
stdout=PIPE,
universal_newlines=True
).stdout.read().strip()
return int(output) // 1048576
def zfs_disk_query() -> list[str]: def zfs_disk_query() -> list[str]:
"""Query available disks for ZFS installation. """Query available disks for ZFS installation.
+201 -238
View File
@@ -3,6 +3,7 @@ from install_station.common import password_strength
from install_station.data import InstallationData, zfs_datasets, be_name, logo, get_text from install_station.data import InstallationData, zfs_datasets, be_name, logo, get_text
from install_station.partition import bios_or_uefi from install_station.partition import bios_or_uefi
from install_station.system_calls import ( from install_station.system_calls import (
get_ram_size_mb,
zfs_disk_query, zfs_disk_query,
zfs_disk_size_query, zfs_disk_size_query,
) )
@@ -38,13 +39,13 @@ class ZFS:
zfs_disk_list = [] zfs_disk_list = []
pool_type = 'stripe' pool_type = 'stripe'
scheme = 'GPT' scheme = 'GPT'
zpool = False
disk_encrypt = False disk_encrypt = False
mirror = 'single disk' mirror = 'none'
vbox1 = None vbox1 = None
# UI elements as class variables # UI elements as class variables
pool = None pool = None
swap_entry = None
password = None password = None
repassword = None repassword = None
mirrorTips = None mirrorTips = None
@@ -69,28 +70,19 @@ class ZFS:
# Validate required fields are populated # Validate required fields are populated
if not cls.zfs_disk_list: if not cls.zfs_disk_list:
raise ValueError("No disks selected for ZFS configuration") raise ValueError("No disks selected for ZFS configuration")
if cls.zpool and not cls.pool.get_text().strip():
raise ValueError("Pool name cannot be empty when zpool is enabled")
if cls.disk_encrypt and not cls.password.get_text().strip(): if cls.disk_encrypt and not cls.password.get_text().strip():
raise ValueError("Password cannot be empty when disk encryption is enabled") raise ValueError("Password cannot be empty when disk encryption is enabled")
size = int(cls.zfs_disk_list[0].partition('-')[2].rstrip()) - 512 size = int(cls.zfs_disk_list[0].partition('-')[2].rstrip()) - 512
swap = 0 swap_size = int(cls.swap_entry.get_text() or '0')
zfs_num = size - swap zfs_num = size - swap_size
if cls.disk_encrypt is True: dgeli = '.eli' if cls.disk_encrypt else ''
dgeli = '.eli'
else:
dgeli = ''
# Store configuration data in InstallationData instead of writing to file # Store configuration data in InstallationData instead of writing to file
InstallationData.zfs_config_data = [] InstallationData.zfs_config_data = []
if cls.zpool is True: InstallationData.zfs_config_data.append(f"zpoolName={cls.pool.get_text()}\n")
InstallationData.zfs_config_data.append(f"zpoolName={cls.pool.get_text()}\n")
else:
InstallationData.zfs_config_data.append("#zpoolName=None\n")
InstallationData.zfs_config_data.append(f"beName={be_name}\n") InstallationData.zfs_config_data.append(f"beName={be_name}\n")
InstallationData.zfs_config_data.append('ashift=12\n\n') InstallationData.zfs_config_data.append('ashift=12\n\n')
disk = cls.zfs_disk_list[0].partition('-')[0].rstrip() disk = cls.zfs_disk_list[0].partition('-')[0].rstrip()
@@ -98,18 +90,13 @@ class ZFS:
InstallationData.zfs_config_data.append('partition=ALL\n') InstallationData.zfs_config_data.append('partition=ALL\n')
InstallationData.zfs_config_data.append(f'partscheme={cls.scheme}\n') InstallationData.zfs_config_data.append(f'partscheme={cls.scheme}\n')
InstallationData.zfs_config_data.append('commitDiskPart\n\n') InstallationData.zfs_config_data.append('commitDiskPart\n\n')
if cls.pool_type == 'none': if len(cls.zfs_disk_list) <= 1:
pool_disk = '\n' pool_disk = '\n'
else: else:
zfs_disk = cls.zfs_disk_list zfs_disk = cls.zfs_disk_list
disk_len = len(zfs_disk) - 1
num = 1
mirror_dsk = '' mirror_dsk = ''
while disk_len != 0: for i in range(1, len(zfs_disk)):
mirror_dsk += ' ' + zfs_disk[num].partition('-')[0].rstrip() mirror_dsk += ' ' + zfs_disk[i].partition('-')[0].rstrip()
print(mirror_dsk)
num += 1
disk_len -= 1
pool_disk = f' ({cls.pool_type}:{mirror_dsk})\n' pool_disk = f' ({cls.pool_type}:{mirror_dsk})\n'
if bios_or_uefi() == "UEFI": if bios_or_uefi() == "UEFI":
zfs_num = zfs_num - 100 zfs_num = zfs_num - 100
@@ -118,19 +105,58 @@ class ZFS:
# adding zero to use remaining space # adding zero to use remaining space
zfs_part = f'disk0-part=ZFS{dgeli} {zfs_num} {zfs_datasets}{pool_disk}' zfs_part = f'disk0-part=ZFS{dgeli} {zfs_num} {zfs_datasets}{pool_disk}'
InstallationData.zfs_config_data.append(zfs_part) InstallationData.zfs_config_data.append(zfs_part)
if swap != 0: # encpass must be on the line immediately after the .eli partition
InstallationData.zfs_config_data.append('disk0-part=swap 0 none\n') if cls.disk_encrypt:
if cls.disk_encrypt is True:
InstallationData.zfs_config_data.append(f'encpass={cls.password.get_text()}\n') InstallationData.zfs_config_data.append(f'encpass={cls.password.get_text()}\n')
else: else:
InstallationData.zfs_config_data.append('#encpass=None\n') InstallationData.zfs_config_data.append('#encpass=None\n')
if swap_size != 0:
if cls.disk_encrypt:
InstallationData.zfs_config_data.append('disk0-part=SWAP.eli 0 none\n')
else:
InstallationData.zfs_config_data.append('disk0-part=SWAP 0 none\n')
InstallationData.zfs_config_data.append('commitDiskLabel\n') InstallationData.zfs_config_data.append('commitDiskLabel\n')
@classmethod
def _disk_count_valid(cls):
"""
Check if the number of selected disks meets the pool type requirement.
Returns:
bool: True if enough disks are selected for the current pool type
"""
count = len(cls.zfs_disk_list)
if cls.mirror == "stripe":
return count >= 1
elif cls.mirror == "mirror":
return count >= 2
elif cls.mirror == "raidz1":
return count == 3
elif cls.mirror == "raidz2":
return count == 4
elif cls.mirror == "raidz3":
return count == 5
return False
@classmethod
def _update_next_button(cls):
"""
Update next button sensitivity based on disk count and encryption state.
When encryption is enabled, passwords must also match.
"""
if cls.disk_encrypt:
passwd_match = (cls.password.get_text() == cls.repassword.get_text()
and len(cls.password.get_text()) > 0)
Button.next_button.set_sensitive(cls._disk_count_valid() and passwd_match)
else:
Button.next_button.set_sensitive(cls._disk_count_valid())
@classmethod @classmethod
def scheme_selection(cls, combobox): def scheme_selection(cls, combobox):
""" """
Handle partition scheme selection from combo box. Handle partition scheme selection from combo box.
Args: Args:
combobox: ComboBox widget containing scheme options (GPT/MBR) combobox: ComboBox widget containing scheme options (GPT/MBR)
""" """
@@ -143,80 +169,48 @@ class ZFS:
def mirror_selection(cls, combobox): def mirror_selection(cls, combobox):
""" """
Handle pool type selection and update UI accordingly. Handle pool type selection and update UI accordingly.
Sets the pool type (stripe, mirror, RAIDZ1/2/3) and updates the tip text Sets the pool type (stripe, mirror, RAIDZ1/2/3) and updates the tip text
and next button sensitivity based on the number of selected disks. and next button sensitivity based on the number of selected disks.
Args: Args:
combobox: ComboBox widget containing pool type options combobox: ComboBox widget containing pool type options
""" """
model = combobox.get_model() model = combobox.get_model()
index = combobox.get_active() index = combobox.get_active()
data = model[index][0] # Get the internal value (English) data = model[index][0]
cls.mirror = data cls.mirror = data
if cls.mirror == "1+ disks Stripe": smallest_msg = get_text("(select the smallest disk first)")
if cls.mirror == "stripe":
cls.pool_type = 'stripe' cls.pool_type = 'stripe'
cls.mirrorTips.set_text( cls.mirrorTips.set_text(
get_text("Please select 1 or more drive for stripe (select the smallest disk first)")) get_text("Select 1 or more drives, no redundancy") + " " + smallest_msg)
if len(cls.zfs_disk_list) >= 1: elif cls.mirror == "mirror":
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "2+ disks Mirror":
cls.pool_type = 'mirror' cls.pool_type = 'mirror'
mir_msg1 = get_text("Please select 2 drive for mirroring (select the smallest disk first)") cls.mirrorTips.set_text(
cls.mirrorTips.set_text(mir_msg1) get_text("Select 2 or more drives for mirroring") + " " + smallest_msg)
if len(cls.zfs_disk_list) >= 2: elif cls.mirror == "raidz1":
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "3 disks RAIDZ1":
cls.pool_type = 'raidz1' cls.pool_type = 'raidz1'
cls.mirrorTips.set_text(get_text("Please select 3 drive for RAIDZ1 (select the smallest disk first)")) cls.mirrorTips.set_text(
if len(cls.zfs_disk_list) == 3: get_text("Select 3 drives for RAIDZ1") + " " + smallest_msg)
Button.next_button.set_sensitive(True) elif cls.mirror == "raidz2":
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "4 disks RAIDZ2":
cls.pool_type = 'raidz2' cls.pool_type = 'raidz2'
cls.mirrorTips.set_text(get_text("Please select 4 drive for RAIDZ2 (select the smallest disk first)")) cls.mirrorTips.set_text(
if len(cls.zfs_disk_list) == 4: get_text("Select 4 drives for RAIDZ2") + " " + smallest_msg)
Button.next_button.set_sensitive(True) elif cls.mirror == "raidz3":
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "5 disks RAIDZ3":
cls.pool_type = 'raidz3' cls.pool_type = 'raidz3'
cls.mirrorTips.set_text(get_text("Please select 5 drive for RAIDZ3 (select the smallest disk first)")) cls.mirrorTips.set_text(
if len(cls.zfs_disk_list) == 5: get_text("Select 5 drives for RAIDZ3") + " " + smallest_msg)
Button.next_button.set_sensitive(True) cls._update_next_button()
else:
Button.next_button.set_sensitive(False)
@classmethod
def on_check_poll(cls, widget):
"""
Handle custom pool name checkbox toggle.
Enables or disables the pool name entry field based on checkbox state.
Args:
widget: CheckButton widget for pool name enable/disable
"""
if widget.get_active():
cls.pool.set_sensitive(True)
cls.zpool = True
else:
cls.pool.set_sensitive(False)
cls.zpool = False
@classmethod @classmethod
def on_check_encrypt(cls, widget): def on_check_encrypt(cls, widget):
""" """
Handle disk encryption checkbox toggle. Handle disk encryption checkbox toggle.
Enables or disables password fields and updates next button sensitivity Enables or disables password fields and updates next button sensitivity
based on encryption state and current disk selection. based on encryption state and current disk selection.
Args: Args:
widget: CheckButton widget for disk encryption enable/disable widget: CheckButton widget for disk encryption enable/disable
""" """
@@ -229,31 +223,37 @@ class ZFS:
cls.password.set_sensitive(False) cls.password.set_sensitive(False)
cls.repassword.set_sensitive(False) cls.repassword.set_sensitive(False)
cls.disk_encrypt = False cls.disk_encrypt = False
if cls.mirror == "1+ disks Stripe": cls._update_next_button()
if len(cls.zfs_disk_list) >= 1:
Button.next_button.set_sensitive(True) @classmethod
else: def on_password_changed(cls, _widget):
Button.next_button.set_sensitive(False) """
elif cls.mirror == "2+ disks Mirror": Handle password entry changes and update strength display.
if len(cls.zfs_disk_list) >= 2:
Button.next_button.set_sensitive(True) Wraps the common password_strength function to extract the text
else: from the Entry widget and pass it with the strength label.
Button.next_button.set_sensitive(False)
elif cls.mirror == "3 disks RAIDZ1": Args:
if len(cls.zfs_disk_list) == 3: _widget: Entry widget that triggered the change (unused)
Button.next_button.set_sensitive(True) """
else: password_strength(cls.password.get_text(), cls.strenght_label)
Button.next_button.set_sensitive(False)
elif cls.mirror == "4 disks RAIDZ2": @classmethod
if len(cls.zfs_disk_list) == 4: def digit_only(cls, widget, text, length, position):
Button.next_button.set_sensitive(True) """
else: Block non-digit characters from being inserted into the swap entry.
Button.next_button.set_sensitive(False)
elif cls.mirror == "5 disks RAIDZ3": Connected to the swap entry 'insert-text' signal to prevent
if len(cls.zfs_disk_list) == 5: non-numeric input before it enters the field.
Button.next_button.set_sensitive(True)
else: Args:
Button.next_button.set_sensitive(False) widget: Entry widget receiving the input
text: Text being inserted
length: Length of the text being inserted
position: Cursor position at time of insertion
"""
if not text.isdigit():
widget.stop_emission_by_name('insert-text')
@classmethod @classmethod
def initialize(cls): def initialize(cls):
@@ -271,7 +271,8 @@ class ZFS:
""" """
cls.vbox1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=False, spacing=0) cls.vbox1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=False, spacing=0)
cls.vbox1.show() cls.vbox1.show()
# Chose disk
# Disk list in a scrolled window
sw = Gtk.ScrolledWindow(hexpand=True, vexpand=True) sw = Gtk.ScrolledWindow(hexpand=True, vexpand=True)
sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
@@ -319,37 +320,38 @@ class ZFS:
tree_selection.set_mode(Gtk.SelectionMode.SINGLE) tree_selection.set_mode(Gtk.SelectionMode.SINGLE)
sw.add(treeview) sw.add(treeview)
sw.show() sw.show()
cls.mirrorTips = Gtk.Label(label=get_text('Please select one drive')) cls.mirrorTips = Gtk.Label(label=get_text('Please select one drive'))
cls.mirrorTips.set_justify(Gtk.Justification.LEFT) cls.mirrorTips.set_justify(Gtk.Justification.LEFT)
cls.mirrorTips.set_alignment(0.01, 0.5) cls.mirrorTips.set_alignment(0.01, 0.5)
# Mirror, raidz and stripe
# Pool Layout
cls.mirror = 'none' cls.mirror = 'none'
mirror_label = Gtk.Label(label=get_text('<b>Pool Type</b>')) mirror_label = Gtk.Label(label=get_text('Pool Layout'))
mirror_label.set_use_markup(True) mirror_label.set_use_markup(True)
mirror_box = Gtk.ComboBox() mirror_box = Gtk.ComboBoxText()
mirror_store = Gtk.ListStore(str, str) # value, display_text mirror_box.append_text("stripe")
mirror_store.append(["1+ disks Stripe", get_text("1+ disks Stripe")]) mirror_box.append_text("mirror")
mirror_store.append(["2+ disks Mirror", get_text("2+ disks Mirror")]) mirror_box.append_text("raidz1")
mirror_store.append(["3 disks RAIDZ1", get_text("3 disks RAIDZ1")]) mirror_box.append_text("raidz2")
mirror_store.append(["4 disks RAIDZ2", get_text("4 disks RAIDZ2")]) mirror_box.append_text("raidz3")
mirror_store.append(["5 disks RAIDZ3", get_text("5 disks RAIDZ3")])
mirror_box.set_model(mirror_store)
renderer = Gtk.CellRendererText()
mirror_box.pack_start(renderer, True)
mirror_box.add_attribute(renderer, "text", 1) # Display column 1 (translated text)
mirror_box.connect('changed', cls.mirror_selection) mirror_box.connect('changed', cls.mirror_selection)
mirror_box.set_active(0) mirror_box.set_active(0)
# Pool Name # Pool Name (always editable)
cls.zpool = False pool_label = Gtk.Label(label=get_text('Pool Name'))
pool_name_label = Gtk.Label(label=get_text('<b>Pool Name</b>')) pool_label.set_use_markup(True)
pool_name_label.set_use_markup(True)
cls.pool = Gtk.Entry() cls.pool = Gtk.Entry()
cls.pool.set_text('zroot') cls.pool.set_text('zroot')
# Swap Size
swap_label = Gtk.Label(label=get_text('Swap Size(MB)'))
swap_label.set_use_markup(True)
cls.swap_entry = Gtk.Entry()
cls.swap_entry.set_text(str(get_ram_size_mb()))
cls.swap_entry.connect('insert-text', cls.digit_only)
# Creating MBR or GPT drive # Creating MBR or GPT drive
scheme_label = Gtk.Label(label='<b>Partition Scheme</b>')
scheme_label.set_use_markup(True)
# Adding a combo box to selecting MBR or GPT sheme.
cls.scheme = 'GPT' cls.scheme = 'GPT'
shemebox = Gtk.ComboBoxText() shemebox = Gtk.ComboBoxText()
shemebox.append_text("GPT") shemebox.append_text("GPT")
@@ -360,52 +362,85 @@ class ZFS:
shemebox.set_sensitive(False) shemebox.set_sensitive(False)
else: else:
shemebox.set_sensitive(True) shemebox.set_sensitive(True)
# GELI Disk encryption # GELI Disk encryption
cls.disk_encrypt = False cls.disk_encrypt = False
encrypt_check = Gtk.CheckButton(label=get_text("Encrypt Disk")) encrypt_check = Gtk.CheckButton(label=get_text("Encrypt Disk (GELI)"))
encrypt_check.connect("toggled", cls.on_check_encrypt) encrypt_check.connect("toggled", cls.on_check_encrypt)
encrypt_check.set_sensitive(True) encrypt_check.set_sensitive(True)
# password
# Password
cls.passwd_label = Gtk.Label(label=get_text("Password")) cls.passwd_label = Gtk.Label(label=get_text("Password"))
cls.password = Gtk.Entry() cls.password = Gtk.Entry()
cls.password.set_sensitive(False) cls.password.set_sensitive(False)
cls.password.set_visibility(False) cls.password.set_visibility(False)
cls.password.connect("changed", password_strength) cls.password.connect("changed", cls.on_password_changed)
cls.strenght_label = Gtk.Label() cls.strenght_label = Gtk.Label()
cls.strenght_label.set_alignment(0.1, 0.5) cls.strenght_label.set_alignment(0.1, 0.5)
cls.vpasswd_label = Gtk.Label(label=get_text("Verify it")) cls.strenght_label.set_size_request(-1, 20)
# Verify password
cls.vpasswd_label = Gtk.Label(label=get_text("Confirm"))
cls.repassword = Gtk.Entry() cls.repassword = Gtk.Entry()
cls.repassword.set_sensitive(False) cls.repassword.set_sensitive(False)
cls.repassword.set_visibility(False) cls.repassword.set_visibility(False)
cls.repassword.connect("changed", cls.password_verification) cls.repassword.connect("changed", cls.password_verification)
# set image for password matching
# Password match image
cls.img = Gtk.Image() cls.img = Gtk.Image()
cls.img.set_alignment(0.2, 0.5) cls.img.set_size_request(20, 20)
# table = Gtk.Table(12, 12, True)
grid = Gtk.Grid() # Two-column layout: left settings, right disk list
grid.set_row_spacing(10) hbox_main = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, homogeneous=False, spacing=10)
# grid.set_column_homogeneous(True)
# grid.set_row_homogeneous(True) # Left panel: settings grid
# grid.attach(Title, 1, 1, 10, 1) left_grid = Gtk.Grid()
grid.attach(mirror_label, 1, 2, 1, 1) left_grid.set_row_spacing(4)
grid.attach(mirror_box, 2, 2, 1, 1) left_grid.set_column_spacing(6)
grid.attach(pool_name_label, 7, 2, 2, 1) left_grid.set_size_request(200, -1)
grid.attach(cls.pool, 9, 2, 2, 1)
grid.attach(cls.mirrorTips, 1, 3, 8, 1) mirror_label.set_alignment(0, 0.5)
# grid.attach(zfs4kcheck, 9, 3, 2, 1) pool_label.set_alignment(0, 0.5)
grid.attach(sw, 1, 4, 10, 3) swap_label.set_alignment(0, 0.5)
# grid.attach(scheme_label, 1, 9, 1, 1) cls.passwd_label.set_alignment(0, 0.5)
# grid.attach(shemebox, 2, 9, 1, 1) cls.vpasswd_label.set_alignment(0, 0.5)
# grid.attach(cls.swap_encrypt_check, 9, 15, 11, 12)
# grid.attach(swap_mirror_check, 9, 15, 11, 12) # Row 0-1: Pool Layout
# grid.attach(encrypt_check, 2, 8, 2, 1) left_grid.attach(mirror_label, 0, 0, 2, 1)
# grid.attach(cls.passwd_label, 1, 9, 1, 1) left_grid.attach(mirror_box, 0, 1, 2, 1)
# grid.attach(cls.password, 2, 9, 2, 1) # Row 2-3: Pool Name
# grid.attach(cls.strenght_label, 4, 9, 2, 1) left_grid.attach(pool_label, 0, 2, 2, 1)
# grid.attach(cls.vpasswd_label, 1, 10, 1, 1) left_grid.attach(cls.pool, 0, 3, 2, 1)
# grid.attach(cls.repassword, 2, 10, 2, 1) # Row 4-5: Swap Size
# grid.attach(cls.img, 4, 10, 2, 1) left_grid.attach(swap_label, 0, 4, 2, 1)
cls.vbox1.pack_start(grid, True, True, 10) left_grid.attach(cls.swap_entry, 0, 5, 2, 1)
# Row 6: Separator
sep = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
left_grid.attach(sep, 0, 6, 2, 1)
# Row 7: Encrypt Disk checkbox
left_grid.attach(encrypt_check, 0, 7, 2, 1)
# Row 8: Password label + strength indicator
left_grid.attach(cls.passwd_label, 0, 8, 1, 1)
left_grid.attach(cls.strenght_label, 1, 8, 1, 1)
# Row 9: Password input
left_grid.attach(cls.password, 0, 9, 2, 1)
# Row 10: Confirm label + match icon
left_grid.attach(cls.vpasswd_label, 0, 10, 1, 1)
left_grid.attach(cls.img, 1, 10, 1, 1)
# Row 11: Confirm input
left_grid.attach(cls.repassword, 0, 11, 2, 1)
hbox_main.pack_start(left_grid, False, False, 10)
# Right panel: tips + disk list
right_panel = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=False, spacing=0)
cls.mirrorTips.set_alignment(0, 0.5)
right_panel.pack_start(cls.mirrorTips, False, False, 0)
right_panel.pack_start(sw, True, True, 0)
hbox_main.pack_start(right_panel, True, True, 10)
cls.vbox1.pack_start(hbox_main, True, True, 10)
return return
@classmethod @classmethod
@@ -465,59 +500,11 @@ class ZFS:
model[path][3] = not model[path][3] model[path][3] = not model[path][3]
if model[path][3] is False: if model[path][3] is False:
cls.zfs_disk_list.remove(model[path][0] + "-" + model[path][1]) cls.zfs_disk_list.remove(model[path][0] + "-" + model[path][1])
if cls.mirror == "1+ disks Stripe": cls._update_next_button()
if len(cls.zfs_disk_list) >= 1:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "2+ disks Mirror":
if len(cls.zfs_disk_list) >= 2:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "3 disks RAIDZ1":
if len(cls.zfs_disk_list) == 3:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "4 disks RAIDZ2":
if len(cls.zfs_disk_list) == 4:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "5 disks RAIDZ3":
if len(cls.zfs_disk_list) == 5:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
else: else:
if cls.check_if_small_disk(model[path][1]) is False: if cls.check_if_small_disk(model[path][1]) is False:
cls.zfs_disk_list.extend([model[path][0] + "-" + model[path][1]]) cls.zfs_disk_list.extend([model[path][0] + "-" + model[path][1]])
if cls.mirror == "1+ disks Stripe": cls._update_next_button()
if len(cls.zfs_disk_list) >= 1:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "2+ disks Mirror":
if len(cls.zfs_disk_list) >= 2:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "3 disks RAIDZ1":
if len(cls.zfs_disk_list) == 3:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "4 disks RAIDZ2":
if len(cls.zfs_disk_list) == 4:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "5 disks RAIDZ3":
if len(cls.zfs_disk_list) == 5:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
else: else:
cls.check_cell.set_sensitive(False) cls.check_cell.set_sensitive(False)
cls.small_disk_warning() cls.small_disk_warning()
@@ -589,32 +576,8 @@ class ZFS:
_widget: Entry widget that triggered the verification (unused) _widget: Entry widget that triggered the verification (unused)
""" """
if cls.password.get_text() == cls.repassword.get_text(): if cls.password.get_text() == cls.repassword.get_text():
cls.img.set_from_stock(Gtk.STOCK_YES, 5) cls.img.set_from_icon_name("gtk-yes", Gtk.IconSize.MENU)
if cls.mirror == "1+ disks Stripe": cls._update_next_button()
if len(cls.zfs_disk_list) >= 1:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "2+ disks Mirror":
if len(cls.zfs_disk_list) >= 2:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "3 disks RAIDZ1":
if len(cls.zfs_disk_list) == 3:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "4 disks RAIDZ2":
if len(cls.zfs_disk_list) == 4:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
elif cls.mirror == "5 disks RAIDZ3":
if len(cls.zfs_disk_list) == 5:
Button.next_button.set_sensitive(True)
else:
Button.next_button.set_sensitive(False)
else: else:
cls.img.set_from_stock(Gtk.STOCK_NO, 5) cls.img.set_from_icon_name("gtk-no", Gtk.IconSize.MENU)
Button.next_button.set_sensitive(False) Button.next_button.set_sensitive(False)
+1 -1
View File
@@ -14,7 +14,7 @@ from DistUtilsExtra.command.build_i18n import build_i18n
from DistUtilsExtra.command.clean_i18n import clean_i18n from DistUtilsExtra.command.clean_i18n import clean_i18n
prefix = sys.prefix prefix = sys.prefix
__VERSION__ = '0.1' __VERSION__ = '0.4'
PROGRAM_VERSION = __VERSION__ PROGRAM_VERSION = __VERSION__