mirror of
https://github.com/nixietab/picodulce.git
synced 2025-12-10 00:28:43 +00:00
added actual progressbar to the version prepare menu
This commit is contained in:
parent
da0f4449ea
commit
9bac8e2d6d
169
loaddaemon.py
169
loaddaemon.py
@ -3,6 +3,7 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import shlex
|
import shlex
|
||||||
import gc
|
import gc
|
||||||
|
import re
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QProgressBar, QPushButton, QHBoxLayout
|
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QProgressBar, QPushButton, QHBoxLayout
|
||||||
from PyQt5.QtCore import Qt, pyqtSignal, QObject, QTimer, QEvent
|
from PyQt5.QtCore import Qt, pyqtSignal, QObject, QTimer, QEvent
|
||||||
@ -40,7 +41,7 @@ class StreamingCapture(StringIO):
|
|||||||
# Signal/Object might be deleted
|
# Signal/Object might be deleted
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not self.launch_detected:
|
if not self.launch_detected and self.launch_signal:
|
||||||
lower_text = text.lower()
|
lower_text = text.lower()
|
||||||
if "launching" in lower_text and ("game" in lower_text or "version" in lower_text or "minecraft" in lower_text):
|
if "launching" in lower_text and ("game" in lower_text or "version" in lower_text or "minecraft" in lower_text):
|
||||||
self.launch_detected = True
|
self.launch_detected = True
|
||||||
@ -193,8 +194,174 @@ class LaunchWindow(QDialog):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PrepareWindow(QDialog):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle("Preparing Version")
|
||||||
|
self.setModal(True)
|
||||||
|
self.resize(400, 150)
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.status_label = QLabel("Initializing...")
|
||||||
|
self.status_label.setWordWrap(True)
|
||||||
|
self.status_label.setAlignment(Qt.AlignCenter)
|
||||||
|
layout.addWidget(self.status_label)
|
||||||
|
|
||||||
|
self.progress_bar = QProgressBar()
|
||||||
|
self.progress_bar.setRange(0, 0) # Indeterminate progress
|
||||||
|
self.progress_bar.setTextVisible(False)
|
||||||
|
layout.addWidget(self.progress_bar)
|
||||||
|
|
||||||
|
# Add a manual close/cancel button
|
||||||
|
button_layout = QHBoxLayout()
|
||||||
|
button_layout.addStretch()
|
||||||
|
self.cancel_button = QPushButton("Cancel")
|
||||||
|
self.cancel_button.clicked.connect(self.request_abort)
|
||||||
|
button_layout.addWidget(self.cancel_button)
|
||||||
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
self.signals = LaunchSignals()
|
||||||
|
self.signals.log_update.connect(self.update_status)
|
||||||
|
self.signals.launch_complete.connect(self.on_prepare_complete)
|
||||||
|
self.signals.launch_aborted.connect(self.on_prepare_aborted)
|
||||||
|
self.signals.cleanup_done.connect(self.on_cleanup_done)
|
||||||
|
|
||||||
|
self.aborting = False
|
||||||
|
self.capture_streams = []
|
||||||
|
self.thread_running = False
|
||||||
|
self.success = False
|
||||||
|
|
||||||
|
def update_status(self, text):
|
||||||
|
# Parse output for progress updates
|
||||||
|
|
||||||
|
if "Downloading" in text and "libraries" in text:
|
||||||
|
try:
|
||||||
|
count = int(re.search(r'\d+', text).group())
|
||||||
|
self.status_label.setText(f"Downloading {count} libraries...")
|
||||||
|
except:
|
||||||
|
self.status_label.setText(text)
|
||||||
|
elif "Checking" in text and "assets" in text:
|
||||||
|
try:
|
||||||
|
count = int(re.search(r'\d+', text).group())
|
||||||
|
self.status_label.setText(f"Checking {count} assets...")
|
||||||
|
except:
|
||||||
|
self.status_label.setText(text)
|
||||||
|
elif "Jar file" in text and "downloaded" in text:
|
||||||
|
self.status_label.setText("Downloading game jar...")
|
||||||
|
elif "Checking libraries" in text:
|
||||||
|
self.status_label.setText("Checking libraries...")
|
||||||
|
else:
|
||||||
|
if len(text) > 100:
|
||||||
|
text = text[:97] + "..."
|
||||||
|
self.status_label.setText(text)
|
||||||
|
|
||||||
|
def on_prepare_complete(self):
|
||||||
|
if not self.aborting:
|
||||||
|
self.success = True
|
||||||
|
self.status_label.setText("Version prepared successfully!")
|
||||||
|
self.progress_bar.setRange(0, 100)
|
||||||
|
self.progress_bar.setValue(100)
|
||||||
|
self.cancel_button.setEnabled(False)
|
||||||
|
QTimer.singleShot(1500, self.accept)
|
||||||
|
|
||||||
|
def on_prepare_aborted(self):
|
||||||
|
self.status_label.setText("Preparation Aborted.")
|
||||||
|
self.progress_bar.setRange(0, 100)
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
self.success = False
|
||||||
|
|
||||||
|
def on_cleanup_done(self):
|
||||||
|
self.thread_running = False
|
||||||
|
if not self.success:
|
||||||
|
super().reject()
|
||||||
|
|
||||||
|
def request_abort(self):
|
||||||
|
if self.thread_running and not self.aborting:
|
||||||
|
self.aborting = True
|
||||||
|
self.status_label.setText("Aborting...")
|
||||||
|
self.cancel_button.setEnabled(False)
|
||||||
|
# Signal streams to stop
|
||||||
|
for stream in self.capture_streams:
|
||||||
|
stream.abort_requested = True
|
||||||
|
elif not self.thread_running:
|
||||||
|
super().reject()
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
self.request_abort()
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
if self.thread_running:
|
||||||
|
event.ignore()
|
||||||
|
self.request_abort()
|
||||||
|
else:
|
||||||
|
event.accept()
|
||||||
|
|
||||||
|
def prepare_version(self, version):
|
||||||
|
command = f"version prepare {version}"
|
||||||
|
self.thread_running = True
|
||||||
|
thread = threading.Thread(target=self._run_prepare, args=(command,), daemon=True)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
def _run_prepare(self, command):
|
||||||
|
try:
|
||||||
|
modules_to_remove = [mod for mod in sys.modules if mod.startswith('zucaro')]
|
||||||
|
for mod in modules_to_remove:
|
||||||
|
del sys.modules[mod]
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
from zucaro.cli.main import zucaro_cli
|
||||||
|
|
||||||
|
old_stdout, old_stderr = sys.stdout, sys.stderr
|
||||||
|
|
||||||
|
stdout_capture = StreamingCapture(self.signals.log_update, None)
|
||||||
|
stderr_capture = StreamingCapture(self.signals.log_update, None)
|
||||||
|
|
||||||
|
self.capture_streams = [stdout_capture, stderr_capture]
|
||||||
|
|
||||||
|
sys.stdout = stdout_capture
|
||||||
|
sys.stderr = stderr_capture
|
||||||
|
|
||||||
|
try:
|
||||||
|
zucaro_cli.main(args=shlex.split(command), standalone_mode=False)
|
||||||
|
except AbortException:
|
||||||
|
self.signals.launch_aborted.emit()
|
||||||
|
except SystemExit:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
self.signals.log_update.emit(f"Error: {str(e)}")
|
||||||
|
finally:
|
||||||
|
sys.stdout = old_stdout
|
||||||
|
sys.stderr = old_stderr
|
||||||
|
|
||||||
|
if not stdout_capture.abort_requested:
|
||||||
|
self.signals.launch_complete.emit()
|
||||||
|
|
||||||
|
modules_to_remove = [mod for mod in sys.modules if mod.startswith('zucaro')]
|
||||||
|
for mod in modules_to_remove:
|
||||||
|
del sys.modules[mod]
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
self.signals.cleanup_done.emit()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
self.signals.log_update.emit(f"Error preparing version: {str(e)}")
|
||||||
|
self.signals.cleanup_done.emit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def launch_instance_with_window(command, parent=None):
|
def launch_instance_with_window(command, parent=None):
|
||||||
window = LaunchWindow(parent)
|
window = LaunchWindow(parent)
|
||||||
window.launch_game(command)
|
window.launch_game(command)
|
||||||
window.exec_()
|
window.exec_()
|
||||||
return window
|
return window
|
||||||
|
|
||||||
|
def prepare_version_with_window(version, parent=None):
|
||||||
|
window = PrepareWindow(parent)
|
||||||
|
window.prepare_version(version)
|
||||||
|
result = window.exec_()
|
||||||
|
return window.success
|
||||||
|
|||||||
47
picodulce.py
47
picodulce.py
@ -1402,21 +1402,7 @@ class zucaroVersionSelector(QWidget):
|
|||||||
dialog.finished.connect(self.populate_installed_versions)
|
dialog.finished.connect(self.populate_installed_versions)
|
||||||
dialog.exec_()
|
dialog.exec_()
|
||||||
|
|
||||||
class DownloadThread(QThread):
|
|
||||||
completed = pyqtSignal(bool, str)
|
|
||||||
|
|
||||||
def __init__(self, version):
|
|
||||||
super().__init__()
|
|
||||||
self.version = version
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
try:
|
|
||||||
command = f"version prepare {self.version}"
|
|
||||||
modulecli.run_command(command)
|
|
||||||
self.completed.emit(True, f"Version {self.version} prepared successfully!")
|
|
||||||
except Exception as e:
|
|
||||||
error_message = f"Error preparing {self.version}: {str(e)}"
|
|
||||||
self.completed.emit(False, error_message)
|
|
||||||
|
|
||||||
class ModLoaderAndVersionMenu(QDialog):
|
class ModLoaderAndVersionMenu(QDialog):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -1795,39 +1781,12 @@ class ModLoaderAndVersionMenu(QDialog):
|
|||||||
def update_download_button_state(self):
|
def update_download_button_state(self):
|
||||||
self.download_button.setEnabled(self.version_combo.currentIndex() != -1)
|
self.download_button.setEnabled(self.version_combo.currentIndex() != -1)
|
||||||
|
|
||||||
def show_popup(self):
|
|
||||||
self.popup = QDialog(self)
|
|
||||||
self.popup.setWindowTitle("Installing Version")
|
|
||||||
layout = QVBoxLayout(self.popup)
|
|
||||||
|
|
||||||
label = QLabel("The version is being installed...")
|
|
||||||
layout.addWidget(label)
|
|
||||||
|
|
||||||
movie = QMovie("drums.gif")
|
|
||||||
gif_label = QLabel()
|
|
||||||
gif_label.setMovie(movie)
|
|
||||||
layout.addWidget(gif_label)
|
|
||||||
|
|
||||||
movie.start()
|
|
||||||
self.popup.setGeometry(200, 200, 300, 200)
|
|
||||||
self.popup.setWindowModality(Qt.ApplicationModal)
|
|
||||||
self.popup.show()
|
|
||||||
|
|
||||||
def download_version(self, version):
|
def download_version(self, version):
|
||||||
# Show the popup in the main thread
|
success = loaddaemon.prepare_version_with_window(version, self)
|
||||||
self.show_popup()
|
|
||||||
|
|
||||||
self.download_thread = DownloadThread(version)
|
|
||||||
self.download_thread.completed.connect(self.on_download_completed)
|
|
||||||
self.download_thread.start()
|
|
||||||
|
|
||||||
def on_download_completed(self, success, message):
|
|
||||||
self.popup.close()
|
|
||||||
if success:
|
if success:
|
||||||
QMessageBox.information(self, "Success", message)
|
QMessageBox.information(self, "Success", f"Version {version} prepared successfully!")
|
||||||
else:
|
else:
|
||||||
QMessageBox.critical(self, "Error", message)
|
QMessageBox.critical(self, "Error", f"Failed to prepare version {version}.")
|
||||||
logging.error(message)
|
|
||||||
|
|
||||||
def populate_available_releases(self, version_combo, install_forge, install_fabric):
|
def populate_available_releases(self, version_combo, install_forge, install_fabric):
|
||||||
try:
|
try:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user