diff --git a/src/main.py b/src/main.py index 58cb044..4685f5f 100644 --- a/src/main.py +++ b/src/main.py @@ -201,6 +201,7 @@ class WorkerThread(QThread): def stop(self): self.is_running = False + self.wait() class MainWindow(QMainWindow): @@ -222,6 +223,18 @@ class MainWindow(QMainWindow): self._scan_library() self._on_refresh_devices_clicked() + def _cleanup_worker(self): + """Safely clean up the worker thread after it finishes. + + Calls wait() to ensure the C++ thread is fully cleaned up before + dropping the Python reference. This prevents the Qt crash: + 'QThread: Destroyed while thread is still running' + """ + if self.worker_thread: + self.worker_thread.wait(3000) + self.worker_thread.deleteLater() + self.worker_thread = None + def _setup_ui(self): main_widget = QWidget() main_layout = QVBoxLayout(main_widget) @@ -632,6 +645,10 @@ class MainWindow(QMainWindow): QMessageBox.warning(self, "Error", "Please enter a valid URL") return + if self.worker_thread and self.worker_thread.isRunning(): + QMessageBox.information(self, "Info", "Please wait for the current task to finish") + return + self.download_button.setEnabled(False) self.download_status.setText("Downloading...") self.download_progress.setValue(0) @@ -669,7 +686,7 @@ class MainWindow(QMainWindow): self.downloaded_tracks = [] self.track_list.clear() - self.worker_thread = None + self._cleanup_worker() def _on_library_convert_clicked(self): source_files = self._get_selected_source_files() @@ -682,6 +699,10 @@ class MainWindow(QMainWindow): ) return + if self.worker_thread and self.worker_thread.isRunning(): + QMessageBox.information(self, "Info", "Please wait for the current task to finish") + return + output_dir = self.output_dir_input.text().strip() if not output_dir: QMessageBox.warning(self, "Error", "Please set an output directory") @@ -718,7 +739,7 @@ class MainWindow(QMainWindow): self.library_status.setText(f"Error: {message}") QMessageBox.warning(self, "Conversion Error", message) - self.worker_thread = None + self._cleanup_worker() def _on_library_transfer_clicked(self): selected_tracks = self._get_selected_ready_tracks() @@ -730,6 +751,10 @@ class MainWindow(QMainWindow): QMessageBox.warning(self, "Error", "No iPod device mounted. Go to iPod tab and mount first.") return + if self.worker_thread and self.worker_thread.isRunning(): + QMessageBox.information(self, "Info", "Please wait for the current task to finish") + return + self.library_transfer_btn.setEnabled(False) self.library_status.setText("Transferring...") self.library_progress.setValue(0) @@ -759,9 +784,12 @@ class MainWindow(QMainWindow): self.library_status.setText(f"Error: {message}") QMessageBox.warning(self, "Transfer Error", message) - self.worker_thread = None + self._cleanup_worker() def _on_refresh_devices_clicked(self): + if self.worker_thread and self.worker_thread.isRunning(): + return + self.device_combo.clear() self.device_info_label.setText("Detecting devices...") @@ -807,7 +835,7 @@ class MainWindow(QMainWindow): self._set_device_not_found() self.statusBar().showMessage(message) - self.worker_thread = None + self._cleanup_worker() def _set_device_mounted(self, device: dict, mount_point: str): self.current_mount_point = mount_point @@ -1010,7 +1038,8 @@ class MainWindow(QMainWindow): def closeEvent(self, event): if self.worker_thread and self.worker_thread.isRunning(): self.worker_thread.stop() - self.worker_thread.wait() + self.worker_thread.wait(5000) + self.worker_thread.deleteLater() event.accept()