diff --git a/main.spec b/main.spec index adfa183..c0bb049 100644 --- a/main.spec +++ b/main.spec @@ -55,7 +55,7 @@ if platform.system() == 'Darwin': # macOS a.datas, strip=True, name=f'{APP_NAME}.app', - icon=None, + icon='resources/Server.png', bundle_identifier=None, version=APP_VERSION ) diff --git a/server.py b/server.py index 949bec2..24fa882 100755 --- a/server.py +++ b/server.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from init import run +from src.init import run if __name__ == '__main__': run(server_only=True) diff --git a/src/api/preview_manager.py b/src/api/preview_manager.py index f2a454a..6f9db38 100644 --- a/src/api/preview_manager.py +++ b/src/api/preview_manager.py @@ -17,7 +17,7 @@ class PreviewManager: _running_jobs = {} @classmethod - def __generate_job_preview_worker(cls, job, replace_existing=False, max_width=320): + def __generate_job_preview_worker(cls, job, replace_existing=False, max_width=480): # Determine best source file to use for thumbs job_file_list = job.file_list() diff --git a/src/engines/blender/blender_worker.py b/src/engines/blender/blender_worker.py index da06a2e..e8414f0 100644 --- a/src/engines/blender/blender_worker.py +++ b/src/engines/blender/blender_worker.py @@ -31,6 +31,12 @@ class BlenderRenderWorker(BaseRenderWorker): cmd.append('-b') cmd.append(self.input_path) + # Set Render Engine + blender_engine = self.args.get('engine') + if blender_engine: + blender_engine = blender_engine.upper() + cmd.extend(['-E', blender_engine]) + # Start Python expressions - # todo: investigate splitting into separate 'setup' script cmd.append('--python-expr') python_exp = 'import bpy; bpy.context.scene.render.use_overwrite = False;' @@ -40,8 +46,7 @@ class BlenderRenderWorker(BaseRenderWorker): if custom_camera: python_exp = python_exp + f"bpy.context.scene.camera = bpy.data.objects['{custom_camera}'];" - # Set Render Device (gpu/cpu/any) - blender_engine = self.args.get('engine', 'BLENDER_EEVEE').upper() + # Set Render Device for Cycles (gpu/cpu/any) if blender_engine == 'CYCLES': render_device = self.args.get('render_device', 'any').lower() if render_device not in {'any', 'gpu', 'cpu'}: @@ -66,7 +71,7 @@ class BlenderRenderWorker(BaseRenderWorker): # Remove the extension only if it is not composed entirely of digits path_without_ext = main_part if not ext[1:].isdigit() else self.output_path path_without_ext += "_" - cmd.extend(['-E', blender_engine, '-o', path_without_ext, '-F', export_format]) + cmd.extend(['-o', path_without_ext, '-F', export_format]) # set frame range cmd.extend(['-s', self.start_frame, '-e', self.end_frame, '-a']) diff --git a/src/engines/engine_manager.py b/src/engines/engine_manager.py index 77018f8..a5afb35 100644 --- a/src/engines/engine_manager.py +++ b/src/engines/engine_manager.py @@ -305,18 +305,21 @@ class EngineDownloadWorker(threading.Thread): self.cpu = cpu def run(self): - existing_download = EngineManager.is_version_downloaded(self.engine, self.version, self.system_os, self.cpu) - if existing_download: - logger.info(f"Requested download of {self.engine} {self.version}, but local copy already exists") - return existing_download + try: + existing_download = EngineManager.is_version_downloaded(self.engine, self.version, self.system_os, self.cpu) + if existing_download: + logger.info(f"Requested download of {self.engine} {self.version}, but local copy already exists") + return existing_download - # Get the appropriate downloader class based on the engine type - EngineManager.engine_with_name(self.engine).downloader().download_engine( - self.version, download_location=EngineManager.engines_path, system_os=self.system_os, cpu=self.cpu, - timeout=300) - - # remove itself from the downloader list - EngineManager.download_tasks.remove(self) + # Get the appropriate downloader class based on the engine type + EngineManager.engine_with_name(self.engine).downloader().download_engine( + self.version, download_location=EngineManager.engines_path, system_os=self.system_os, cpu=self.cpu, + timeout=300) + except Exception as e: + logger.error(f"Error in download worker: {e}") + finally: + # remove itself from the downloader list + EngineManager.download_tasks.remove(self) if __name__ == '__main__': diff --git a/src/init.py b/src/init.py index 794ca62..e140bb9 100644 --- a/src/init.py +++ b/src/init.py @@ -1,6 +1,7 @@ import logging import multiprocessing import os +import platform import socket import sys import threading diff --git a/src/ui/main_window.py b/src/ui/main_window.py index e56782a..cf3ba14 100644 --- a/src/ui/main_window.py +++ b/src/ui/main_window.py @@ -29,7 +29,8 @@ from src.ui.widgets.proportional_image_label import ProportionalImageLabel from src.ui.widgets.statusbar import StatusBar from src.ui.widgets.toolbar import ToolBar from src.api.serverproxy_manager import ServerProxyManager -from src.utilities.misc_helper import launch_url +from src.utilities.misc_helper import launch_url, iso_datestring_to_formatted_datestring +from version import APP_NAME logger = logging.getLogger() @@ -63,7 +64,7 @@ class MainWindow(QMainWindow): self.buffer_handler = None # Window-Settings - self.setWindowTitle("Zordon") + self.setWindowTitle(APP_NAME) self.setGeometry(100, 100, 900, 800) central_widget = QWidget(self) self.setCentralWidget(central_widget) @@ -256,7 +257,7 @@ class MainWindow(QMainWindow): self.job_list_view.clear() self.refresh_job_headers() - job_fetch = self.current_server_proxy.get_all_jobs(ignore_token=clear_table) + job_fetch = self.current_server_proxy.get_all_jobs(ignore_token=False) if job_fetch: num_jobs = len(job_fetch) self.job_list_view.setRowCount(num_jobs) @@ -276,10 +277,11 @@ class MainWindow(QMainWindow): renderer = f"{job.get('renderer', '')}-{job.get('renderer_version')}" priority = str(job.get('priority', '')) total_frames = str(job.get('total_frames', '')) + date_created_string = iso_datestring_to_formatted_datestring(job['date_created']) items = [QTableWidgetItem(job['id']), QTableWidgetItem(name), QTableWidgetItem(renderer), QTableWidgetItem(priority), QTableWidgetItem(display_status), QTableWidgetItem(time_elapsed), - QTableWidgetItem(total_frames), QTableWidgetItem(job['date_created'])] + QTableWidgetItem(total_frames), QTableWidgetItem(date_created_string)] for col, item in enumerate(items): self.job_list_view.setItem(row, col, item) @@ -591,3 +593,21 @@ class MainWindow(QMainWindow): if file_name: self.new_job_window = NewRenderJobForm(file_name) self.new_job_window.show() + + +if __name__ == "__main__": + # lazy load GUI frameworks + from PyQt6.QtWidgets import QApplication + + # load application + # QtCore.QCoreApplication.setAttribute(QtCore.Qt.ApplicationAttribute.AA_MacDontSwapCtrlAndMeta) + app: QApplication = QApplication(sys.argv) + + # configure main main_window + main_window = MainWindow() + # main_window.buffer_handler = buffer_handler + app.setActiveWindow(main_window) + + main_window.show() + + sys.exit(app.exec()) diff --git a/src/utilities/misc_helper.py b/src/utilities/misc_helper.py index 1278e3c..f7fa4ef 100644 --- a/src/utilities/misc_helper.py +++ b/src/utilities/misc_helper.py @@ -210,3 +210,18 @@ def num_to_alphanumeric(num): result += characters[remainder] return result[::-1] # Reverse the result to get the correct alphanumeric string + + +def iso_datestring_to_formatted_datestring(iso_date_string): + from dateutil import parser + import pytz + + # Parse the ISO date string into a datetime object and convert timezones + date = parser.isoparse(iso_date_string).astimezone(pytz.UTC) + local_timezone = datetime.now().astimezone().tzinfo + date_local = date.astimezone(local_timezone) + + # Format the date to the desired readable yet sortable format with 12-hour time + formatted_date = date_local.strftime('%Y-%m-%d %I:%M %p') + + return formatted_date diff --git a/src/utilities/zeroconf_server.py b/src/utilities/zeroconf_server.py index aa43fd4..e1d526e 100644 --- a/src/utilities/zeroconf_server.py +++ b/src/utilities/zeroconf_server.py @@ -32,9 +32,11 @@ class ZeroconfServer: def start(cls, listen_only=False): if not cls.service_type: raise RuntimeError("The 'configure' method must be run before starting the zeroconf server") - logger.debug("Starting zeroconf service") - if not listen_only: + elif not listen_only: + logger.debug(f"Starting zeroconf service") cls._register_service() + else: + logger.debug(f"Starting zeroconf service - Listen only mode") cls._browse_services() @classmethod