commit 7a0b29c83a6910494a9f162cfabc06faa56d5235 Author: oscarg Date: Sun Jun 1 22:29:01 2025 +1200 Initial Commit diff --git a/main.py b/main.py new file mode 100644 index 0000000..cb6a969 --- /dev/null +++ b/main.py @@ -0,0 +1,31 @@ +# Standard Library +import sys + +# Local Library +from util.gui.logic.app_window_types import MDIApp +from util.gui.logic.characteristics import Characteristics, Window, Toolbar, ToolbarAction, SubWindow +from util.gui.windows import Windows + +# External Library +from PySide6.QtWidgets import QApplication, QTextEdit, QMdiSubWindow + +def main(): + app = QApplication(sys.argv) + + characteristics = Characteristics([ + Window("Main Window"), + Toolbar("Main Toolbar", [ + ToolbarAction("File", lambda app: print("File?")), + ToolbarAction("Connections", lambda app: print("Connections menu")), + ToolbarAction("Create Note", Windows.create_note) + ]) + ]) + + application = MDIApp(characteristics) + + application.show() + sys.exit(app.exec()) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/util/gui/__pycache__/app_window.cpython-313.pyc b/util/gui/__pycache__/app_window.cpython-313.pyc new file mode 100644 index 0000000..58a737e Binary files /dev/null and b/util/gui/__pycache__/app_window.cpython-313.pyc differ diff --git a/util/gui/__pycache__/characteristics.cpython-313.pyc b/util/gui/__pycache__/characteristics.cpython-313.pyc new file mode 100644 index 0000000..cef31de Binary files /dev/null and b/util/gui/__pycache__/characteristics.cpython-313.pyc differ diff --git a/util/gui/__pycache__/window.cpython-313.pyc b/util/gui/__pycache__/window.cpython-313.pyc new file mode 100644 index 0000000..7298082 Binary files /dev/null and b/util/gui/__pycache__/window.cpython-313.pyc differ diff --git a/util/gui/__pycache__/windows.cpython-313.pyc b/util/gui/__pycache__/windows.cpython-313.pyc new file mode 100644 index 0000000..ccc5644 Binary files /dev/null and b/util/gui/__pycache__/windows.cpython-313.pyc differ diff --git a/util/gui/logic/__pycache__/app_window_types.cpython-313.pyc b/util/gui/logic/__pycache__/app_window_types.cpython-313.pyc new file mode 100644 index 0000000..1bc6dc3 Binary files /dev/null and b/util/gui/logic/__pycache__/app_window_types.cpython-313.pyc differ diff --git a/util/gui/logic/__pycache__/characteristics.cpython-313.pyc b/util/gui/logic/__pycache__/characteristics.cpython-313.pyc new file mode 100644 index 0000000..67cfb5e Binary files /dev/null and b/util/gui/logic/__pycache__/characteristics.cpython-313.pyc differ diff --git a/util/gui/logic/app_window_types.py b/util/gui/logic/app_window_types.py new file mode 100644 index 0000000..adce539 --- /dev/null +++ b/util/gui/logic/app_window_types.py @@ -0,0 +1,41 @@ +# Local Library +from util.gui.logic.characteristics import Characteristics + +# External Library +from PySide6.QtWidgets import (QApplication, QMainWindow, QMdiArea, QMdiSubWindow, QTextEdit, QPushButton, QVBoxLayout, QWidget, QToolBar) +from PySide6.QtGui import QKeySequence, QShortcut + +class MDIApp(QMainWindow): + def __init__(self, characteristics: Characteristics): + super().__init__() + + self.mdi_area = QMdiArea(self) + self.setCentralWidget(self.mdi_area) + + for component in characteristics.components: + component.build(self) + + self.fullscreen_shortcut = QShortcut(QKeySequence("F11"), self) + self.fullscreen_shortcut.activated.connect(self.toggle_fullscreen) + + def toggle_fullscreen(self): + if self.isFullScreen(): + self.showNormal() + else: + self.showFullScreen() + +class App(QMainWindow): + def __init__(self, characteristics: Characteristics): + super().__init__() + + for component in characteristics.components: + component.build(self) + + self.fullscreen_shortcut = QShortcut(QKeySequence("F11"), self) + self.fullscreen_shortcut.activated.connect(self.toggle_fullscreen) + + def toggle_fullscreen(self): + if self.isFullScreen(): + self.showNormal() + else: + self.showFullScreen() \ No newline at end of file diff --git a/util/gui/logic/characteristics.py b/util/gui/logic/characteristics.py new file mode 100644 index 0000000..c9903d2 --- /dev/null +++ b/util/gui/logic/characteristics.py @@ -0,0 +1,57 @@ +# Standard Library +from dataclasses import dataclass +from typing import List, Callable, Protocol + +# External Library +from PySide6.QtWidgets import (QToolBar, QMainWindow, QWidget, QMdiArea, QMdiSubWindow) +from PySide6.QtGui import (QAction) + +class UIComponent(Protocol): + def build(self, app: QMainWindow): + pass + +@dataclass +class ToolbarAction: + name: str + callback: Callable[[QMainWindow], None] + +@dataclass +class Toolbar(UIComponent): + name: str + actions: List[ToolbarAction] + + def build(self, app: QMainWindow): + toolbar = QToolBar(self.name) + for action in self.actions: + qt_action = QAction(action.name, app) + qt_action.triggered.connect(lambda checked=False, cb=action.callback: cb(app)) + toolbar.addAction(qt_action) + app.addToolBar(toolbar) + +@dataclass +class SubWindow(UIComponent): + name: str + content_factory: Callable[[], QWidget] + + def build(self, app: QMainWindow): + if not hasattr(app, 'mdi_area'): + raise AttributeError("MDI area not found in app") + + mdi_area: QMdiArea = getattr(app, 'mdi_area') + sub_window = QMdiSubWindow() + sub_window.setWidget(self.content_factory()) + sub_window.setWindowTitle(self.name) + mdi_area.addSubWindow(sub_window) + sub_window.show() + +@dataclass +class Window(UIComponent): + title: str + + def build(self, app: QMainWindow): + app.setWindowTitle(self.title) + +@dataclass +class Characteristics: + components: List[UIComponent] + diff --git a/util/gui/windows.py b/util/gui/windows.py new file mode 100644 index 0000000..8020437 --- /dev/null +++ b/util/gui/windows.py @@ -0,0 +1,14 @@ +# External Library +from PySide6.QtWidgets import QApplication, QTextEdit, QMdiSubWindow + +class Windows: + note_counter = 0 + + @staticmethod + def create_note(app_instance): + Windows.note_counter += 1 + sub = QMdiSubWindow() + sub.setWidget(QTextEdit(f"Notes {Windows.note_counter}")) + sub.setWindowTitle(f"Notes {Windows.note_counter}") + app_instance.mdi_area.addSubWindow(sub) + sub.show() \ No newline at end of file