Add disk selection dialog and improve GUI layout

- Add DiskSelectionDialog class for manual disk selection
- Implement select_installation_disk method with size display and model info
- Update GUI layout to place Network, Disk, and Timezone side by side in first row
- Add QScrollArea to prevent content from going out of sight
- Update start_installation to include selected disk in config
- Ensure proper validation for disk selection before installation
- Maintain auto-detection as default with manual override capability

This provides users with manual disk selection while keeping auto-detection
as the default, and ensures all GUI content remains visible with proper scrolling.
parent c54ccba7
...@@ -118,6 +118,107 @@ class TimezoneDialog(QDialog): ...@@ -118,6 +118,107 @@ class TimezoneDialog(QDialog):
else: else:
QMessageBox.warning(self, "Selection Required", "Please select a timezone") QMessageBox.warning(self, "Selection Required", "Please select a timezone")
class DiskSelectionDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Select Installation Disk")
self.setModal(True)
self.setMinimumSize(600, 400)
self.selected_disk = None
layout = QVBoxLayout(self)
# Disk selection
disk_group = QGroupBox("Available Installation Disks")
disk_layout = QVBoxLayout(disk_group)
self.disk_list = QListWidget()
self.disk_list.itemClicked.connect(self.disk_selected)
disk_layout.addWidget(self.disk_list)
layout.addWidget(disk_group)
# Buttons
button_layout = QHBoxLayout()
self.ok_button = QPushButton("OK")
self.ok_button.clicked.connect(self.accept_selection)
self.cancel_button = QPushButton("Cancel")
self.cancel_button.clicked.connect(self.reject)
button_layout.addWidget(self.ok_button)
button_layout.addWidget(self.cancel_button)
layout.addLayout(button_layout)
self.load_disks()
def load_disks(self):
"""Load available disks"""
try:
# Get all available disk devices
result = subprocess.run(['lsblk', '-rno', 'NAME,TYPE'], capture_output=True, text=True, check=True)
disks = []
for line in result.stdout.strip().split('\n'):
if line and 'disk' in line:
parts = line.split()
if len(parts) >= 1:
disks.append(f'/dev/{parts[0]}')
# Find USB device to exclude
usb_device = None
for mount_point in ['/lib/live/mount/medium', '/cdrom', '/run/live/medium']:
if os.path.isdir(mount_point):
try:
result = subprocess.run(['df', mount_point], capture_output=True, text=True, check=True)
lines = result.stdout.strip().split('\n')
if len(lines) >= 2:
device = lines[1].split()[0]
device = re.sub(r'\d+$', '', device)
if os.path.exists(device):
usb_device = device
break
except subprocess.CalledProcessError:
continue
# Add suitable disks to list
for disk in disks:
if disk == usb_device:
continue
try:
size_result = subprocess.run(['lsblk', '-rbno', 'SIZE', disk],
capture_output=True, text=True, check=True)
size_bytes = int(size_result.stdout.strip().split('\n')[0])
size_gb = size_bytes // (1024 * 1024 * 1024)
if size_gb >= 4:
# Get disk model
try:
model_result = subprocess.run(['lsblk', '-rno', 'MODEL', disk],
capture_output=True, text=True, check=True)
model = model_result.stdout.strip().split('\n')[0] or "Unknown"
except subprocess.CalledProcessError:
model = "Unknown"
item_text = f"{disk} - {size_gb} GB ({model})"
item = QListWidgetItem(item_text)
item.setData(Qt.ItemDataRole.UserRole, disk)
self.disk_list.addItem(item)
except (subprocess.CalledProcessError, ValueError, IndexError):
continue
except subprocess.CalledProcessError:
QMessageBox.warning(self, "Error", "Could not detect disks")
def disk_selected(self, item):
"""Handle disk selection"""
self.selected_disk = item.data(Qt.ItemDataRole.UserRole)
def accept_selection(self):
"""Validate and accept selection"""
if not self.selected_disk:
QMessageBox.warning(self, "Selection Required", "Please select an installation disk")
return
self.accept()
class NetworkInterfaceDialog(QDialog): class NetworkInterfaceDialog(QDialog):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
...@@ -740,8 +841,17 @@ class AutoInstallerGUI(QMainWindow): ...@@ -740,8 +841,17 @@ class AutoInstallerGUI(QMainWindow):
self.set_defaults() self.set_defaults()
def init_ui(self): def init_ui(self):
from PyQt6.QtWidgets import QScrollArea
# Create scroll area for main content
scroll_area = QScrollArea()
scroll_area.setWidgetResizable(True)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
central_widget = QWidget() central_widget = QWidget()
self.setCentralWidget(central_widget) scroll_area.setWidget(central_widget)
self.setCentralWidget(scroll_area)
layout = QVBoxLayout(central_widget) layout = QVBoxLayout(central_widget)
# Header # Header
...@@ -750,20 +860,13 @@ class AutoInstallerGUI(QMainWindow): ...@@ -750,20 +860,13 @@ class AutoInstallerGUI(QMainWindow):
header.setFont(QFont("Arial", 24, QFont.Weight.Bold)) header.setFont(QFont("Arial", 24, QFont.Weight.Bold))
layout.addWidget(header) layout.addWidget(header)
# Timezone Selection - Graphical Dialog # Main configuration row - Network, Disk, Timezone side by side
timezone_group = QGroupBox("Timezone Selection") config_row = QHBoxLayout()
timezone_layout = QVBoxLayout(timezone_group)
self.timezone_button = QPushButton("Select Timezone...")
self.timezone_button.clicked.connect(self.open_timezone_dialog)
self.timezone_label = QLabel("No timezone selected (default: UTC)")
timezone_layout.addWidget(self.timezone_button)
timezone_layout.addWidget(self.timezone_label)
layout.addWidget(timezone_group)
# Network Configuration # Network Configuration
network_group = QGroupBox("Network Configuration (Optional)") network_group = QGroupBox("Network Configuration")
network_layout = QVBoxLayout(network_group) network_layout = QVBoxLayout(network_group)
self.network_checkbox = QCheckBox("Configure network for installed system") self.network_checkbox = QCheckBox("Configure network")
self.network_checkbox.stateChanged.connect(self.toggle_network_config) self.network_checkbox.stateChanged.connect(self.toggle_network_config)
network_layout.addWidget(self.network_checkbox) network_layout.addWidget(self.network_checkbox)
...@@ -771,9 +874,9 @@ class AutoInstallerGUI(QMainWindow): ...@@ -771,9 +874,9 @@ class AutoInstallerGUI(QMainWindow):
network_form = QVBoxLayout(self.network_widget) network_form = QVBoxLayout(self.network_widget)
# Interface selection button # Interface selection button
self.interface_button = QPushButton("Select Network Interface...") self.interface_button = QPushButton("Select Interface...")
self.interface_button.clicked.connect(self.select_network_interface) self.interface_button.clicked.connect(self.select_network_interface)
self.interface_label = QLabel("No interface selected") self.interface_label = QLabel("Auto-detecting...")
network_form.addWidget(self.interface_button) network_form.addWidget(self.interface_button)
network_form.addWidget(self.interface_label) network_form.addWidget(self.interface_label)
...@@ -803,7 +906,29 @@ class AutoInstallerGUI(QMainWindow): ...@@ -803,7 +906,29 @@ class AutoInstallerGUI(QMainWindow):
network_form.addWidget(ip_group) network_form.addWidget(ip_group)
network_layout.addWidget(self.network_widget) network_layout.addWidget(self.network_widget)
layout.addWidget(network_group) config_row.addWidget(network_group)
# Disk Selection
disk_group = QGroupBox("Installation Disk")
disk_layout = QVBoxLayout(disk_group)
self.disk_button = QPushButton("Select Installation Disk...")
self.disk_button.clicked.connect(self.select_installation_disk)
self.disk_label = QLabel("Auto-detecting...")
disk_layout.addWidget(self.disk_button)
disk_layout.addWidget(self.disk_label)
config_row.addWidget(disk_group)
# Timezone Selection
timezone_group = QGroupBox("Timezone Selection")
timezone_layout = QVBoxLayout(timezone_group)
self.timezone_button = QPushButton("Select Timezone...")
self.timezone_button.clicked.connect(self.open_timezone_dialog)
self.timezone_label = QLabel("Auto-detecting...")
timezone_layout.addWidget(self.timezone_button)
timezone_layout.addWidget(self.timezone_label)
config_row.addWidget(timezone_group)
layout.addLayout(config_row)
# Confirmation # Confirmation
self.confirm_button = QPushButton("Confirm and Start Installation") self.confirm_button = QPushButton("Confirm and Start Installation")
...@@ -1024,6 +1149,23 @@ class AutoInstallerGUI(QMainWindow): ...@@ -1024,6 +1149,23 @@ class AutoInstallerGUI(QMainWindow):
def toggle_static_ip_fields(self, method): def toggle_static_ip_fields(self, method):
self.static_ip_widget.setVisible(method == "Static IP (manual)") self.static_ip_widget.setVisible(method == "Static IP (manual)")
def select_installation_disk(self):
"""Open dialog to select installation disk"""
dialog = DiskSelectionDialog(self)
if dialog.exec() == QDialog.DialogCode.Accepted:
self.selected_disk = dialog.selected_disk
if self.selected_disk:
try:
size_result = subprocess.run(['lsblk', '-rbno', 'SIZE', self.selected_disk],
capture_output=True, text=True, check=True)
size_bytes = int(size_result.stdout.strip().split('\n')[0])
size_gb = size_bytes // (1024 * 1024 * 1024)
self.disk_label.setText(f"Selected: {self.selected_disk} ({size_gb} GB)")
except (subprocess.CalledProcessError, ValueError, IndexError):
self.disk_label.setText(f"Selected: {self.selected_disk}")
else:
self.disk_label.setText("No disk selected")
def select_network_interface(self): def select_network_interface(self):
"""Open dialog to select network interface - same logic as auto-installer.sh""" """Open dialog to select network interface - same logic as auto-installer.sh"""
dialog = NetworkInterfaceDialog(self) dialog = NetworkInterfaceDialog(self)
...@@ -1054,6 +1196,13 @@ class AutoInstallerGUI(QMainWindow): ...@@ -1054,6 +1196,13 @@ class AutoInstallerGUI(QMainWindow):
QMessageBox.warning(self, "Network Configuration", "Please select a network interface first") QMessageBox.warning(self, "Network Configuration", "Please select a network interface first")
return return
# Get disk selection
if hasattr(self, 'selected_disk') and self.selected_disk:
self.config['target_disk'] = self.selected_disk
else:
QMessageBox.warning(self, "Disk Selection", "Please select an installation disk first")
return
self.confirm_button.setEnabled(False) self.confirm_button.setEnabled(False)
self.worker = InstallerWorker(self.config) self.worker = InstallerWorker(self.config)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment