Fix py2app (#69)
* Initial commit of py2app code * Use environment variable RESOURCE_PATH when running as a bundle * Move config files to system config location
1
main.py
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from src import init
|
from src import init
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 921 B After Width: | Height: | Size: 921 B |
|
Before Width: | Height: | Size: 476 B After Width: | Height: | Size: 476 B |
|
Before Width: | Height: | Size: 979 B After Width: | Height: | Size: 979 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 450 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 694 B After Width: | Height: | Size: 694 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 816 B After Width: | Height: | Size: 816 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 806 B After Width: | Height: | Size: 806 B |
21
setup.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
"""
|
||||||
|
This is a setup.py script generated by py2applet
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python setup.py py2app
|
||||||
|
"""
|
||||||
|
import glob
|
||||||
|
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
APP = ['main.py']
|
||||||
|
DATA_FILES = [('config', glob.glob('config/*.*')),
|
||||||
|
('resources', glob.glob('resources/*.*'))]
|
||||||
|
OPTIONS = {}
|
||||||
|
|
||||||
|
setup(
|
||||||
|
app=APP,
|
||||||
|
data_files=DATA_FILES,
|
||||||
|
options={'py2app': OPTIONS},
|
||||||
|
setup_requires=['py2app'],
|
||||||
|
)
|
||||||
@@ -26,7 +26,7 @@ from src.engines.engine_manager import EngineManager
|
|||||||
from src.render_queue import RenderQueue, JobNotFoundError
|
from src.render_queue import RenderQueue, JobNotFoundError
|
||||||
from src.utilities.config import Config
|
from src.utilities.config import Config
|
||||||
from src.utilities.misc_helper import system_safe_path, current_system_os, current_system_cpu, \
|
from src.utilities.misc_helper import system_safe_path, current_system_os, current_system_cpu, \
|
||||||
current_system_os_version, config_dir
|
current_system_os_version
|
||||||
from src.utilities.server_helper import generate_thumbnail_for_job
|
from src.utilities.server_helper import generate_thumbnail_for_job
|
||||||
from src.utilities.zeroconf_server import ZeroconfServer
|
from src.utilities.zeroconf_server import ZeroconfServer
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ def sorted_jobs(all_jobs, sort_by_date=True):
|
|||||||
@server.route('/')
|
@server.route('/')
|
||||||
@server.route('/index')
|
@server.route('/index')
|
||||||
def index():
|
def index():
|
||||||
with open(system_safe_path(os.path.join(config_dir(), 'presets.yaml'))) as f:
|
with open(system_safe_path(os.path.join(Config.config_dir(), 'presets.yaml'))) as f:
|
||||||
render_presets = yaml.load(f, Loader=yaml.FullLoader)
|
render_presets = yaml.load(f, Loader=yaml.FullLoader)
|
||||||
|
|
||||||
return render_template('index.html', all_jobs=sorted_jobs(RenderQueue.all_jobs()),
|
return render_template('index.html', all_jobs=sorted_jobs(RenderQueue.all_jobs()),
|
||||||
|
|||||||
@@ -25,9 +25,8 @@ def run() -> int:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Load Config YAML
|
# Load Config YAML
|
||||||
config_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'config')
|
Config.setup_config_dir()
|
||||||
Config.load_config(system_safe_path(os.path.join(config_dir, 'config.yaml')))
|
Config.load_config(system_safe_path(os.path.join(Config.config_dir(), 'config.yaml')))
|
||||||
|
|
||||||
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(module)s: %(message)s', datefmt='%d-%b-%y %H:%M:%S',
|
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(module)s: %(message)s', datefmt='%d-%b-%y %H:%M:%S',
|
||||||
level=Config.server_log_level.upper())
|
level=Config.server_log_level.upper())
|
||||||
|
|
||||||
|
|||||||
@@ -401,7 +401,7 @@ class MainWindow(QMainWindow):
|
|||||||
for hostname in found_servers:
|
for hostname in found_servers:
|
||||||
if hostname not in current_server_list:
|
if hostname not in current_server_list:
|
||||||
properties = ZeroconfServer.get_hostname_properties(hostname)
|
properties = ZeroconfServer.get_hostname_properties(hostname)
|
||||||
image_path = os.path.join(resources_dir(), 'icons', f"{properties.get('system_os', 'Monitor')}.png")
|
image_path = os.path.join(resources_dir(), f"{properties.get('system_os', 'Monitor')}.png")
|
||||||
list_widget = QListWidgetItem(QIcon(image_path), hostname)
|
list_widget = QListWidgetItem(QIcon(image_path), hostname)
|
||||||
self.server_list_view.addItem(list_widget)
|
self.server_list_view.addItem(list_widget)
|
||||||
|
|
||||||
@@ -438,23 +438,22 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# Top Toolbar Buttons
|
# Top Toolbar Buttons
|
||||||
self.topbar.add_button(
|
self.topbar.add_button(
|
||||||
"New Job", f"{resources_directory}/icons/AddProduct.png", self.new_job)
|
"Console", f"{resources_directory}/Console.png", self.open_console_window)
|
||||||
self.topbar.add_button(
|
self.topbar.add_button(
|
||||||
"Engines", f"{resources_directory}/icons/SoftwareInstaller.png", self.engine_browser)
|
"Engines", f"{resources_directory}/SoftwareInstaller.png", self.engine_browser)
|
||||||
self.topbar.add_button(
|
|
||||||
"Console", f"{resources_directory}/icons/Console.png", self.open_console_window)
|
|
||||||
self.topbar.add_separator()
|
self.topbar.add_separator()
|
||||||
self.topbar.add_button(
|
self.topbar.add_button(
|
||||||
"Stop Job", f"{resources_directory}/icons/StopSign.png", self.stop_job)
|
"Stop Job", f"{resources_directory}/StopSign.png", self.stop_job)
|
||||||
self.topbar.add_button(
|
self.topbar.add_button(
|
||||||
"Delete Job", f"{resources_directory}/icons/Trash.png", self.delete_job)
|
"Delete Job", f"{resources_directory}/Trash.png", self.delete_job)
|
||||||
self.topbar.add_button(
|
self.topbar.add_button(
|
||||||
"Render Log", f"{resources_directory}/icons/Document.png", self.job_logs)
|
"Render Log", f"{resources_directory}/Document.png", self.job_logs)
|
||||||
self.topbar.add_button(
|
self.topbar.add_button(
|
||||||
"Download", f"{resources_directory}/icons/Download.png", self.download_files)
|
"Download", f"{resources_directory}/Download.png", self.download_files)
|
||||||
self.topbar.add_button(
|
self.topbar.add_button(
|
||||||
"Open Files", f"{resources_directory}/icons/SearchFolder.png", self.open_files)
|
"Open Files", f"{resources_directory}/SearchFolder.png", self.open_files)
|
||||||
|
self.topbar.add_button(
|
||||||
|
"New Job", f"{resources_directory}/AddProduct.png", self.new_job)
|
||||||
self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.topbar)
|
self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.topbar)
|
||||||
|
|
||||||
# -- Toolbar Buttons -- #
|
# -- Toolbar Buttons -- #
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class StatusBar(QStatusBar):
|
|||||||
while True:
|
while True:
|
||||||
new_status = proxy.status()
|
new_status = proxy.status()
|
||||||
new_image_name = image_names.get(new_status, 'Synchronize.png')
|
new_image_name = image_names.get(new_status, 'Synchronize.png')
|
||||||
image_path = os.path.join(resources_dir(), 'icons', new_image_name)
|
image_path = os.path.join(resources_dir(), new_image_name)
|
||||||
self.label.setPixmap((QPixmap(image_path).scaled(16, 16, Qt.AspectRatioMode.KeepAspectRatio)))
|
self.label.setPixmap((QPixmap(image_path).scaled(16, 16, Qt.AspectRatioMode.KeepAspectRatio)))
|
||||||
|
|
||||||
# add download status
|
# add download status
|
||||||
@@ -54,7 +54,7 @@ class StatusBar(QStatusBar):
|
|||||||
|
|
||||||
# Create a label that holds an image
|
# Create a label that holds an image
|
||||||
self.label = QLabel()
|
self.label = QLabel()
|
||||||
image_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'resources', 'icons',
|
image_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'resources',
|
||||||
'RedSquare.png')
|
'RedSquare.png')
|
||||||
pixmap = (QPixmap(image_path).scaled(16, 16, Qt.AspectRatioMode.KeepAspectRatio))
|
pixmap = (QPixmap(image_path).scaled(16, 16, Qt.AspectRatioMode.KeepAspectRatio))
|
||||||
self.label.setPixmap(pixmap)
|
self.label.setPixmap(pixmap)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import yaml
|
import yaml
|
||||||
|
from src.utilities.misc_helper import current_system_os, copy_directory_contents
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
@@ -34,3 +35,40 @@ class Config:
|
|||||||
cls.port_number = cfg.get('port_number', cls.port_number)
|
cls.port_number = cfg.get('port_number', cls.port_number)
|
||||||
cls.enable_split_jobs = cfg.get('enable_split_jobs', cls.enable_split_jobs)
|
cls.enable_split_jobs = cfg.get('enable_split_jobs', cls.enable_split_jobs)
|
||||||
cls.download_timeout_seconds = cfg.get('download_timeout_seconds', cls.download_timeout_seconds)
|
cls.download_timeout_seconds = cfg.get('download_timeout_seconds', cls.download_timeout_seconds)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def config_dir(cls):
|
||||||
|
# Setup the config path
|
||||||
|
if current_system_os() == 'macos':
|
||||||
|
local_config_path = os.path.expanduser('~/Library/Application Support/Zordon')
|
||||||
|
elif current_system_os() == 'windows':
|
||||||
|
local_config_path = os.path.join(os.environ['APPDATA'], 'Zordon')
|
||||||
|
else:
|
||||||
|
local_config_path = os.path.expanduser('~/.config/Zordon')
|
||||||
|
return local_config_path
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setup_config_dir(cls):
|
||||||
|
# Setup the config path
|
||||||
|
local_config_dir = cls.config_dir()
|
||||||
|
if os.path.exists(local_config_dir):
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Create the local configuration directory
|
||||||
|
os.makedirs(local_config_dir)
|
||||||
|
|
||||||
|
# Determine the template path
|
||||||
|
resource_environment_path = os.environ.get('RESOURCEPATH')
|
||||||
|
if resource_environment_path:
|
||||||
|
template_path = os.path.join(resource_environment_path, 'config')
|
||||||
|
else:
|
||||||
|
template_path = os.path.join(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'config')
|
||||||
|
|
||||||
|
# Copy contents from the template to the local configuration directory
|
||||||
|
copy_directory_contents(template_path, local_config_dir)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred while setting up the config directory: {e}")
|
||||||
|
raise
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -127,15 +128,24 @@ def current_system_cpu():
|
|||||||
|
|
||||||
|
|
||||||
def resources_dir():
|
def resources_dir():
|
||||||
resources_directory = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
resource_environment_path = os.environ.get('RESOURCEPATH', None)
|
||||||
'resources')
|
if resource_environment_path: # running inside resource bundle
|
||||||
return resources_directory
|
return os.path.join(resource_environment_path, 'resources')
|
||||||
|
else:
|
||||||
|
return os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'resources')
|
||||||
|
|
||||||
|
|
||||||
def config_dir():
|
def copy_directory_contents(src_dir, dst_dir):
|
||||||
config_directory = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
"""
|
||||||
'config')
|
Copy the contents of the source directory (src_dir) to the destination directory (dst_dir).
|
||||||
return config_directory
|
"""
|
||||||
|
for item in os.listdir(src_dir):
|
||||||
|
src_path = os.path.join(src_dir, item)
|
||||||
|
dst_path = os.path.join(dst_dir, item)
|
||||||
|
if os.path.isdir(src_path):
|
||||||
|
shutil.copytree(src_path, dst_path, dirs_exist_ok=True)
|
||||||
|
else:
|
||||||
|
shutil.copy2(src_path, dst_path)
|
||||||
|
|
||||||
|
|
||||||
def is_localhost(comparison_hostname):
|
def is_localhost(comparison_hostname):
|
||||||
|
|||||||