More WIP for the Settings panel

This commit is contained in:
Brett Williams
2025-02-28 22:18:57 -06:00
parent 9aafb5c0fb
commit a4e6fca73d
2 changed files with 129 additions and 25 deletions

View File

@@ -23,6 +23,10 @@ class EngineManager:
def supported_engines():
return [Blender, FFMPEG]
@classmethod
def downloadable_engines(cls):
return [engine for engine in cls.supported_engines() if hasattr(engine, "downloader") and engine.downloader()]
@classmethod
def engine_with_name(cls, engine_name):
for obj in cls.supported_engines():

View File

@@ -1,19 +1,32 @@
import humanize
import socket
from datetime import datetime
from PyQt6 import QtCore
from PyQt6.QtCore import Qt
from PyQt6.QtCore import Qt, QSettings
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication, QMainWindow, QListWidget, QListWidgetItem, QStackedWidget, QVBoxLayout, \
QWidget, QLabel, QCheckBox, QLineEdit, \
QComboBox, QPushButton, QHBoxLayout, QGroupBox, QTableWidget, QAbstractItemView, QTableWidgetItem, QHeaderView
from api.server_proxy import RenderServerProxy
from engines.engine_manager import EngineManager
from utilities.misc_helper import launch_url
from version import APP_AUTHOR, APP_NAME
settings = QSettings(APP_AUTHOR, APP_NAME)
class SettingsWindow(QMainWindow):
def __init__(self):
super().__init__()
# declare objects we need to store settings
self.check_for_engine_updates_checkbox = None
# todo: add all here
self.installed_engines_table = None
self.setWindowTitle("Settings")
# Create the main layout
@@ -33,7 +46,7 @@ class SettingsWindow(QMainWindow):
# Add items with icons to the sidebar
self.add_sidebar_item("General", "../../resources/Gear.png")
self.add_sidebar_item("Server", "../../resources/Server.png")
self.add_sidebar_item("Network", "../../resources/Server.png")
self.add_sidebar_item("Engines", "../../resources/Blender.png")
self.sidebar.setCurrentRow(0)
@@ -50,8 +63,6 @@ class SettingsWindow(QMainWindow):
self.stacked_widget.addWidget(network_page)
self.stacked_widget.addWidget(engines_page)
self.installed_engines_table = None
# Connect the sidebar to the stacked widget
self.sidebar.currentRowChanged.connect(self.stacked_widget.setCurrentIndex)
@@ -90,21 +101,33 @@ class SettingsWindow(QMainWindow):
# Startup Settings Group
startup_group = QGroupBox("Startup Settings")
startup_layout = QVBoxLayout()
startup_layout.addWidget(QCheckBox("Start application on system startup"))
startup_layout.addWidget(QCheckBox("Check for updates automatically"))
# startup_layout.addWidget(QCheckBox("Start application on system startup"))
check_for_updates_checkbox = QCheckBox("Check for updates automatically")
check_for_updates_checkbox.setChecked(settings.value("auto_check_for_updates", True))
check_for_updates_checkbox.stateChanged.connect(lambda state: settings.setValue("auto_check_for_updates", bool(state)))
startup_layout.addWidget(check_for_updates_checkbox)
startup_group.setLayout(startup_layout)
# Language Settings Group
language_group = QGroupBox("Language Settings")
language_layout = QVBoxLayout()
language_layout.addWidget(QLabel("Language"))
language_combo = QComboBox()
language_combo.addItems(["English", "Spanish", "French", "German"])
language_layout.addWidget(language_combo)
language_group.setLayout(language_layout)
# Render Settings Group
render_settings_group = QGroupBox("Render Settings")
render_settings_layout = QVBoxLayout()
render_settings_layout.addWidget(QLabel("Require same:"))
require_same_engine_checkbox = QCheckBox("Renderer Version")
require_same_engine_checkbox.setChecked(settings.value("render_require_same_engine_version"))
require_same_engine_checkbox.stateChanged.connect(lambda state: settings.setValue("render_require_same_engine_version", bool(state)))
render_settings_layout.addWidget(require_same_engine_checkbox)
require_same_cpu_checkbox = QCheckBox("CPU Architecture")
require_same_cpu_checkbox.setChecked(settings.value("render_require_same_cpu_type"))
require_same_cpu_checkbox.stateChanged.connect(lambda state: settings.setValue("render_require_same_cpu_type", bool(state)))
render_settings_layout.addWidget(require_same_cpu_checkbox)
require_same_os_checkbox = QCheckBox("Operating System")
require_same_os_checkbox.setChecked(settings.value("render_require_same_os"))
require_same_os_checkbox.stateChanged.connect(lambda state: settings.setValue("render_require_same_os", bool(state)))
render_settings_layout.addWidget(require_same_os_checkbox)
render_settings_group.setLayout(render_settings_layout)
layout.addWidget(startup_group)
layout.addWidget(language_group)
layout.addWidget(render_settings_group)
layout.addStretch() # Add a stretch to push content to the top
page.setLayout(layout)
@@ -142,31 +165,92 @@ class SettingsWindow(QMainWindow):
self.installed_engines_table = EngineTableWidget()
installed_layout.addWidget(self.installed_engines_table)
installed_buttons_layout = QHBoxLayout()
check_engine_updates_button = QPushButton("Check for New Versions")
launch_engine_button = QPushButton("Launch")
launch_engine_button.clicked.connect(self.launch_selected_engine)
delete_engine_button = QPushButton("Delete")
delete_engine_button.clicked.connect(self.delete_selected_engine)
installed_buttons_layout.addWidget(check_engine_updates_button)
installed_buttons_layout.addWidget(launch_engine_button)
installed_buttons_layout.addWidget(delete_engine_button)
installed_layout.addLayout(installed_buttons_layout)
installed_group.setLayout(installed_layout)
# Display Options Group
display_group = QGroupBox("Display Options")
display_layout = QVBoxLayout()
display_layout.addWidget(QCheckBox("Enable high DPI scaling"))
display_layout.addWidget(QCheckBox("Show status bar"))
display_group.setLayout(display_layout)
# Engine Updates Group
engine_updates_group = QGroupBox("Auto-Install")
engine_updates_layout = QVBoxLayout()
engine_download_layout = QHBoxLayout()
engine_download_layout.addWidget(QLabel("Enable Downloads for:"))
at_least_one_downloadable = False
for engine in EngineManager.downloadable_engines():
engine_download_check = QCheckBox(engine.name())
is_checked = settings.value(f"engine_download-{engine.name()}", False)
at_least_one_downloadable |= is_checked
engine_download_check.setChecked(is_checked)
# Capture the checkbox correctly using a default argument in lambda
engine_download_check.clicked.connect(
lambda state, checkbox=engine_download_check: self.engine_download_settings_changed(state, checkbox.text())
)
engine_download_layout.addWidget(engine_download_check)
engine_updates_layout.addLayout(engine_download_layout)
self.check_for_engine_updates_checkbox = QCheckBox("Check for new versions on launch")
self.check_for_engine_updates_checkbox.setChecked(settings.value('check_for_engine_updates_on_launch', True))
self.check_for_engine_updates_checkbox.setEnabled(at_least_one_downloadable)
self.check_for_engine_updates_checkbox.stateChanged.connect(
lambda state: settings.setValue("check_for_engine_updates_on_launch", bool(state)))
engine_updates_layout.addWidget(self.check_for_engine_updates_checkbox)
self.engines_last_update_label = QLabel()
self.update_last_checked_label()
self.engines_last_update_label.setEnabled(at_least_one_downloadable)
engine_updates_layout.addWidget(self.engines_last_update_label)
self.check_for_new_engines_button = QPushButton("Check for New Versions")
self.check_for_new_engines_button.setEnabled(at_least_one_downloadable)
self.check_for_new_engines_button.clicked.connect(self.check_for_new_engines)
engine_updates_layout.addWidget(self.check_for_new_engines_button)
engine_updates_group.setLayout(engine_updates_layout)
layout.addWidget(installed_group)
layout.addWidget(display_group)
layout.addWidget(engine_updates_group)
layout.addStretch() # Add a stretch to push content to the top
page.setLayout(layout)
return page
def update_last_checked_label(self):
"""Retrieve the last check timestamp and return a human-friendly string."""
last_checked_str = settings.value("engines_last_update_time", None)
if not last_checked_str:
time_string = "Never"
else:
last_checked_dt = datetime.fromisoformat(last_checked_str)
now = datetime.now()
time_string = humanize.naturaltime(now - last_checked_dt)
self.engines_last_update_label.setText(f"Last Updated: {time_string}")
def engine_download_settings_changed(self, state, engine_name):
settings.setValue(f"engine_download-{engine_name}", state)
at_least_one_downloadable = False
for engine in EngineManager.downloadable_engines():
at_least_one_downloadable |= settings.value(f"engine_download-{engine.name()}", False)
self.check_for_new_engines_button.setEnabled(at_least_one_downloadable)
self.check_for_engine_updates_checkbox.setEnabled(at_least_one_downloadable)
self.engines_last_update_label.setEnabled(at_least_one_downloadable)
def delete_selected_engine(self):
pass
def launch_selected_engine(self):
engine_info = self.installed_engines_table.selected_engine_data()
if engine_info:
launch_url(engine_info['path'])
def check_for_new_engines(self):
settings.setValue("engines_last_update_time", datetime.now().isoformat())
self.update_last_checked_label()
class EngineTableWidget(QWidget):
def __init__(self):
@@ -214,6 +298,22 @@ class EngineTableWidget(QWidget):
self.table.selectRow(0)
def selected_engine_data(self):
"""Returns the data from the selected row as a dictionary."""
row = self.table.currentRow() # Get the selected row index
if row < 0: # No row selected
return None
data = {
"engine": self.table.item(row, 0).text(),
"version": self.table.item(row, 1).text(),
"type": self.table.item(row, 2).text(),
"path": self.table.item(row, 3).text(),
}
return data
if __name__ == "__main__":
app = QApplication([])