]> Softwares of Agnibho - medscript.git/blob - plugin.py
8381f57b80a3d86768733ba875e6692cd1281e8c
[medscript.git] / plugin.py
1 # MedScript
2 # Copyright (C) 2023 Dr. Agnibho Mondal
3 # This file is part of MedScript.
4 # 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.
5 # 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.
6 # You should have received a copy of the GNU General Public License along with MedScript. If not, see <https://www.gnu.org/licenses/>.
7
8 import logging, os, importlib, copy, json
9 from PyQt6.QtWidgets import QMessageBox, QMainWindow, QInputDialog, QFileDialog, QVBoxLayout
10 from PyQt6.QtCore import QObject, QThread, QUrl, pyqtSignal, pyqtSlot
11 from PyQt6.QtWebChannel import QWebChannel
12 from PyQt6.QtGui import QIcon
13 from PyQt6.QtWebEngineWidgets import QWebEngineView
14 from glob import glob
15 from config import config
16
17 class Plugin(QObject):
18
19 update=pyqtSignal()
20
21 plugins=[]
22 names=[]
23 workers=[]
24
25 def __init__(self):
26 super().__init__()
27 if(config["enable_plugin"]):
28 self.load()
29
30 def load(self):
31 plugin_list=glob(os.path.join(config["plugin_directory"], "*"))
32 for i in plugin_list:
33 try:
34 if(os.path.isdir(i)):
35 spec=importlib.util.spec_from_file_location(os.path.basename(i), os.path.join(i, "main.py"))
36 mod=importlib.util.module_from_spec(spec)
37 spec.loader.exec_module(mod)
38 self.plugins.append(mod)
39 except Exception as e:
40 logging.warning(i+":"+str(e))
41
42 def get_name(self, mod):
43 try:
44 return(mod.name)
45 except Exception as e:
46 return(mod.__name__)
47
48 def commands(self):
49 cmds=[]
50 for i in self.plugins:
51 if(hasattr(i, "run") and callable(i.run)):
52 cmds.append([i, self.get_name(i)])
53 return(cmds)
54
55 def new(self, prescription):
56 for i in self.plugins:
57 try:
58 if(hasattr(i, "new") and callable(i.new)):
59 if(hasattr(i, "input") and callable(i.input)):
60 i.input(self.input())
61 message=i.new(prescription)
62 if(message):
63 self.showMessage(message)
64 except Exception as e:
65 logging.exception(e)
66
67 def open(self, prescription):
68 for i in self.plugins:
69 try:
70 if(hasattr(i, "open") and callable(i.open)):
71 if(hasattr(i, "input") and callable(i.input)):
72 i.input(self.input())
73 message=i.open(prescription)
74 if(message):
75 self.showMessage(message)
76 except Exception as e:
77 logging.exception(e)
78
79 def save(self, prescription):
80 for i in self.plugins:
81 try:
82 if(hasattr(i, "save") and callable(i.save)):
83 if(hasattr(i, "input") and callable(i.input)):
84 i.input(self.input())
85 message=i.save(prescription)
86 if(message):
87 self.showMessage(message)
88 except Exception as e:
89 logging.exception(e)
90
91 def refresh(self, prescription):
92 for i in self.plugins:
93 try:
94 if(hasattr(i, "refresh") and callable(i.refresh)):
95 if(hasattr(i, "input") and callable(i.input)):
96 i.input(self.input())
97 message=i.refresh(prescription)
98 if(message):
99 self.showMessage(message)
100 except Exception as e:
101 logging.exception(e)
102
103 def run(self, module, prescription):
104 try:
105 if(hasattr(module, "web") and callable(module.web)):
106 self.webapp=WebApp()
107 self.webapp.done.connect(lambda: self.update.emit())
108 url, data=module.web(prescription)
109 self.webapp.load(module, QUrl(url), prescription, data)
110 self.webapp.show()
111 elif(hasattr(module, "run") and callable(module.run)):
112 if(hasattr(module, "confirm") and module.confirm):
113 if(QMessageBox.StandardButton.Yes!=QMessageBox.question(None,"Confirm", module.confirm)):
114 return
115 if(hasattr(module, "input") and callable(module.input)):
116 module.input(self.input())
117 if(hasattr(module, "fileopen") and callable(module.fileopen)):
118 module.fileopen(QFileDialog.getOpenFileName()[0])
119 if(hasattr(module, "filesave") and callable(module.filesave)):
120 module.filesave(QFileDialog.getSaveFileName()[0])
121 if(hasattr(module, "background") and module.background):
122 self.showMessage("Module "+module.__name__+" will run in background.")
123 self.workers.append(Worker(module.run, prescription))
124 index=len(self.workers)-1
125 self.workers[index].setIndex(index)
126 self.workers[index].pluginComplete.connect(self.showMessage)
127 self.workers[index].start()
128 else:
129 message=module.run(prescription)
130 if(message):
131 self.showMessage(message)
132 except Exception as e:
133 logging.exception(e)
134
135 def input(self):
136 try:
137 text, ok=QInputDialog.getText(None, "User input", "Enter text:")
138 if text and ok:
139 return text
140 else:
141 return ""
142 except Exception as e:
143 logging.exception(e)
144
145 def showMessage(self, message, index=None):
146 QMessageBox.information(None, "Information", message)
147 if index is not None:
148 self.workers[index]=None
149
150 class WebApp(QMainWindow):
151
152 done=pyqtSignal()
153
154 def __init__(self, *args, **kwargs):
155 super().__init__(*args, **kwargs)
156
157 self.setWindowTitle("WebApp Plugin")
158 self.setGeometry(100, 100, 400, 400)
159 self.setWindowIcon(QIcon(os.path.join("resource", "icon_medscript.ico")))
160
161 self.webview=QWebEngineView()
162 self.setCentralWidget(self.webview)
163
164 def load(self, module, url, prescription, data):
165 self.module=module
166 self.webview.load(url)
167 self.channel=QWebChannel()
168 self.js=JS(module, prescription, data)
169 self.channel.registerObject("js", self.js)
170 self.webview.page().setWebChannel(self.channel)
171 self.js.done.connect(lambda: self.done.emit())
172
173 class JS(QObject):
174
175 done=pyqtSignal()
176
177 def __init__(self, module, prescription, data):
178 super().__init__()
179 self.module=module
180 self.prescription=prescription
181 self.data=data
182
183 @pyqtSlot(str, str)
184 def run(self, prescription, result):
185 self.prescription.set_data_from_json(json.loads(prescription))
186 try:
187 message=self.module.run(self.prescription, result)
188 if(message):
189 QMessageBox.information(None, "Information", message)
190 self.done.emit()
191 except Exception as e:
192 logging.error(self.module)
193 logging.exception(e)
194
195 @pyqtSlot(result=str)
196 def getPrescription(self):
197 return self.prescription.get_json()
198
199 @pyqtSlot(result=str)
200 def getData(self):
201 return self.data
202
203 class Worker(QThread):
204
205 pluginComplete=pyqtSignal(str, int)
206 function=None
207 prescription=None
208 index=None
209
210 def __init__(self, function, prescription):
211 super().__init__()
212 self.function=function
213 self.prescription=prescription
214
215 def setIndex(self, index):
216 self.index=index
217
218 def run(self):
219 try:
220 prescription_copy=copy.deepcopy(self.prescription)
221 message=self.function(prescription_copy)
222 self.pluginComplete.emit(message, self.index)
223 except Exception as e:
224 logging.exception(e)