Sync from development - prepare for v0.4.0

This commit is contained in:
Omni
2026-02-25 17:40:43 +00:00
parent 2eb54b9a36
commit 805718222a
324 changed files with 4914 additions and 4567 deletions

View File

@@ -5,7 +5,7 @@ File progress item widget for a single file's progress display.
from PySide6.QtWidgets import (
QWidget, QHBoxLayout, QLabel, QProgressBar, QSizePolicy
)
from PySide6.QtCore import Qt, QTimer
from PySide6.QtCore import Qt
from jackify.shared.progress_models import FileProgress, OperationType
from ..shared_theme import JACKIFY_COLOR_BLUE
@@ -17,13 +17,8 @@ class FileProgressItem(QWidget):
def __init__(self, file_progress: FileProgress, parent=None):
super().__init__(parent)
self.file_progress = file_progress
self._target_percent = file_progress.percent
self._current_display_percent = file_progress.percent
self._spinner_position = 0
self._is_indeterminate = False
self._animation_timer = QTimer(self)
self._animation_timer.timeout.connect(self._animate_progress)
self._animation_timer.setInterval(16)
self._is_queued = False
self._setup_ui()
self._update_display()
@@ -73,22 +68,24 @@ class FileProgressItem(QWidget):
def _get_operation_symbol(self) -> str:
symbols = {
OperationType.DOWNLOAD: "",
OperationType.EXTRACT: "",
OperationType.EXTRACT: "",
OperationType.VALIDATE: "",
OperationType.INSTALL: "",
OperationType.INSTALL: "",
}
return symbols.get(self.file_progress.operation, "")
def _truncate_filename(self, filename: str, max_length: int = 40) -> str:
if len(filename) <= max_length:
return filename
return filename[:max_length-3] + "..."
return filename[:max_length - 3] + "..."
def _update_display(self):
is_summary = hasattr(self.file_progress, '_is_summary') and self.file_progress._is_summary
no_progress_bar = hasattr(self.file_progress, '_no_progress_bar') and self.file_progress._no_progress_bar
is_summary = getattr(self.file_progress, '_is_summary', False)
no_progress_bar = getattr(self.file_progress, '_no_progress_bar', False)
if 'Installing Files' in self.file_progress.filename or 'Converting Texture' in self.file_progress.filename or 'BSA:' in self.file_progress.filename:
if ('Installing Files' in self.file_progress.filename
or 'Converting Texture' in self.file_progress.filename
or 'BSA:' in self.file_progress.filename):
name_display = self.file_progress.filename
elif self.file_progress.filename.startswith('Wine component:'):
rest = self.file_progress.filename.split(':', 1)[1].strip()
@@ -106,7 +103,8 @@ class FileProgressItem(QWidget):
self.filename_label.setToolTip(self.file_progress.filename)
if no_progress_bar:
self._animation_timer.stop()
self._is_indeterminate = False
self._is_queued = False
self.percent_label.setText("")
self.progress_bar.setVisible(False)
return
@@ -116,80 +114,58 @@ class FileProgressItem(QWidget):
if is_summary:
summary_step = getattr(self.file_progress, '_summary_step', 0)
summary_max = getattr(self.file_progress, '_summary_max', 0)
self._is_queued = False
if summary_max > 0:
percent = (summary_step / summary_max) * 100.0
self._target_percent = max(0, min(100, percent))
if not self._animation_timer.isActive():
self._animation_timer.start()
self.progress_bar.setRange(0, 100)
self._set_determinate((summary_step / summary_max) * 100.0)
else:
self._is_indeterminate = True
self.percent_label.setText("")
self.progress_bar.setRange(0, 100)
if not self._animation_timer.isActive():
self._animation_timer.start()
self._set_indeterminate()
return
is_queued = (
self.file_progress.total_size > 0 and
self.file_progress.percent == 0 and
self.file_progress.current_size == 0 and
self.file_progress.speed <= 0
self.file_progress.total_size > 0
and self.file_progress.percent == 0
and self.file_progress.current_size == 0
and self.file_progress.speed <= 0
)
if is_queued:
self._is_queued = True
self._is_indeterminate = False
self._animation_timer.stop()
self.percent_label.setText("Queued")
self.progress_bar.setRange(0, 100)
self.progress_bar.setValue(0)
return
self._is_queued = False
has_meaningful_progress = (
self.file_progress.percent > 0 or
(self.file_progress.total_size > 0 and self.file_progress.current_size > 0) or
(self.file_progress.speed > 0 and self.file_progress.percent >= 0)
self.file_progress.percent > 0
or (self.file_progress.total_size > 0 and self.file_progress.current_size > 0)
or (self.file_progress.speed > 0 and self.file_progress.percent >= 0)
)
if has_meaningful_progress:
self._is_indeterminate = False
self._target_percent = max(0, self.file_progress.percent)
if not self._animation_timer.isActive():
self._animation_timer.start()
self.progress_bar.setRange(0, 100)
self._set_determinate(max(0.0, self.file_progress.percent))
else:
self._set_indeterminate()
def _set_indeterminate(self):
if not self._is_indeterminate:
self._is_indeterminate = True
self.percent_label.setText("")
self.progress_bar.setRange(0, 100)
if not self._animation_timer.isActive():
self._animation_timer.start()
# Qt's QProgressStyleAnimation drives this automatically — no manual timer needed
self.progress_bar.setRange(0, 0)
self.percent_label.setText("")
def _animate_progress(self):
def _set_determinate(self, percent: float):
if self._is_indeterminate:
self._spinner_position = (self._spinner_position + 4) % 200
if self._spinner_position < 100:
display_value = self._spinner_position
else:
display_value = 200 - self._spinner_position
self.progress_bar.setValue(display_value)
self._is_indeterminate = False
self.progress_bar.setRange(0, 100)
self.progress_bar.setValue(int(max(0.0, min(100.0, percent))))
if self.file_progress.percent > 0:
self.percent_label.setText(f"{percent:.0f}%")
else:
diff = self._target_percent - self._current_display_percent
if abs(diff) >= 0.1:
self._current_display_percent += diff * 0.2
self._current_display_percent = max(0, min(100, self._current_display_percent))
display_percent = self._current_display_percent
self.progress_bar.setValue(int(display_percent))
if self.file_progress.percent > 0:
self.percent_label.setText(f"{display_percent:.0f}%")
else:
self.percent_label.setText("")
self.percent_label.setText("")
def update_progress(self, file_progress: FileProgress):
self.file_progress = file_progress
self._update_display()
def cleanup(self):
if self._animation_timer.isActive():
self._animation_timer.stop()
pass