From 5f73623550e3612028779ca9ba303eb6ba943a8b Mon Sep 17 00:00:00 2001 From: overcuriousity Date: Mon, 20 Oct 2025 11:55:36 +0200 Subject: [PATCH] migration to pyside6 and adding status bar --- .github/instructions/concept.instructions.md | 4 +- pyproject.toml | 7 +- run.py | 3 +- src/forensictrails/__main__.py | 26 ++++--- src/forensictrails/gui/main_window.py | 77 ++++++++++++++++++-- 5 files changed, 92 insertions(+), 25 deletions(-) diff --git a/.github/instructions/concept.instructions.md b/.github/instructions/concept.instructions.md index 8de2d2b..6eb55dc 100644 --- a/.github/instructions/concept.instructions.md +++ b/.github/instructions/concept.instructions.md @@ -32,7 +32,7 @@ applyTo: '**' ``` Frontend/GUI: - Python 3.13+ - - PyQt6 (desktop GUI framework) + - PySide6 (desktop GUI framework) - QtWebEngine (for rich text/markdown rendering) Database: @@ -55,7 +55,7 @@ applyTo: '**' - ``` ┌─────────────────────────────────────────────┐ - │ PyQt6 GUI Layer │ + │ PySide6 GUI Layer │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Note │ │ Evidence │ │ Report │ │ │ │ Editor │ │ Manager │ │ Generator│ │ diff --git a/pyproject.toml b/pyproject.toml index 17821f0..44e037e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "forensictrails" version = "0.1.0" description = "Forensic Investigation Documentation System" readme = "README.md" -requires-python = ">=3.12" +requires-python = ">=3.11" license = {text = "BSD 3-Clause"} authors = [ {name = "Overcuriousity", email = "overcuriousity@posteo.org"} @@ -15,12 +15,11 @@ authors = [ classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Legal Industry", - "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.11", ] dependencies = [ - "PyQt6>=6.6.0", - "PyQt6-WebEngine>=6.6.0", + "PySide6>=6.10.0", "reportlab>=4.0.0", "python-docx>=1.0.0", "Pillow>=10.0.0", diff --git a/run.py b/run.py index abe0cd3..7584511 100644 --- a/run.py +++ b/run.py @@ -1,4 +1,5 @@ from src.forensictrails.__main__ import main +import sys if __name__ == "__main__": - main() \ No newline at end of file + sys.exit(main()) \ No newline at end of file diff --git a/src/forensictrails/__main__.py b/src/forensictrails/__main__.py index 8b64cc6..60e647f 100644 --- a/src/forensictrails/__main__.py +++ b/src/forensictrails/__main__.py @@ -1,28 +1,34 @@ """Entry point for ForensicTrails application.""" import sys import logging -from PyQt6.QtWidgets import QApplication +from PySide6.QtWidgets import QApplication from .db.database import initialize_database from .utils.logging import setup_logging +from .gui.main_window import MainWindow -def main(): - """Main entry point for the application.""" + +def main(argv=None): setup_logging() logging.info("Starting ForensicTrails application") - + initialize_database() - + # Create Qt application - app = QApplication(sys.argv) + if argv is None: + argv = sys.argv + app = QApplication(argv) app.setApplicationName("ForensicTrails") app.setOrganizationName("ForensicTrails") app.setApplicationVersion("0.1.0") - - # TODO: Create and show main window - + + # Create and show main window + window = MainWindow() + window.show() + logging.info("Application started") - sys.exit(app.exec()) + return app.exec() + if __name__ == "__main__": sys.exit(main()) \ No newline at end of file diff --git a/src/forensictrails/gui/main_window.py b/src/forensictrails/gui/main_window.py index a0b5391..7d823df 100644 --- a/src/forensictrails/gui/main_window.py +++ b/src/forensictrails/gui/main_window.py @@ -1,12 +1,73 @@ -from PyQt6 import QtWidgets, uic -from PyQt6.QtWidgets import QMainWindow, QFileDialog, QMessageBox -from PyQt6.QtCore import Qt -import os -import logging -from ..core.case_manager import CaseManager -from ..utils.config import config +"""main window for ForensicTrails. +""" + +from PySide6.QtWidgets import ( + QMainWindow, + QWidget, + QBoxLayout, + QStatusBar, + QMessageBox, +) +from PySide6.QtGui import QAction +from PySide6.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): - pass + super().__init__() + self.setWindowTitle("ForensicTrails") + self.resize(900, 600) + + # Platform-native menu bar + menu_bar = self.menuBar() + try: + menu_bar.setNativeMenuBar(True) + except Exception: + pass + + # Case menu + case_menu = menu_bar.addMenu("&Case") + self.action_new_case = QAction("&New Case...", self) + self.action_select_case = QAction("&Select Case...", self) + self.action_exit = QAction("E&xit", self) + + case_menu.addAction(self.action_new_case) + case_menu.addAction(self.action_select_case) + case_menu.addSeparator() + case_menu.addAction(self.action_exit) + + # Help menu with an About entry + help_menu = menu_bar.addMenu("&Help") + self.action_about = QAction("&About", self) + help_menu.addAction(self.action_about) + + # Wire actions to lightweight stubs for now + self.action_new_case.triggered.connect(self.new_case) + self.action_select_case.triggered.connect(self.select_case) + self.action_exit.triggered.connect(self.close) + self.action_about.triggered.connect(self.show_about) + + # Central layout + central = QWidget() + self.setCentralWidget(central) + + # Use dynamic attribute access for the Direction enum to satisfy type + # checkers that may not expose the enum members in stubs. + direction = getattr(QBoxLayout, "TopToBottom", 2) + layout = QBoxLayout(direction) # type: ignore[arg-type] + layout.setContentsMargins(8, 8, 8, 8) + layout.setSpacing(6) + central.setLayout(layout) + + # Status bar + self.setStatusBar(QStatusBar(self)) + + # action stubs + def new_case(self): + self.statusBar().showMessage("New case (not implemented)", 3000) + + def select_case(self): + self.statusBar().showMessage("Select case (not implemented)", 3000) + + def show_about(self): + QMessageBox.about(self, "About ForensicTrails", "ForensicTrails — Forensic investigation documentation system\nVersion 0.1.0") \ No newline at end of file