Release v0.7.2 - TTW Linux Installer 0.2.0

This commit is contained in:
Omni
2026-07-18 13:46:48 +01:00
parent d78e16f758
commit ada21f90c8
42 changed files with 1111 additions and 605 deletions
+4 -95
View File
@@ -16,10 +16,9 @@ from PySide6.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
QGroupBox, QTextEdit, QApplication
)
from PySide6.QtCore import Qt, QThread, Signal
from PySide6.QtCore import Qt
from PySide6.QtGui import QFont, QClipboard
from ....backend.services.update_service import UpdateService
from ....backend.models.configuration import SystemInfo
from .... import __version__
from jackify.frontends.gui.mixins.thread_lifecycle_mixin import ThreadLifecycleMixin
@@ -27,34 +26,13 @@ from jackify.frontends.gui.mixins.thread_lifecycle_mixin import ThreadLifecycleM
logger = logging.getLogger(__name__)
class UpdateCheckThread(QThread):
"""Background thread for checking updates."""
update_check_finished = Signal(object) # UpdateInfo or None
def __init__(self, update_service: UpdateService):
super().__init__()
self.update_service = update_service
def run(self):
"""Check for updates in background."""
try:
update_info = self.update_service.check_for_updates()
self.update_check_finished.emit(update_info)
except Exception as e:
logger.error(f"Error checking for updates: {e}")
self.update_check_finished.emit(None)
class AboutDialog(ThreadLifecycleMixin, QDialog):
"""About dialog showing system info and app details."""
def __init__(self, system_info: SystemInfo, parent=None):
super().__init__(parent)
self.system_info = system_info
self.update_service = UpdateService(__version__)
self.update_check_thread = None
self.setup_ui()
self.setup_connections()
@@ -117,45 +95,9 @@ class AboutDialog(ThreadLifecycleMixin, QDialog):
layout.addWidget(jackify_group)
# Update status
self.update_status_label = QLabel("")
self.update_status_label.setStyleSheet("color: #666; font-size: 10pt; margin: 5px;")
self.update_status_label.setAlignment(Qt.AlignCenter)
layout.addWidget(self.update_status_label)
# Buttons
button_layout = QHBoxLayout()
# Update check button
self.update_button = QPushButton("Check for Updates")
self.update_button.clicked.connect(self.check_for_updates)
self.update_button.setStyleSheet("""
QPushButton {
background-color: #23272e;
color: #3fd0ea;
font-weight: bold;
padding: 8px 16px;
border-radius: 4px;
border: 2px solid #3fd0ea;
}
QPushButton:hover {
background-color: #3fd0ea;
color: #23272e;
}
QPushButton:pressed {
background-color: #2bb8d6;
color: #23272e;
}
QPushButton:disabled {
background-color: #444;
color: #666;
border-color: #666;
}
""")
button_layout.addWidget(self.update_button)
button_layout.addStretch()
# Copy Info button
copy_button = QPushButton("Copy Info")
copy_button.clicked.connect(self.copy_system_info)
@@ -324,36 +266,6 @@ class AboutDialog(ThreadLifecycleMixin, QDialog):
logger.error(f"Error getting engine version: {e}")
return "Unknown"
def check_for_updates(self):
"""Check for updates in background."""
if self.update_check_thread and self.update_check_thread.isRunning():
return
self.update_button.setEnabled(False)
self.update_button.setText("Checking...")
self.update_status_label.setText("Checking for updates...")
self.update_check_thread = UpdateCheckThread(self.update_service)
self.update_check_thread.update_check_finished.connect(self.update_check_finished)
self.update_check_thread.start()
def update_check_finished(self, update_info):
"""Handle update check completion."""
self.update_button.setEnabled(True)
self.update_button.setText("Check for Updates")
if update_info:
self.update_status_label.setText(f"Update available: v{update_info.version}")
self.update_status_label.setStyleSheet("color: #3fd0ea; font-size: 10pt; margin: 5px;")
# Show update dialog
from .update_dialog import UpdateDialog
update_dialog = UpdateDialog(update_info, self.update_service, self)
update_dialog.exec()
else:
self.update_status_label.setText("You're running the latest version")
self.update_status_label.setStyleSheet("color: #666; font-size: 10pt; margin: 5px;")
def copy_system_info(self):
"""Copy system information to clipboard."""
try:
@@ -421,7 +333,4 @@ Python: {platform.python_version()}"""
def closeEvent(self, event):
"""Handle dialog close event."""
self.update_check_thread = self._park_thread(
self.update_check_thread, ["update_available", "no_update", "check_failed"]
)
event.accept()
@@ -319,14 +319,16 @@ class SettingsDialog(SettingsDialogTabsMixin, SettingsDialogProtonMixin, QDialog
# Save component installation method preference
if self.winetricks_radio.isChecked():
method = 'winetricks'
else: # protontricks_radio (alternative)
elif self.protontricks_radio.isChecked():
method = 'system_protontricks'
else: # native_radio (default)
method = 'native'
old_method = self.config_handler.get('component_installation_method', 'winetricks')
old_method = self.config_handler.get('component_installation_method', 'native')
method_changed = (old_method != method)
self.config_handler.set("component_installation_method", method)
self.config_handler.set("use_winetricks_for_components", method == 'winetricks')
self.config_handler.set("use_winetricks_for_components", method != 'system_protontricks')
# Force immediate save and verify
save_result = self.config_handler.save_config()
@@ -262,18 +262,29 @@ class SettingsDialogTabsMixin:
component_layout.addWidget(QLabel("Wine Components Installation:"))
self.component_method_group = QButtonGroup()
component_method_layout = QVBoxLayout()
current_method = self.config_handler.get('component_installation_method', 'winetricks')
current_method = self.config_handler.get('component_installation_method', 'native')
if current_method == 'bundled_protontricks':
current_method = 'system_protontricks'
self.winetricks_radio = QRadioButton("Winetricks (Default)")
self.native_radio = QRadioButton("Native (Default)")
self.native_radio.setChecked(current_method == 'native')
self.native_radio.setToolTip(
"Install components directly, without winetricks or protontricks, falling back to "
"bundled winetricks only for the handful of components not yet supported natively."
)
self.component_method_group.addButton(self.native_radio, 0)
component_method_layout.addWidget(self.native_radio)
self.winetricks_radio = QRadioButton("Winetricks")
self.winetricks_radio.setChecked(current_method == 'winetricks')
self.winetricks_radio.setToolTip("Use bundled winetricks for component installation. Faster and more reliable.")
self.component_method_group.addButton(self.winetricks_radio, 0)
self.winetricks_radio.setToolTip("Use bundled winetricks for every component, bypassing the native installer entirely.")
self.component_method_group.addButton(self.winetricks_radio, 1)
component_method_layout.addWidget(self.winetricks_radio)
self.protontricks_radio = QRadioButton("Protontricks (Alternative)")
self.protontricks_radio = QRadioButton("Protontricks")
self.protontricks_radio.setChecked(current_method == 'system_protontricks')
self.protontricks_radio.setToolTip("Use system-installed protontricks (flatpak or native). Fallback option if winetricks fails.")
self.component_method_group.addButton(self.protontricks_radio, 1)
self.protontricks_radio.setToolTip(
"Use system-installed protontricks (flatpak or native) for every component, "
"bypassing the native installer entirely."
)
self.component_method_group.addButton(self.protontricks_radio, 2)
component_method_layout.addWidget(self.protontricks_radio)
component_layout.addLayout(component_method_layout)
@@ -202,6 +202,7 @@ class SuccessDialog(QDialog):
"QLabel { color: #3fd0ea; font-size: 11px; margin-top: 4px; padding: 4px; background-color: transparent; }"
)
readme_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
readme_label.setOpenExternalLinks(False)
readme_label.linkActivated.connect(open_url)
card_layout.addWidget(readme_label)
@@ -218,6 +219,7 @@ class SuccessDialog(QDialog):
"}"
)
kofi_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
kofi_label.setOpenExternalLinks(False)
kofi_label.linkActivated.connect(open_url)
card_layout.addWidget(kofi_label)