New UI Redesign in pyqt6 (#56)

* Initial commit for new UI

* Initial commit for new UI

* WIP

* Status bar updates and has an icon for online / offline

* Add log_viewer.py

* Use JSON for delete_engine_download API

* Fix class issue with Downloaders

* Move Config class to new ui

* Add engine_browser.py

* Add a close event handler to the main window

* Fix issue with engine manager not deleting engines properly

* Rearrange all the files

* Add icons and resources

* Cache system info in RenderServerProxy

* Toolbar polish

* Fix resource path in status bar

* Add config_dir to misc_helper.py

* Add try block to zeroconf setup

* Add add_job.py

* Add raw args to add_job.py
This commit is contained in:
2023-11-04 09:52:15 -05:00
committed by GitHub
parent bc8e88ea59
commit 65c256b641
45 changed files with 1491 additions and 53 deletions

View File

1
src/ui/widgets/dialog.py Normal file
View File

@@ -0,0 +1 @@
''' app/ui/widgets/dialog.py '''

23
src/ui/widgets/menubar.py Normal file
View File

@@ -0,0 +1,23 @@
''' app/ui/widgets/menubar.py '''
from PyQt6.QtWidgets import QMenuBar
class MenuBar(QMenuBar):
"""
Initialize the menu bar.
Args:
parent: The parent widget.
"""
def __init__(self, parent=None) -> None:
super().__init__(parent)
file_menu = self.addMenu("File")
# edit_menu = self.addMenu("Edit")
# view_menu = self.addMenu("View")
# help_menu = self.addMenu("Help")
# Add actions to the menus
# file_menu.addAction(self.parent().topbar.actions_call["Open"]) # type: ignore
# file_menu.addAction(self.parent().topbar.actions_call["Save"]) # type: ignore
# file_menu.addAction(self.parent().topbar.actions_call["Exit"]) # type: ignore

View File

@@ -0,0 +1,40 @@
from PyQt6.QtCore import QRectF
from PyQt6.QtGui import QPainter
from PyQt6.QtWidgets import QLabel
class ProportionalImageLabel(QLabel):
def __init__(self):
super().__init__()
def setPixmap(self, pixmap):
self._pixmap = pixmap
super().setPixmap(self._pixmap)
def paintEvent(self, event):
if self._pixmap.isNull():
super().paintEvent(event)
return
painter = QPainter(self)
targetRect = event.rect()
# Calculate the aspect ratio of the pixmap
aspectRatio = self._pixmap.width() / self._pixmap.height()
# Calculate the size of the pixmap within the target rectangle while maintaining the aspect ratio
if aspectRatio > targetRect.width() / targetRect.height():
scaledWidth = targetRect.width()
scaledHeight = targetRect.width() / aspectRatio
else:
scaledHeight = targetRect.height()
scaledWidth = targetRect.height() * aspectRatio
# Calculate the position to center the pixmap within the target rectangle
x = targetRect.x() + (targetRect.width() - scaledWidth) / 2
y = targetRect.y() + (targetRect.height() - scaledHeight) / 2
sourceRect = QRectF(0.0, 0.0, self._pixmap.width(), self._pixmap.height())
targetRect = QRectF(x, y, scaledWidth, scaledHeight)
painter.drawPixmap(targetRect, self._pixmap, sourceRect)

View File

@@ -0,0 +1,61 @@
''' app/ui/widgets/statusbar.py '''
import os.path
import socket
import threading
import time
from PyQt6.QtCore import Qt, QTimer
from PyQt6.QtGui import QPixmap
from PyQt6.QtWidgets import QStatusBar, QLabel
from src.api.server_proxy import RenderServerProxy
from src.utilities.misc_helper import resources_dir
class StatusBar(QStatusBar):
"""
Initialize the status bar.
Args:
parent: The parent widget.
"""
def __init__(self, parent) -> None:
super().__init__(parent)
def background_update():
proxy = RenderServerProxy(socket.gethostname())
proxy.start_background_update()
image_names = {'Ready': 'GreenCircle.png', 'Offline': "RedSquare.png"}
last_update = None
# Check for status change every 1s on background thread
while True:
new_status = proxy.status()
if new_status is not last_update:
new_image_name = image_names.get(new_status, 'Synchronize.png')
image_path = os.path.join(resources_dir(), 'icons', new_image_name)
self.label.setPixmap((QPixmap(image_path).scaled(16, 16, Qt.AspectRatioMode.KeepAspectRatio)))
self.messageLabel.setText(new_status)
last_update = new_status
time.sleep(1)
background_thread = threading.Thread(target=background_update,)
background_thread.daemon = True
background_thread.start()
# Create a label that holds an image
self.label = QLabel()
image_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'resources', 'icons',
'RedSquare.png')
pixmap = (QPixmap(image_path).scaled(16, 16, Qt.AspectRatioMode.KeepAspectRatio))
self.label.setPixmap(pixmap)
self.addWidget(self.label)
# Create a label for the message
self.messageLabel = QLabel()
self.addWidget(self.messageLabel)
# Call this method to display a message
self.messageLabel.setText("Loading...")

49
src/ui/widgets/toolbar.py Normal file
View File

@@ -0,0 +1,49 @@
''' app/ui/widgets/toolbar.py '''
from PyQt6.QtCore import Qt, QSize
from PyQt6.QtGui import QAction, QIcon
from PyQt6.QtWidgets import QToolBar, QWidget, QSizePolicy
class ToolBar(QToolBar):
"""
Initialize the toolbar.
Args:
parent: The parent widget.
orientation: The toolbar's orientation.
style: The toolbar's tool button style.
icon_size: The toolbar's icon size.
"""
def __init__(self, parent,
orientation: Qt.Orientation = Qt.Orientation.Horizontal,
style: Qt.ToolButtonStyle = Qt.ToolButtonStyle.ToolButtonTextUnderIcon,
icon_size: tuple[int, int] = (32, 32)) -> None:
super().__init__(parent)
self.actions_call = {}
self.setOrientation(orientation)
self.setToolButtonStyle(style)
self.setIconSize(QSize(icon_size[0], icon_size[1]))
def add_button(self, text: str, icon: str, trigger_action) -> None:
"""
Add a button to the toolbar.
Args:
text: The button's text.
icon: The button's icon.
trigger_action: The action to be executed when the button is clicked.
"""
self.actions_call[text] = QAction(QIcon(icon), text, self)
self.actions_call[text].triggered.connect(trigger_action)
self.addAction(self.actions_call[text])
def add_separator(self) -> None:
"""
Add a separator to the toolbar.
"""
separator = QWidget(self)
separator.setSizePolicy(
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.addWidget(separator)

View File

@@ -0,0 +1,29 @@
''' app/ui/widgets/treeview.py '''
from PyQt6.QtWidgets import QTreeView
from PyQt6.QtGui import QFileSystemModel
from PyQt6.QtCore import QDir
class TreeView(QTreeView):
"""
Initialize the TreeView widget.
Args:
parent (QWidget, optional): Parent widget of the TreeView. Defaults to None.
"""
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.file_system_model: QFileSystemModel = QFileSystemModel()
self.file_system_model.setRootPath(QDir.currentPath())
self.setModel(self.file_system_model)
self.setRootIndex(self.file_system_model.index(QDir.currentPath()))
self.setColumnWidth(0, 100)
self.setFixedWidth(150)
self.setSortingEnabled(True)
def clear_view(self) -> None:
"""
Clearing the TreeView
"""
self.destroy(destroySubWindows=True)