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
-------
"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": ""
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"))
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"))
"preset_delimiter": ",",
"markdown": false,
"check_update": false,
+ "enable_plugin": false,
"smime": false,
"root_bundle": "",
"certificate": "",
--- /dev/null
+# 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)
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"])
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()
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)
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
from preset import Preset
from tabular import Tabular
from index import Index
+from plugin import Plugin
class MainWindow(QMainWindow):
current_file=FileHandler()
prescription=Prescription()
renderer=Renderer()
+ plugin=Plugin()
save_state=md5("".encode()).hexdigest()
unchanged_state=False
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())
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?")):
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):
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):
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)