]> Softwares of Agnibho - medscript.git/commitdiff
Implemented the plugin system
authorAgnibho Mondal <mondal@agnibho.com>
Thu, 26 Oct 2023 16:47:04 +0000 (22:17 +0530)
committerAgnibho Mondal <mondal@agnibho.com>
Thu, 26 Oct 2023 16:47:04 +0000 (22:17 +0530)
README
config.py
data/config.json
plugin.py [new file with mode: 0644]
setting.py
window.py

diff --git a/README b/README
index b879ea8d6ccf3833b96419108d8a844abd210fc0..bc8754b297f00983c162ec8bd7045fa5887eba83 100644 (file)
--- a/README
+++ b/README
@@ -214,10 +214,31 @@ here.
 
 5. Markdown: The markdown formatting can be enabled from here.
 
-6. S/MIME: This is an experimental feature and is disabled by default. To use
+6. Check update: Whether updates are available can be checked at program start
+up by enabling this option.
+
+7. Plugin: The plugin system can be enabled from here.
+
+8. S/MIME: This is an experimental feature and is disabled by default. To use
 it, it has to be enabled first from the settings. The Private key, X509
 certificate and Root bundle can be selected from the options that follow this.
 
+Plugin
+------
+
+MedScript has a plugin system which can be used to incorporate customized
+plugins written in python. To use the plugins, the plugins must be saved in
+the configured plugin directory and plugin must be enabled in the
+configuration.
+
+The details of the plugin system and the documentation for development is
+available in the project website.
+
+Website
+-------
+
+<https://code.agnibho.com/medscript/>
+
 License
 -------
 
index 4b43fd81ca836b843e98b7ac3722bddca7d96568..f97cf81b749cfb8d15dfc7a37eec0138e55b96ac 100644 (file)
--- a/config.py
+++ b/config.py
@@ -33,11 +33,13 @@ default = {
         "template_directory": "template",
         "template": "default_prescription",
         "preset_directory": "preset",
-        "preset_newline": "True",
+        "plugin_directory": "plugin",
+        "enable_plugin": False,
+        "preset_newline": True,
         "preset_delimiter": ",",
-        "markdown": "False",
-        "check_update": "False",
-        "smime": "False",
+        "markdown": False,
+        "check_update": False,
+        "smime": False,
         "root_bundle": "",
         "private_key": "",
         "certificate": ""
@@ -55,6 +57,7 @@ config["filename"]=args.filename
 config["data_directory"]=os.path.abspath(os.path.join(real_dir, os.path.expanduser(config["data_directory"])))
 config["document_directory"]=os.path.join(config["data_directory"], config["document_directory"])
 config["preset_directory"]=os.path.join(config["data_directory"], config["preset_directory"])
+config["plugin_directory"]=os.path.join(config["data_directory"], config["plugin_directory"])
 config["template_directory"]=os.path.join(config["data_directory"], config["template_directory"])
 config["template"]=os.path.join(config["template_directory"], config["template"])
 config["resource"]=os.path.abspath(os.path.join(real_dir, "resource"))
@@ -75,6 +78,7 @@ os.makedirs(config["data_directory"], exist_ok=True)
 os.makedirs(config["document_directory"], exist_ok=True)
 os.makedirs(config["prescriber_directory"], exist_ok=True)
 os.makedirs(config["preset_directory"], exist_ok=True)
+os.makedirs(config["plugin_directory"], exist_ok=True)
 os.makedirs(config["template_directory"], exist_ok=True)
 if not os.path.exists(os.path.join(config["data_directory"], "config.json")):
     shutil.copyfile(os.path.abspath(os.path.join(real_dir, "data", "config.json")), os.path.join(config["data_directory"], "config.json"))
index c931c384a96705b0b5994284f94fb1672da54d6c..d96bc87251274b478d6a120390bde03b1e7fc065 100644 (file)
@@ -10,6 +10,7 @@
     "preset_delimiter": ",",
     "markdown": false,
     "check_update": false,
+    "enable_plugin": false,
     "smime": false,
     "root_bundle": "",
     "certificate": "",
diff --git a/plugin.py b/plugin.py
new file mode 100644 (file)
index 0000000..3b86520
--- /dev/null
+++ b/plugin.py
@@ -0,0 +1,88 @@
+# MedScript
+# Copyright (C) 2023 Dr. Agnibho Mondal
+# This file is part of MedScript.
+# MedScript is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+# MedScript is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License along with MedScript. If not, see <https://www.gnu.org/licenses/>.
+
+import os, importlib
+from PyQt6.QtWidgets import QMessageBox
+from glob import glob
+from config import config
+
+class Plugin():
+
+    plugins=[]
+    names=[]
+
+    def __init__(self):
+        if(config["enable_plugin"]):
+        #if(not config["enable_plugin"]):
+            self.load()
+
+    def load(self):
+        plugin_list=glob(os.path.join(config["plugin_directory"], "*"))
+        for i in plugin_list:
+            try:
+                spec=importlib.util.spec_from_file_location(os.path.basename(i), os.path.join(i, "main.py"))
+                mod=importlib.util.module_from_spec(spec)
+                spec.loader.exec_module(mod)
+                self.plugins.append(mod)
+            except Exception as e:
+                print(i, ":", e)
+
+    def get_name(self, mod):
+            try:
+                return(mod.name)
+            except Exception as e:
+                return(mod.__name__)
+
+    def commands(self):
+        cmds=[]
+        for i in self.plugins:
+            cmds.append([i, self.get_name(i)])
+        return(cmds)
+
+    def new(self, prescription):
+        for i in self.plugins:
+            try:
+                msg=i.new(prescription)
+                if(msg):
+                    QMessageBox.information(None, "Information", msg)
+            except Exception as e:
+                print(e)
+
+    def open(self, prescription):
+        for i in self.plugins:
+            try:
+                msg=i.open(prescription)
+                if(msg):
+                    QMessageBox.information(None, "Information", msg)
+            except Exception as e:
+                print(e)
+
+    def save(self, prescription):
+        for i in self.plugins:
+            try:
+                msg=i.save(prescription)
+                if(msg):
+                    QMessageBox.information(None, "Information", msg)
+            except Exception as e:
+                print(e)
+
+    def refresh(self, prescription):
+        for i in self.plugins:
+            try:
+                msg=i.refresh(prescription)
+                if(msg):
+                    QMessageBox.information(None, "Information", msg)
+            except Exception as e:
+                print(e)
+
+    def run(self, module, prescription):
+        try:
+            msg=module.run(prescription)
+            if(msg):
+                QMessageBox.information(None, "Information", msg)
+        except Exception as e:
+            print(e)
index a4a68fa916f1dd4c7a40f8678f7633539952557d..c05cd571794c68c945e6690319655b7eedf5f584 100644 (file)
@@ -43,6 +43,7 @@ class EditConfiguration(QMainWindow):
             self.input_delimiter.setCurrentText(self.config["preset_delimiter"])
             self.input_markdown.setChecked(bool(self.config["markdown"]))
             self.input_update.setChecked(bool(self.config["check_update"]))
+            self.input_plugin.setChecked(bool(self.config["enable_plugin"]))
             self.input_smime.setChecked(bool(self.config["smime"]))
             self.input_key.setText(self.config["private_key"])
             self.input_certificate.setText(self.config["certificate"])
@@ -60,6 +61,7 @@ class EditConfiguration(QMainWindow):
                 self.config["preset_delimiter"]=self.input_delimiter.currentText()
                 self.config["markdown"]=self.input_markdown.isChecked()
                 self.config["check_update"]=self.input_update.isChecked()
+                self.config["enable_plugin"]=self.input_plugin.isChecked()
                 self.config["smime"]=self.input_smime.isChecked()
                 self.config["private_key"]=self.input_key.text()
                 self.config["certificate"]=self.input_certificate.text()
@@ -110,6 +112,8 @@ class EditConfiguration(QMainWindow):
         layout.addRow("Markdown", self.input_markdown)
         self.input_update=QCheckBox("Check update on startup", self)
         layout.addRow("Check Update", self.input_update)
+        self.input_plugin=QCheckBox("Enable plugin", self)
+        layout.addRow("Plugin", self.input_plugin)
         self.input_smime=QCheckBox("Enable digital signature (experimental)", self)
         layout.addRow("S/MIME", self.input_smime)
         self.input_key=QLineEdit(self)
index 0066531f39b9f65511e1e55bc3b7db33382fab3b..0b0924cbefa16b0618854970b0420b9d407521fe 100644 (file)
--- a/window.py
+++ b/window.py
@@ -13,6 +13,7 @@ from pathlib import Path
 from hashlib import md5
 from urllib import request
 from packaging import version
+from functools import partial
 
 from config import config, info, real_dir
 from prescription import Prescription
@@ -24,6 +25,7 @@ from viewbox import ViewBox
 from preset import Preset
 from tabular import Tabular
 from index import Index
+from plugin import Plugin
 
 class MainWindow(QMainWindow):
 
@@ -33,6 +35,7 @@ class MainWindow(QMainWindow):
     current_file=FileHandler()
     prescription=Prescription()
     renderer=Renderer()
+    plugin=Plugin()
     save_state=md5("".encode()).hexdigest()
     unchanged_state=False
 
@@ -50,6 +53,7 @@ class MainWindow(QMainWindow):
                     self.current_file.set_file(QFileDialog.getOpenFileName(self, "Open File", config["document_directory"], "Prescriptions (*.mpaz);; All Files (*)")[0])
                 self.current_file.open()
                 self.prescription.read_from(os.path.join(self.current_file.directory.name,"prescription.json"))
+                self.plugin.open(self.prescription)
                 self.load_interface_from_instance()
                 self.save_state=md5(self.prescription.get_json().encode()).hexdigest()
                 self.load_attachment(self.current_file.list())
@@ -69,6 +73,8 @@ class MainWindow(QMainWindow):
 
     def cmd_save(self, save_as=False):
         self.update_instance()
+        self.plugin.save(self.prescription)
+        self.load_interface_from_instance()
         suggest=self.prescription.id if(self.prescription.id) else self.prescription.name
         suggest=os.path.abspath(os.path.join(config["document_directory"], suggest)+".mpaz")
         if(save_as or not self.unchanged_state or QMessageBox.StandardButton.Yes==QMessageBox.question(self,"Confirm change", "Modify the original file?")):
@@ -96,6 +102,8 @@ class MainWindow(QMainWindow):
         self.cmd_save(save_as=True)
 
     def cmd_refresh(self):
+        self.plugin.refresh(self.prescription)
+        self.load_interface_from_instance()
         self.refresh()
 
     def cmd_quit(self):
@@ -394,6 +402,8 @@ class MainWindow(QMainWindow):
         self.input_attachment.clear()
         self.load_interface()
         self.update_instance()
+        self.plugin.new(self.prescription)
+        self.load_interface_from_instance()
         self.save_state=md5(self.prescription.get_json().encode()).hexdigest()
 
     def refresh(self):
@@ -532,6 +542,20 @@ class MainWindow(QMainWindow):
         menu_data=menubar.addMenu("Data")
         menu_data.addAction(action_index)
         menu_data.addAction(action_tabular)
+
+        if(config["enable_plugin"]):
+            action_plugin=[]
+            try:
+                for i in self.plugin.commands():
+                    action_plugin.append(QAction(i[1], self))
+                    action_plugin[-1].triggered.connect(partial(self.plugin.run, i[0], self.prescription))
+                    action_plugin[-1].triggered.connect(self.load_interface_from_instance)
+            except Exception as e:
+                print(e)
+            menu_plugin=menubar.addMenu("Plugin")
+            for i in action_plugin:
+                menu_plugin.addAction(i)
+
         menu_help=menubar.addMenu("Help")
         menu_help.addAction(action_update)
         menu_help.addAction(action_about)