From a79fe735293cbd53c7551f86a7955a147011e114 Mon Sep 17 00:00:00 2001 From: CodeByMrFinchum Date: Mon, 13 Jan 2025 15:44:02 +0100 Subject: [PATCH] Thread for processing images. --- src/OptimaLab35/gui.py | 131 +++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 63 deletions(-) diff --git a/src/OptimaLab35/gui.py b/src/OptimaLab35/gui.py index 1f5cc1b..ce99d86 100644 --- a/src/OptimaLab35/gui.py +++ b/src/OptimaLab35/gui.py @@ -7,13 +7,12 @@ import time from optima35.core import OptimaManager from OptimaLab35.utils.utility import Utilities from OptimaLab35.ui.main_window import Ui_MainWindow -#from OptimaLab35.ui.test_window import Ui_Test_Window from OptimaLab35.ui.preview_window import Ui_Preview_Window from OptimaLab35.ui.exif_handler_window import ExifEditor from OptimaLab35.ui.simple_dialog import SimpleDialog # Import the SimpleDialog class from OptimaLab35 import __version__ -from PySide6.QtCore import Signal +from PySide6.QtCore import QRunnable, QThreadPool, Signal, QObject from PySide6 import QtWidgets from PySide6.QtWidgets import ( @@ -68,13 +67,12 @@ class PreviewWindow(QMainWindow, Ui_Preview_Window): image_output_file = "", grayscale = self.ui.grayscale_checkBox.isChecked(), brightness = int(self.ui.brightness_spinBox.text()), - contrast = int(self.ui.contrast_spinBox.text()), + contrast = int(self.ui.contrast_spinBox.text()) ) except Exception as e: QMessageBox.warning(self, "Warning", "Error loading image...") print(f"Error loading image...\n{e}") return - # Create a QPixmap object from an image file self.preview_image = QPixmap.fromImage(img) self.ui.QLabel.setPixmap(self.preview_image) @@ -85,6 +83,55 @@ class PreviewWindow(QMainWindow, Ui_Preview_Window): self.values_selected.emit(self.ui.brightness_spinBox.value(), self.ui.contrast_spinBox.value(), self.ui.grayscale_checkBox.isChecked()) self.close() +class WorkerSignals(QObject): + # ChatGPT + progress = Signal(int) + finished = Signal() + +class ImageProcessorRunnable(QRunnable): + # ChatGPT gave rough function layout + def __init__(self, image_files, settings, progress_callback): + super().__init__() + self.image_files = image_files + self.settings = settings + self.signals = WorkerSignals() + self.signals.progress.connect(progress_callback) + self.o = OptimaManager() + self.u = Utilities() + + def run(self): + input_folder = self.settings["input_folder"] + output_folder = self.settings["output_folder"] + + for i, image_file in enumerate(self.image_files, start=1): + input_path = os.path.join(input_folder, image_file) + if self.settings["new_file_names"] != False: + image_name = self.u.append_number_to_name(self.settings["new_file_names"], i, len(self.image_files), self.settings["invert_image_order"]) + else: + image_name = os.path.splitext(image_file)[0] + output_path = os.path.join(output_folder, image_name) + + self.o.process_image( + image_input_file = input_path, + image_output_file = output_path, + file_type = self.settings["file_format"], + quality = self.settings["jpg_quality"], + compressing = self.settings["png_compression"], + optimize = self.settings["optimize"], + resize = self.settings["resize"], + watermark = self.settings["watermark"], + font_size = self.settings["font_size"], + grayscale = self.settings["grayscale"], + brightness = self.settings["brightness"], + contrast = self.settings["contrast"], + dict_for_exif = self.settings["user_selected_exif"], + gps = self.settings["gps"], + copy_exif = self.settings["copy_exif"] + ) + self.signals.progress.emit(int((i / len(self.image_files)) * 100)) + + self.signals.finished.emit() + class OptimaLab35(QMainWindow, Ui_MainWindow): def __init__(self): super(OptimaLab35, self).__init__() @@ -107,6 +154,7 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): self._change_statusbar(f"Using {self.o.name} v{self.o.version}", 5000) # Instantiate the second window self.preview_window = PreviewWindow() + self.thread_pool = QThreadPool() # multi thread ChatGPT def open_preview_window(self): self.preview_window.values_selected.connect(self.update_values) @@ -141,15 +189,6 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): self.ui.actionPreview.triggered.connect(self.open_preview_window) self.ui.preview_Button.clicked.connect(self.open_preview_window) - def _debug(self): - for i in range(10): - print(f"Testing... {i}") - time.sleep(.3) - - self._handle_qprogressbar(i, 10) - print("Finished") - self.ui.progressBar.setValue(0) - def _info_window(self): # ChatGPT, mainly info_text = f""" @@ -209,10 +248,19 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): self._toggle_buttons(True) return - self._process_images(image_list) + # Create a worker ChatGPT + worker = ImageProcessorRunnable(image_list, self.settings, self._handle_qprogressbar) + worker.signals.finished.connect(self._on_processing_finished) + # Start worker in thread pool ChatGPT + self.thread_pool.start(worker) + def _handle_qprogressbar(self, value): + self.ui.progressBar.setValue(value) + + def _on_processing_finished(self): self._toggle_buttons(True) - QMessageBox.information(self, "Information", "Finished") + self._handle_qprogressbar(0) + QMessageBox.information(self, "Information", "Finished!") def _toggle_buttons(self, state): self.ui.start_button.setEnabled(state) @@ -220,40 +268,6 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): if self.ui.exif_checkbox.isChecked(): self.ui.insert_exif_Button.setEnabled(state) - def _process_images(self, image_files): - input_folder = self.settings["input_folder"] - output_folder = self.settings["output_folder"] - - i = 1 - for image_file in image_files: - input_path = os.path.join(input_folder, image_file) - if self.settings["new_file_names"] != False: - image_name = self.u.append_number_to_name(self.settings["new_file_names"], i, len(image_files), self.settings["invert_image_order"]) - else: - image_name = os.path.splitext(image_file)[0] - output_path = os.path.join(output_folder, image_name) - - self.o.process_image( - image_input_file = input_path, - image_output_file = output_path, - file_type = self.settings["file_format"], - quality = self.settings["jpg_quality"], - compressing = self.settings["png_compression"], - optimize = self.ui.optimize_checkBox.isChecked(), - resize = self.settings["resize"], - watermark = self.settings["watermark"], - font_size = self.settings["font_size"], - grayscale = self.settings["grayscale"], - brightness = self.settings["brightness"], - contrast = self.settings["contrast"], - dict_for_exif = self.user_selected_exif, - gps = self.settings["gps"], - copy_exif = self.settings["copy_exif"]) - self._handle_qprogressbar(i, len(image_files)) - i += 1 - - self.ui.progressBar.setValue(0) - def _insert_exif(self, image_files): input_folder = self.settings["input_folder"] @@ -261,14 +275,13 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): for image_file in image_files: input_path = os.path.join(input_folder, image_file) - print(input_path) self.o.insert_dict_to_image( - exif_dict = self.user_selected_exif, + exif_dict = self.settings["user_selected_exif"], image_path = input_path, gps = self.settings["gps"]) self._change_statusbar(image_file, 100) - self._handle_qprogressbar(i, len(image_files)) + self._handle_qprogressbar(int((i / len(image_files)) * 100)) i += 1 self.ui.progressBar.setValue(0) @@ -422,10 +435,6 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): def _change_statusbar(self, msg, timeout = 500): self.ui.statusBar.showMessage(msg, timeout) - def _handle_qprogressbar(self, current, total): - progress = int((100 / total) * current) - self.ui.progressBar.setValue(progress) - def _get_checkbox_value(self, checkbox, default=None): """Helper function to get the value of a checkbox or a default value.""" return checkbox.isChecked() if checkbox else default @@ -472,23 +481,19 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): # Conditional settings with logic self.settings["resize"] = int(self.ui.resize_spinBox.text()) if self.ui.resize_spinBox.text() != "100" else None - #self._get_spinbox_value(self.ui.resize_spinBox) if self.ui.resize_checkbox.isChecked() else None self.settings["brightness"] = int(self.ui.brightness_spinBox.text()) if self.ui.brightness_spinBox.text() != "0" else None - #self._get_spinbox_value(self.ui.brightness_spinBox) if self.ui.brightness_checkbox.isChecked() else None self.settings["contrast"] = int(self.ui.contrast_spinBox.text()) if self.ui.contrast_spinBox.text() != "0" else None - #self._get_spinbox_value(self.ui.contrast_spinBox) if self.ui.contrast_checkbox.isChecked() else None new_name = self._get_text_value(self.ui.filename, False) if self.ui.rename_checkbox.isChecked() else False if isinstance(new_name, str): new_name = new_name.replace(" ", "_") self.settings["new_file_names"] = new_name self.settings["watermark"] = self.ui.watermark_lineEdit.text() if len(self.ui.watermark_lineEdit.text()) != 0 else None - #self._get_text_value(self.ui.watermark_lineEdit) if self.ui.watermark_checkbox.isChecked() else None # Handle EXIF data selection if self.settings["own_exif"]: - self.user_selected_exif = self._get_selected_exif() + self.settings["user_selected_exif"] = self._get_selected_exif() else: - self.user_selected_exif = None + self.settings["user_selected_exif"] = None self.settings["gps"] = None def _get_date(self): @@ -512,7 +517,7 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): def closeEvent(self, event): self.preview_window.close() - def check_version(self, min_version="0.6.5-a1"): + def check_version(self, min_version="0.6.6"): # Mainly ChatGPT from packaging import version # Use `packaging` for robust version comparison