diff --git a/zxlive/app.py b/zxlive/app.py index f995db54..b586c052 100644 --- a/zxlive/app.py +++ b/zxlive/app.py @@ -16,11 +16,12 @@ from __future__ import annotations from PySide6.QtWidgets import QApplication +from PySide6.QtCore import QCommandLineParser import sys +from .mainwindow import MainWindow -sys.path.insert(0,'../pyzx') # So that it can find a local copy of pyzx +sys.path.insert(0, '../pyzx') # So that it can find a local copy of pyzx -from .mainwindow import MainWindow class ZXLive(QApplication): """The main ZX Live application @@ -32,10 +33,20 @@ def __init__(self) -> None: super().__init__(sys.argv) self.setApplicationName('ZX Live') self.setDesktopFileName('ZX Live') + self.setApplicationVersion('0.1') # TODO: read this from pyproject.toml if possible self.main_window = MainWindow() self.lastWindowClosed.connect(self.quit) + parser = QCommandLineParser() + parser.setApplicationDescription("ZX Live - An interactive tool for the ZX calculus") + parser.addHelpOption() + parser.addVersionOption() + parser.addPositionalArgument("files", "File(s) to open.", "[files...]") + parser.process(self) + for f in parser.positionalArguments(): + self.main_window.open_file_from_path(f) + def main() -> None: """Main entry point for ZX Live""" diff --git a/zxlive/dialogs.py b/zxlive/dialogs.py index 04057c2d..d0162867 100644 --- a/zxlive/dialogs.py +++ b/zxlive/dialogs.py @@ -85,6 +85,7 @@ def show_error_msg(title: str, description: Optional[str] = None) -> None: msg.setInformativeText(description) msg.exec() + def import_diagram_dialog(parent: QWidget) -> Optional[ImportGraphOutput | ImportProofOutput | ImportRuleOutput]: """Shows a dialog to import a diagram from disk. @@ -98,9 +99,17 @@ def import_diagram_dialog(parent: QWidget) -> Optional[ImportGraphOutput | Impor # This happens if the user clicks on cancel return None + return import_diagram_from_file(file_path, selected_filter) + + +def import_diagram_from_file(file_path: str, selected_filter: str = FileFormat.All.filter) -> \ + Optional[ImportGraphOutput | ImportProofOutput | ImportRuleOutput]: + """Imports a diagram from a given file path. + + Returns the imported graph or `None` if the import failed.""" file = QFile(file_path) if not file.open(QIODevice.OpenModeFlag.ReadOnly | QIODevice.OpenModeFlag.Text): - show_error_msg("Could not open file") + show_error_msg(f"Could not open file: {file_path}.") return None stream = QTextStream(file) data = stream.readAll() @@ -111,7 +120,7 @@ def import_diagram_dialog(parent: QWidget) -> Optional[ImportGraphOutput | Impor ext = file_path.split(".")[-1] selected_format = next(f for f in FileFormat if f.extension == ext) - # TODO: This would be nicer with match statements... + # TODO: This would be nicer with match statements (requires python 3.10 though)... try: if selected_format == FileFormat.ZXProof: return ImportProofOutput(selected_format, file_path, ProofModel.from_json(data)) @@ -135,11 +144,11 @@ def import_diagram_dialog(parent: QWidget) -> Optional[ImportGraphOutput | Impor try: return ImportGraphOutput(FileFormat.TikZ, file_path, GraphT.from_tikz(data)) # type: ignore except: - show_error_msg(f"Failed to import {selected_format.name} file", "Couldn't determine filetype.") + show_error_msg(f"Failed to import {selected_format.name} file", f"Couldn't determine filetype: {file_path}.") return None except Exception as e: - show_error_msg(f"Failed to import {selected_format.name} file", str(e)) + show_error_msg(f"Failed to import {selected_format.name} file: {file_path}", str(e)) return None def write_to_file(file_path: str, data: str) -> bool: diff --git a/zxlive/mainwindow.py b/zxlive/mainwindow.py index 85a40bc5..54888fba 100644 --- a/zxlive/mainwindow.py +++ b/zxlive/mainwindow.py @@ -36,7 +36,7 @@ ImportRuleOutput, create_new_rewrite, export_diagram_dialog, export_proof_dialog, export_rule_dialog, get_lemma_name_and_description, - import_diagram_dialog, show_error_msg) + import_diagram_dialog, import_diagram_from_file, show_error_msg) from zxlive.settings_dialog import open_settings_dialog from .edit_panel import GraphEditPanel @@ -270,6 +270,14 @@ def _redo_changed(self) -> None: def open_file(self) -> None: out = import_diagram_dialog(self) if out is not None: + self._open_file_from_output(out) + + def open_file_from_path(self, file_path: str) -> None: + out = import_diagram_from_file(file_path) + if out is not None: + self._open_file_from_output(out) + + def _open_file_from_output(self, out: ImportGraphOutput | ImportProofOutput | ImportRuleOutput) -> None: name = QFileInfo(out.file_path).baseName() if isinstance(out, ImportGraphOutput): self.new_graph(out.g, name)