From: Agnibho Mondal Date: Sun, 12 Nov 2023 12:38:09 +0000 (+0530) Subject: Web App Plugin X-Git-Tag: v0.5~10 X-Git-Url: https://code.agnibho.com/repo?a=commitdiff_plain;h=e930fd718a29c4b95ce0abdbd261a4a1b18c3749;p=medscript.git Web App Plugin --- diff --git a/README b/README index b8868f1..19eb119 100644 --- a/README +++ b/README @@ -424,6 +424,15 @@ An example plugin, that modifies the name of the patient, may be as follows: global text text=data.strip() +Plugins may also contain a web app written in HTML/JavaScript. To use it the +plugin must contain a function called `web` which takes the prescription object +and returns the URL of the web app. The run function of such a plugin must +take two arguments, the prescription and the data returned from the web app. + +The web app itself must include the qtwebchannel.js from PyQt6. The webchannel +exposes an object named `js` to the web app. The web app may return data by +calling the `run` function of the exposed `js` object. + Template Development -------------------- diff --git a/plugin.py b/plugin.py index eb4fb18..44a100c 100644 --- a/plugin.py +++ b/plugin.py @@ -6,18 +6,24 @@ # You should have received a copy of the GNU General Public License along with MedScript. If not, see . import logging, os, importlib, copy -from PyQt6.QtWidgets import QMessageBox, QInputDialog, QFileDialog -from PyQt6.QtCore import QThread, pyqtSignal +from PyQt6.QtWidgets import QMessageBox, QMainWindow, QInputDialog, QFileDialog, QVBoxLayout +from PyQt6.QtCore import QObject, QThread, QUrl, pyqtSignal, pyqtSlot +from PyQt6.QtWebChannel import QWebChannel +from PyQt6.QtGui import QIcon +from PyQt6.QtWebEngineWidgets import QWebEngineView from glob import glob from config import config -class Plugin(): +class Plugin(QObject): + + update=pyqtSignal() plugins=[] names=[] workers=[] def __init__(self): + super().__init__() if(config["enable_plugin"]): self.load() @@ -96,7 +102,13 @@ class Plugin(): def run(self, module, prescription): try: - if(hasattr(module, "run") and callable(module.run)): + if(hasattr(module, "web") and callable(module.web)): + self.webapp=WebApp() + self.webapp.done.connect(lambda: self.update.emit()) + url=module.web(prescription) + self.webapp.load(module, QUrl(url), prescription) + self.webapp.show() + elif(hasattr(module, "run") and callable(module.run)): if(hasattr(module, "confirm") and module.confirm): if(QMessageBox.StandardButton.Yes!=QMessageBox.question(None,"Confirm", module.confirm)): return @@ -135,6 +147,49 @@ class Plugin(): if index is not None: self.workers[index]=None +class WebApp(QMainWindow): + + done=pyqtSignal() + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.setWindowTitle("WebApp Plugin") + self.setGeometry(100, 100, 400, 400) + self.setWindowIcon(QIcon(os.path.join("resource", "icon_medscript.ico"))) + + self.webview=QWebEngineView() + self.setCentralWidget(self.webview) + + def load(self, module, url, prescription): + self.module=module + self.webview.load(url) + self.channel=QWebChannel() + self.js=JS(module, prescription) + self.channel.registerObject("js", self.js) + self.webview.page().setWebChannel(self.channel) + self.js.done.connect(lambda: self.done.emit()) + +class JS(QObject): + + done=pyqtSignal() + + def __init__(self, module, prescription): + super().__init__() + self.module=module + self.prescription=prescription + + @pyqtSlot(str) + def run(self, data): + try: + message=self.module.run(self.prescription, data) + if(message): + QMessageBox.information(None, "Information", message) + self.done.emit() + except Exception as e: + logging.error(self.module) + logging.exception(e) + class Worker(QThread): pluginComplete=pyqtSignal(str, int) diff --git a/window.py b/window.py index 445b06a..a5b71cb 100644 --- a/window.py +++ b/window.py @@ -942,6 +942,7 @@ class MainWindow(QMainWindow): self.installer=Installer() self.index.signal_open.connect(self.cmd_open) self.index.signal_copy.connect(self.cmd_copy) + self.plugin.update.connect(lambda: self.load_interface_from_instance()) self.signal_update.connect(self.show_update) self.new_doc()