234 lines
9.1 KiB
Python
234 lines
9.1 KiB
Python
import sys, glob, json, os
|
|
from PySide6 import QtWidgets
|
|
from PySide6.QtWidgets import (
|
|
QApplication,
|
|
QWidget,
|
|
QRadioButton,
|
|
QButtonGroup,
|
|
QGroupBox,
|
|
QVBoxLayout,
|
|
QHBoxLayout,
|
|
QLabel,
|
|
QFileDialog,
|
|
QInputDialog,
|
|
QMessageBox,
|
|
)
|
|
from PySide6.QtCore import Slot
|
|
from readdisk import ReadDiskWindow
|
|
from ui_main_window import Ui_MainWindow
|
|
from ui_read_disk import Ui_ReadDialog
|
|
|
|
# Inherit only from the Qt base class
|
|
class MainWindow(QtWidgets.QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
self.settings = self.get_defaults()
|
|
|
|
# Create an instance of the UI class
|
|
self.ui = Ui_MainWindow()
|
|
# Call its setupUi method, passing in the current window (self)
|
|
self.ui.setupUi(self)
|
|
|
|
# 1. Create the logical group. Pass `self` for parentage.
|
|
self.logical_button_group = QButtonGroup(self)
|
|
|
|
# 2. Add all radio buttons from different containers.
|
|
# Assign a unique integer ID to each one. This is best practice.
|
|
self.logical_button_group.addButton(self.ui.rb_read, 1)
|
|
self.logical_button_group.addButton(self.ui.rb_write, 2)
|
|
self.logical_button_group.addButton(self.ui.rb_clean_heads, 3)
|
|
self.logical_button_group.addButton(self.ui.rb_erase_disk, 4)
|
|
self.logical_button_group.addButton(self.ui.rb_convert_files, 5)
|
|
self.logical_button_group.addButton(self.ui.rb_info, 6)
|
|
self.logical_button_group.addButton(self.ui.rb_measure, 7)
|
|
self.logical_button_group.addButton(self.ui.rb_pin_level, 8)
|
|
self.logical_button_group.addButton(self.ui.rb_reset, 9)
|
|
self.logical_button_group.addButton(self.ui.rb_rpm, 10)
|
|
self.logical_button_group.addButton(self.ui.rb_seek, 11)
|
|
self.logical_button_group.addButton(self.ui.rb_delays, 12)
|
|
self.logical_button_group.addButton(self.ui.rb_update_firmware, 13)
|
|
self.profile = "GWUIDefault"
|
|
|
|
self.ui.rb_read.setChecked(True)
|
|
|
|
# Populate combo_port with /dev/ttyACM* devices
|
|
self.populate_serial_ports()
|
|
self.profile = "GWUIDefault"
|
|
|
|
# Populate combo_profile with available profiles
|
|
self.populate_profiles()
|
|
self.ui.combo_profile.currentTextChanged.connect(self.on_combo_profile_changed)
|
|
|
|
self.load_settings(self.profile)
|
|
|
|
self.ui.combo_port.setCurrentText(self.settings.get("device", "Auto"))
|
|
self.ui.combo_port.currentTextChanged.connect(self.on_combo_port_text_changed)
|
|
|
|
self.ui.action_quit.triggered.connect(self.close)
|
|
self.ui.pb_close.clicked.connect(self.close)
|
|
self.ui.pb_execute.clicked.connect(self.on_execute)
|
|
self.ui.pb_refresh_ports.clicked.connect(self.populate_serial_ports)
|
|
|
|
self.ui.pb_add_profile.clicked.connect(self.on_pb_add_profile)
|
|
self.ui.pb_delete_profile.clicked.connect(self.on_pb_delete_profile)
|
|
|
|
def on_combo_profile_changed(self, profile_name: str):
|
|
if profile_name:
|
|
self.profile = profile_name
|
|
self.load_settings(self.profile)
|
|
self.ui.combo_port.setCurrentText(self.settings.get("device", "Auto"))
|
|
|
|
def on_pb_add_profile(self):
|
|
text, ok = QInputDialog.getText(self, "Add Profile", "Enter new profile name:")
|
|
if ok and text:
|
|
self.profile = text
|
|
self.settings = self.get_defaults()
|
|
self.save_settings(self.profile)
|
|
self.populate_profiles()
|
|
|
|
self.ui.combo_profile.setCurrentText(self.profile)
|
|
self.on_combo_profile_changed(self.profile)
|
|
|
|
def on_pb_delete_profile(self):
|
|
"""Delete the currently selected profile and load the previous one, or defaults if none remain."""
|
|
config_path = self.get_config_path(self.profile)
|
|
try:
|
|
if os.path.exists(config_path):
|
|
os.remove(config_path)
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "Error", f"Failed to delete profile: {e}")
|
|
return
|
|
# Refresh profile list
|
|
self.populate_profiles()
|
|
profiles = [self.ui.combo_profile.itemText(i) for i in range(self.ui.combo_profile.count())]
|
|
if profiles:
|
|
# Select the previous profile in the list, or the first if deleted was first
|
|
idx = profiles.index(self.profile) if self.profile in profiles else 0
|
|
if idx > 0:
|
|
idx -= 1
|
|
self.profile = profiles[idx]
|
|
self.ui.combo_profile.setCurrentText(self.profile)
|
|
self.load_settings(self.profile)
|
|
self.ui.combo_port.setCurrentText(self.settings.get("device", "Auto"))
|
|
else:
|
|
# No profiles left, create default
|
|
self.profile = "GWUIDefault"
|
|
self.settings = self.get_defaults()
|
|
self.save_settings(self.profile)
|
|
self.populate_profiles()
|
|
self.ui.combo_profile.setCurrentText(self.profile)
|
|
self.ui.combo_port.setCurrentText(self.settings.get("device", "Auto"))
|
|
|
|
def on_combo_port_text_changed(self, text: str) -> None:
|
|
self.settings["device"] = text
|
|
self.save_settings(self.profile)
|
|
|
|
def get_defaults(self):
|
|
return {
|
|
"fileprefix": "disk-image",
|
|
"filepath": "",
|
|
"device": "Auto",
|
|
"double_step_enabled": False,
|
|
"double_step_value": "1",
|
|
"fake_index_enabled": False,
|
|
"fake_index_value": "300",
|
|
"fake_index_unit": "",
|
|
"bitrate_enabled": False,
|
|
"bitrate_value": "250",
|
|
"revs_enabled": False,
|
|
"revs_value": "3",
|
|
"drive_select_enabled": False,
|
|
"drive_select_value": "A",
|
|
"retries_enabled": False,
|
|
"retriesAttributeError: 'MainWindow' object has no attribute 'profile'_value": "3",
|
|
"pllspec_enabled": False,
|
|
"pll_period": "",
|
|
"pll_phase": "",
|
|
"pll_lowpass": "",
|
|
"head_sets_enabled": False,
|
|
"head_sets_value": "0-1",
|
|
"head_swap_enabled": False,
|
|
"ss_legacy_enabled": False,
|
|
"cylinder_sets_enabled": False,
|
|
"cylinder_sets_value": "0-34,35-79",
|
|
"rev_track_data_enabled": False,
|
|
"hard_sectors_enabled": False,
|
|
"no_clobber_enabled": False,
|
|
"raw_enabled": False,
|
|
"pin2_enabled": False,
|
|
"pin2_high": False,
|
|
"pin2_low": False,
|
|
"flippy_enabled": False,
|
|
"flippy_panasonic": True,
|
|
"flippy_teac": False,
|
|
"adjust_speed_enabled": False,
|
|
"adjust_speed_value": "300",
|
|
"adjust_speed_unit": "",
|
|
"suffix_value": "",
|
|
"inc_enabled": True,
|
|
"format_enabled": False,
|
|
"format_value": "",
|
|
"disktype_value": ""
|
|
}
|
|
|
|
def get_config_path(self, profile_name: str) -> str:
|
|
"""Return the full path for a profile config file in ~/.config/gwui/"""
|
|
config_dir = os.path.expanduser("~/.config/gwui")
|
|
if not os.path.exists(config_dir):
|
|
os.makedirs(config_dir, exist_ok=True)
|
|
return os.path.join(config_dir, profile_name + ".json")
|
|
|
|
@Slot()
|
|
def on_execute(self):
|
|
read_disk_window = ReadDiskWindow()
|
|
# read_disk_window.set_port(self.ui.combo_port.currentText())
|
|
read_disk_window.set_settings(self.settings)
|
|
read_disk_window.exec()
|
|
self.settings = read_disk_window.get_settings()
|
|
self.settings["device"] = self.ui.combo_port.currentText()
|
|
self.save_settings(self.profile)
|
|
|
|
def load_settings(self, profile_name: str):
|
|
config_path = self.get_config_path(profile_name)
|
|
if profile_name:
|
|
if os.path.exists(config_path):
|
|
with open(config_path, 'r') as f:
|
|
self.settings = json.load(f)
|
|
return True
|
|
return False
|
|
|
|
def save_settings(self, profile_name: str):
|
|
config_path = self.get_config_path(profile_name)
|
|
if profile_name:
|
|
with open(config_path, 'w') as f:
|
|
json.dump(self.settings, f, indent=2)
|
|
|
|
def populate_serial_ports(self):
|
|
"""Populate the combo_port with all /dev/ttyACM* devices."""
|
|
ports = glob.glob('/dev/ttyACM*')
|
|
self.ui.combo_port.clear()
|
|
self.ui.combo_port.addItem("Auto")
|
|
self.ui.combo_port.addItems(ports)
|
|
|
|
def populate_profiles(self):
|
|
"""Populate combo_profile with all config files in ~/.config/gwui/ (minus .json)."""
|
|
config_dir = os.path.expanduser("~/.config/gwui")
|
|
if not os.path.exists(config_dir):
|
|
os.makedirs(config_dir, exist_ok=True)
|
|
profiles = []
|
|
for fname in os.listdir(config_dir):
|
|
if fname.endswith('.json'):
|
|
profiles.append(fname[:-5])
|
|
self.ui.combo_profile.clear()
|
|
self.ui.combo_profile.addItems(sorted(profiles))
|
|
# Optionally, set current profile
|
|
if self.profile in profiles:
|
|
self.ui.combo_profile.setCurrentText(self.profile)
|
|
|
|
if __name__ == "__main__":
|
|
app = QtWidgets.QApplication(sys.argv)
|
|
window = MainWindow()
|
|
window.show()
|
|
sys.exit(app.exec())
|