diff --git a/src/ui/settings_window.py b/src/ui/settings_window.py new file mode 100644 index 0000000..8e2df0e --- /dev/null +++ b/src/ui/settings_window.py @@ -0,0 +1,222 @@ +import socket + +from PyQt6 import QtCore +from PyQt6.QtCore import Qt +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 + + +class SettingsWindow(QMainWindow): + def __init__(self): + super().__init__() + + self.setWindowTitle("Settings") + + # Create the main layout + main_layout = QVBoxLayout() + + # Create the sidebar (QListWidget) for navigation + self.sidebar = QListWidget() + self.sidebar.setFixedWidth(150) + + # Set the icon size + self.sidebar.setIconSize(QtCore.QSize(32, 32)) # Increase the icon size to 32x32 pixels + + # Adjust the font size for the sidebar items + font = self.sidebar.font() + font.setPointSize(12) # Increase the font size + self.sidebar.setFont(font) + + # 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("Engines", "../../resources/Blender.png") + self.sidebar.setCurrentRow(0) + + # Create the stacked widget to hold different settings pages + self.stacked_widget = QStackedWidget() + + # Create pages for each section + general_page = self.create_general_page() + network_page = self.create_network_page() + engines_page = self.create_engines_page() + + # Add pages to the stacked widget + self.stacked_widget.addWidget(general_page) + 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) + + # Create a horizontal layout to hold the sidebar and stacked widget + content_layout = QHBoxLayout() + content_layout.addWidget(self.sidebar) + content_layout.addWidget(self.stacked_widget) + + # Add the content layout to the main layout + main_layout.addLayout(content_layout) + + # Add the "OK" button at the bottom + ok_button = QPushButton("OK") + ok_button.clicked.connect(self.close) + ok_button.setFixedWidth(80) + ok_button.setDefault(True) + main_layout.addWidget(ok_button, alignment=Qt.AlignmentFlag.AlignRight) + + # Create a central widget and set the layout + central_widget = QWidget() + central_widget.setLayout(main_layout) + self.setCentralWidget(central_widget) + + self.setMinimumSize(700, 400) + + def add_sidebar_item(self, name, icon_path): + """Add an item with an icon to the sidebar.""" + item = QListWidgetItem(QIcon(icon_path), name) + self.sidebar.addItem(item) + + def create_general_page(self): + """Create the General settings page.""" + page = QWidget() + layout = QVBoxLayout() + + # 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_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) + + layout.addWidget(startup_group) + layout.addWidget(language_group) + + layout.addStretch() # Add a stretch to push content to the top + page.setLayout(layout) + return page + + def create_network_page(self): + """Create the Network settings page.""" + page = QWidget() + layout = QVBoxLayout() + + # Proxy Settings Group + proxy_group = QGroupBox("Proxy Settings") + proxy_layout = QVBoxLayout() + proxy_layout.addWidget(QCheckBox("Use Proxy")) + proxy_layout.addWidget(QLabel("Proxy Address")) + proxy_layout.addWidget(QLineEdit()) + proxy_layout.addWidget(QLabel("Proxy Port")) + proxy_layout.addWidget(QLineEdit()) + proxy_group.setLayout(proxy_layout) + + layout.addWidget(proxy_group) + + layout.addStretch() # Add a stretch to push content to the top + page.setLayout(layout) + return page + + def create_engines_page(self): + """Create the Engines settings page.""" + page = QWidget() + layout = QVBoxLayout() + + # Installed Engines Group + installed_group = QGroupBox("Installed Engines") + installed_layout = QVBoxLayout() + 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") + delete_engine_button = QPushButton("Delete") + + 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) + + layout.addWidget(installed_group) + layout.addWidget(display_group) + + layout.addStretch() # Add a stretch to push content to the top + page.setLayout(layout) + return page + + +class EngineTableWidget(QWidget): + def __init__(self): + super().__init__() + + self.table = QTableWidget(0, 4) + self.table.setHorizontalHeaderLabels(["Engine", "Version", "Type", "Path"]) + self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) + self.table.verticalHeader().setVisible(False) + # self.table_widget.itemSelectionChanged.connect(self.engine_picked) + self.table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) + + layout = QVBoxLayout(self) + layout.addWidget(self.table) + + def showEvent(self, event): + """Runs when the widget is about to be shown.""" + self.update_table() + super().showEvent(event) # Ensure normal event processing + + def update_table(self): + raw_server_data = RenderServerProxy(socket.gethostname()).get_renderer_info() + if not raw_server_data: + return + + table_data = [] # convert the data into a flat list + for _, engine_data in raw_server_data.items(): + table_data.extend(engine_data['versions']) + + self.table.clear() + self.table.setRowCount(len(table_data)) + self.table.setColumnCount(4) + + self.table.setHorizontalHeaderLabels(['Engine', 'Version', 'Type', 'Path']) + self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Fixed) + self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed) + self.table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeMode.Fixed) + self.table.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeMode.Stretch) + + for row, engine in enumerate(table_data): + self.table.setItem(row, 0, QTableWidgetItem(engine['engine'])) + self.table.setItem(row, 1, QTableWidgetItem(engine['version'])) + self.table.setItem(row, 2, QTableWidgetItem(engine['type'])) + self.table.setItem(row, 3, QTableWidgetItem(engine['path'])) + + self.table.selectRow(0) + + +if __name__ == "__main__": + app = QApplication([]) + window = SettingsWindow() + window.show() + app.exec() \ No newline at end of file diff --git a/src/ui/widgets/menubar.py b/src/ui/widgets/menubar.py index 5b061d6..a59b4d7 100644 --- a/src/ui/widgets/menubar.py +++ b/src/ui/widgets/menubar.py @@ -14,6 +14,8 @@ class MenuBar(QMenuBar): def __init__(self, parent=None) -> None: super().__init__(parent) + self.settings_window = None + # setup menus file_menu = self.addMenu("File") # edit_menu = self.addMenu("Edit") @@ -30,7 +32,7 @@ class MenuBar(QMenuBar): settings_action = QAction("Settings...", self) settings_action.triggered.connect(self.show_settings) settings_action.setShortcut(f'Ctrl+,') - # file_menu.addAction(settings_action) # todo: enable once we have a setting screen + file_menu.addAction(settings_action) # exit exit_action = QAction('&Exit', self) exit_action.setShortcut('Ctrl+Q') @@ -49,7 +51,9 @@ class MenuBar(QMenuBar): self.parent().new_job() def show_settings(self): - pass + from src.ui.settings_window import SettingsWindow + self.settings_window = SettingsWindow() + self.settings_window.show() @staticmethod def show_about():