]> Softwares of Agnibho - medscript.git/blobdiff - window.py
Bugfix: Windows uninstall package permission error
[medscript.git] / window.py
index 96030e803a3984c494c565461e160b867e042cda..5c75e2a0cc1b30f32600d7e92f6cff62dc953ac2 100644 (file)
--- a/window.py
+++ b/window.py
@@ -5,7 +5,7 @@
 # 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, sys, datetime, dateutil.parser, shutil, json, threading
+import logging, os, sys, datetime, dateutil.parser, shutil, json, copy, threading
 from PyQt6.QtCore import Qt, QDateTime, QDate, QSize, pyqtSignal
 from PyQt6.QtWidgets import QWidget, QMainWindow, QMessageBox, QLabel, QPushButton, QLineEdit, QTextEdit, QDateTimeEdit, QDateEdit, QCalendarWidget, QListWidget, QComboBox, QCheckBox, QRadioButton, QButtonGroup, QVBoxLayout, QHBoxLayout, QFormLayout, QToolBar, QTabWidget, QStatusBar, QFileDialog, QInputDialog, QCompleter, QSizePolicy
 from PyQt6.QtGui import QAction, QIcon
@@ -19,15 +19,15 @@ from config import config, info, real_dir
 from prescription import Prescription, Prescriber
 from renderer import Renderer
 from filehandler import FileHandler
-from renderbox import RenderBox
+from renderbox import RenderBox, UnrenderBox
 from setting import EditConfiguration, EditPrescriber, SelectPrescriber
 from editpreset import EditPreset
 from viewbox import ViewBox
 from preset import Preset
-from tabular import Tabular
 from index import Index
 from customform import CustomForm
 from plugin import Plugin
+from installer import Installer
 
 class MainWindow(QMainWindow):
 
@@ -58,22 +58,23 @@ class MainWindow(QMainWindow):
                 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.update_instance()
                 self.save_state=md5(self.prescription.get_json().encode()).hexdigest()
                 self.load_attachment(self.current_file.list())
                 self.unchanged_state=True
+            except FileNotFoundError as e:
+                logging.warning(e)
             except Exception as e:
                 QMessageBox.warning(self,"Open failed", "Failed to open file.")
-                print(e)
+                logging.exception(e)
 
     def cmd_copy(self, data):
         self.cmd_new()
-        self.prescription.name=data["name"]
-        self.prescription.age=data["age"]
-        self.prescription.sex=data["sex"]
-        self.prescription.address=data["address"]
-        self.prescription.contact=data["contact"]
+        self.prescription.set_data_from_json(data)
+        self.prescription.id=""
+        self.prescription.date=None
         self.load_interface_from_instance()
+        self.refresh()
 
     def cmd_save(self, save_as=False):
         self.update_instance()
@@ -90,11 +91,16 @@ class MainWindow(QMainWindow):
             try:
                 if not os.path.exists(self.current_file.file):
                     filename=QFileDialog.getSaveFileName(self, "Save File", suggest, "Prescriptions (*.mpaz);; All Files (*)")[0]
+                    if(len(filename)<=0):
+                        return
                     if(not filename.endswith(".mpaz")):
                        filename=filename+".mpaz"
                     self.current_file.set_file(filename)
                 for i in range(self.input_attachment.count()):
                     self.current_file.copy(self.input_attachment.item(i).text())
+                if(self.prescription.prescriber.get_json()!=self.prescriber.get_json()):
+                    if(QMessageBox.StandardButton.Yes==QMessageBox.question(self,"Change Prescriber", "Original Prescriber: "+self.prescription.prescriber.name+"\nCurrent Prescriber: "+self.prescriber.name+"\nReplace original with current?")):
+                        self.prescription.prescriber=copy.deepcopy(self.prescriber)
                 self.prescription.write_to(os.path.join(self.current_file.directory.name, "prescription.json"))
                 if change_template:
                     config["template"]=os.path.join(config["template_directory"], template)
@@ -104,41 +110,49 @@ class MainWindow(QMainWindow):
                 self.save_state=md5(self.prescription.get_json().encode()).hexdigest()
             except Exception as e:
                 QMessageBox.warning(self,"Save failed", "Failed to save file.")
-                print(e)
+                logging.exception(e)
 
     def cmd_save_as(self):
         suggest=self.prescription.id if(self.prescription.id) else self.prescription.name
         suggest=os.path.abspath(os.path.join(config["document_directory"], suggest)+".mpaz")
-        self.current_file.set_file(QFileDialog.getSaveFileName(self, "Save File", suggest, "Prescriptions (*.mpaz);; All Files (*)")[0])
-        Path(self.current_file.file).touch()
-        self.cmd_save(save_as=True)
+        filename=QFileDialog.getSaveFileName(self, "Save File", suggest, "Prescriptions (*.mpaz);; All Files (*)")[0]
+        if(len(filename)>0):
+            if not filename.endswith(".mpaz"):
+                filename=filename+".mpaz"
+            self.current_file.set_file(filename)
+            Path(self.current_file.file).touch()
+            self.cmd_save(save_as=True)
 
     def cmd_refresh(self):
-        self.update_instance()
-        self.plugin.refresh(self.prescription)
-        self.load_interface_from_instance()
         self.refresh()
 
     def cmd_quit(self):
         if(self.confirm_close()):
             sys.exit()
 
+    def cmd_unrender(self):
+        self.update_instance()
+        self.unrenderbox.show(self.prescription).exec()
+
     def cmd_render(self):
-        self.refresh()
+        self.update_instance()
         if(self.save_state==md5(self.prescription.get_json().encode()).hexdigest()):
             try:
                 target=self.renderer.render(self.current_file.directory.name)
-                self.signal_view.emit(target)
-                self.renderbox.showMaximized()
+                if target is not None:
+                    self.signal_view.emit(target)
+                    self.renderbox.showMaximized()
+                else:
+                    QMessageBox.critical(self, "Render failed", "Presciption rendering failed. Please check if prescription file or template is corrupted.")
+                    logging.error("Prescription rendering failed.")
             except FileNotFoundError as e:
-                print(e)
+                logging.warning(e)
                 QMessageBox.information(self, "Save first", "Please save the file before rendering.")
-
         else:
            QMessageBox.information(self, "Save first", "Please save the file before rendering.")
 
     def cmd_sign(self):
-        self.refresh()
+        self.update_instance()
         if(self.save_state==md5(self.prescription.get_json().encode()).hexdigest()):
             ok=True #password, ok=QInputDialog.getText(self, "Enter password", "Private key password", QLineEdit.EchoMode.Password)
             if(ok):
@@ -148,25 +162,25 @@ class MainWindow(QMainWindow):
                         #self.current_file.sign(password)
                         self.cmd_save()
                     except FileNotFoundError as e:
-                        print(e)
+                        logging.warning(e)
                         QMessageBox.information(self, "Save first", "Please save the file before signing.")
                     except TypeError as e:
-                        print(e)
+                        logging.warning(e)
                         QMessageBox.information(self, "Configure", "Please add valid key and certificate to the config file.")
                     except EVPError as e:
-                        print(e)
+                        logging.warning(e)
                         QMessageBox.information(self, "Check password", "Failed to load key. Please check if password is correct.")
                     except BIOError as e:
-                        print(e)
+                        logging.warning(e)
                         QMessageBox.information(self, "Not found", "Certifcate and/or key not found.")
                     except SMIME_Error as e:
-                        print(e)
+                        logging.warning(e)
                         QMessageBox.information(self, "Failed to load", "Failed to sign. Please check if certificate and key match.")
                     except Exception as e:
-                        print(e)
+                        logging.exception(e)
                         QMessageBox.information(self, "Failed", "Failed to sign.")
                 except Exception as e:
-                    print(e)
+                    logging.exception(e)
         else:
            QMessageBox.information(self, "Save first", "Please save the file before signing.")
 
@@ -183,44 +197,33 @@ class MainWindow(QMainWindow):
             elif result is None:
                 QMessageBox.warning(self, "No Siganture", "No signature was found.")
             else:
-                print(result)
+                logging.info(result)
                 QMessageBox.information(self, "Valid signature", "Valid signature found with the following information:\n"+result)
         except FileNotFoundError as e:
-            print(e)
+            logging.warning(e)
             QMessageBox.warning(self, "No Siganture", "No signature was found.")
         except Exception as e:
-            print(e)
+            logging.exception(e)
             QMessageBox.warning(self, "Failed", "Failed to verify.")
 
-    def cmd_tabular(self):
-        try:
-            filename=QFileDialog.getSaveFileName(self, "Export CSV File", os.path.join(config["data_directory"], "data.csv"), "CSV (*.csv);; All Files (*)")[0]
-            Tabular.export(filename)
-            QMessageBox.information(self, "Data Exported", "Data exported to."+filename)
-        except Exception as e:
-            print(e)
-            QMessageBox.critical(self, "Export failed", "Failed to export the data.")
-
     def cmd_index(self):
-        self.index.refresh()
         self.index.show()
 
     def cmd_configuration(self):
-        self.edit_configuration.exec()
-
-    def cmd_prescriber(self, file=None):
-        self.edit_prescriber.load(file)
-        self.edit_prescriber.exec()
+        self.editConfiguration.exec()
 
-    def cmd_switch(self):
+    def cmd_prescriber(self):
         try:
-            self.select_prescriber.load()
-            self.select_prescriber.exec()
+            self.selectPrescriber.load()
+            self.selectPrescriber.exec()
         except FileNotFoundError as e:
-            print(e)
+            logging.warning(e)
 
     def cmd_preset(self):
-        self.edit_preset.show()
+        self.editPreset.show()
+
+    def cmd_installer(self):
+        self.installer.show()
 
     def cmd_about(self):
         year=datetime.datetime.now().year
@@ -241,17 +244,17 @@ class MainWindow(QMainWindow):
 
     def cmd_update(self, silent=False):
         try:
-            print("Current version "+info["version"])
+            logging.info("Current version "+info["version"])
             with request.urlopen(info["url"]+"/info.json") as response:
                 latest=json.loads(response.read().decode())
-            print("Latest version "+latest["version"])
+            logging.info("Latest version "+latest["version"])
             if(version.parse(info["version"]) < version.parse(latest["version"])):
                 self.signal_update.emit("New version <strong>"+latest["version"]+"</strong> available.<br>Visit <a href='"+latest["url"]+"'>"+latest["url"]+"</a> to get the latest version.")
             elif(not silent):
                 self.signal_update.emit("No update available. You are using version "+info["version"]+".")
         except Exception as e:
             self.signal_update.emit("Failed to check available update.")
-            print(e)
+            logging.warning(e)
 
     def show_update(self, message):
         QMessageBox.information(self, "Check update", message)
@@ -326,7 +329,7 @@ class MainWindow(QMainWindow):
             if config["preset_newline"]:
                 self.input_certificate.insertPlainText("\n")
 
-    def load_interface(self, file="", date=None, id="", name="", dob="", age="", sex="", address="", contact="", extra="", mode="", daw="", diagnosis="", note="", report="", advice="", investigation="", medication="", additional="", certificate="", custom=None):
+    def load_interface(self, file="", date=None, id="", pid="", name="", dob="", age="", sex="", address="", contact="", extra="", mode="", daw="", diagnosis="", note="", report="", advice="", investigation="", medication="", additional="", certificate="", custom=None):
         try:
             file_msg=self.current_file.file if self.current_file.file else "New file"
             sign_msg="(signed)" if config["smime"] and self.current_file.is_signed() else ""
@@ -339,9 +342,10 @@ class MainWindow(QMainWindow):
                     d=QDateTime.fromString(pdate.strftime("%Y-%m-%d %H:%M:%S"), "yyyy-MM-dd hh:mm:ss")
                 except Exception as e:
                     QMessageBox.warning(self,"Failed to load", str(e))
-                    print(e)
+                    logging.exception(e)
             self.input_date.setDateTime(d)
             self.input_id.setText(id)
+            self.input_pid.setText(pid)
             self.input_name.setText(name)
             try:
                 pdate=dateutil.parser.parse(dob)
@@ -368,11 +372,12 @@ class MainWindow(QMainWindow):
             self.input_medication.setText(medication)
             self.input_additional.setText(additional)
             self.input_certificate.setText(certificate)
-            self.input_custom.setData(custom)
+            if(config["enable_form"] and custom is not None):
+                self.input_custom.setData(custom)
             self.label_prescriber.setText(self.prescriber.name)
         except Exception as e:
             QMessageBox.warning(self,"Failed to load", "Failed to load the data into the application.")
-            print(e)
+            logging.exception(e)
 
     def load_interface_from_instance(self):
         if(self.current_file.has_template()):
@@ -385,6 +390,7 @@ class MainWindow(QMainWindow):
                 file=self.prescription.file,
                 date=self.prescription.date,
                 id=self.prescription.id,
+                pid=self.prescription.pid,
                 name=self.prescription.name,
                 dob=self.prescription.dob,
                 age=self.prescription.age,
@@ -410,6 +416,7 @@ class MainWindow(QMainWindow):
             self.prescription.set_data(
                     date=self.input_date.dateTime().toString("yyyy-MM-dd hh:mm:ss"),
                     id=self.input_id.text(),
+                    pid=self.input_pid.text(),
                     name=self.input_name.text(),
                     dob=self.input_dob.text(),
                     age=self.input_age.text(),
@@ -431,7 +438,7 @@ class MainWindow(QMainWindow):
                     )
         except Exception as e:
             QMessageBox.critical(self,"Failed", "Critical failure happned. Please check console for more info.")
-            print(e)
+            logging.error(e)
 
     def new_doc(self):
         self.current_file.reset()
@@ -441,6 +448,9 @@ class MainWindow(QMainWindow):
         self.update_instance()
         self.plugin.new(self.prescription)
         self.load_interface_from_instance()
+        if(config["age_default"]):
+            self.btnAge.click()
+            self.update_instance()
         self.save_state=md5(self.prescription.get_json().encode()).hexdigest()
 
     def change_prescriber(self, file):
@@ -448,8 +458,13 @@ class MainWindow(QMainWindow):
         self.prescriber.read_from(file)
         self.refresh()
 
+    def edit_prescriber(self, file=None):
+        self.editPrescriber.load(file)
+        self.editPrescriber.exec()
+
     def refresh(self):
         self.update_instance()
+        self.plugin.refresh(self.prescription)
         self.load_interface_from_instance()
 
     def add_attachment(self):
@@ -459,7 +474,7 @@ class MainWindow(QMainWindow):
                 self.input_attachment.addItem(new)
         except Exception as e:
             QMessageBox.warning(self,"Attach failed", "Failed to attach file.")
-            print(e)
+            logging.exception(e)
 
     def remove_attachment(self):
         index=self.input_attachment.currentRow()
@@ -473,7 +488,7 @@ class MainWindow(QMainWindow):
         try:
             shutil.copyfile(self.input_attachment.currentItem().text(), QFileDialog.getSaveFileName(self, "Save Attachment", os.path.join(config["document_directory"], os.path.basename(self.input_attachment.currentItem().text())))[0])
         except Exception as e:
-            print(e)
+            logging.exception(e)
 
     def load_attachment(self, attachments):
         for attach in attachments:
@@ -491,9 +506,27 @@ class MainWindow(QMainWindow):
             self.input_age.setText("")
             self.input_age.setEnabled(False)
 
+    def load_presets(self):
+        self.preset_note=Preset("note")
+        self.preset_report=Preset("report")
+        self.preset_advice=Preset("advice")
+        self.preset_investigation=Preset("investigation")
+        self.preset_medication=Preset("medication", text_as_key=True)
+        self.preset_additional=Preset("additional")
+        self.preset_certificate=Preset("certificate")
+
+    def reload_presets(self):
+        self.load_presets()
+        self.input_note_preset.addItems(self.preset_note.data.keys())
+        self.input_report_preset.addItems(self.preset_note.data.keys())
+        self.input_advice_preset.addItems(self.preset_note.data.keys())
+        self.input_investigation_preset.addItems(self.preset_note.data.keys())
+        self.input_medication_preset.addItems(self.preset_note.data.keys())
+        self.input_additional_preset.addItems(self.preset_note.data.keys())
+        self.input_certificate_preset.addItems(self.preset_note.data.keys())
 
     def confirm_close(self):
-        self.refresh()
+        self.update_instance()
         flag=(self.save_state==md5(self.prescription.get_json().encode()).hexdigest() or QMessageBox.StandardButton.Yes==QMessageBox.question(self,"Confirm action", "Unsaved changes may be lost. Continue?"))
         return flag
 
@@ -510,28 +543,24 @@ class MainWindow(QMainWindow):
         self.setGeometry(100, 100, 600, 400)
         self.setWindowIcon(QIcon(os.path.join(config["resource"], "icon_medscript.ico")))
 
+        icon_index=QIcon(os.path.join(config["resource"], "icon_index.svg"))
         icon_open=QIcon(os.path.join(config["resource"], "icon_open.svg"))
         icon_save=QIcon(os.path.join(config["resource"], "icon_save.svg"))
         icon_render=QIcon(os.path.join(config["resource"], "icon_render.svg"))
         icon_refresh=QIcon(os.path.join(config["resource"], "icon_refresh.svg"))
+        icon_view=QIcon(os.path.join(config["resource"], "icon_view.svg"))
 
-        self.preset_note=Preset("note")
-        self.preset_report=Preset("report")
-        self.preset_advice=Preset("advice")
-        self.preset_investigation=Preset("investigation")
-        self.preset_medication=Preset("medication", text_as_key=True)
-        self.preset_additional=Preset("additional")
-        self.preset_certificate=Preset("certificate")
+        self.load_presets()
 
-        action_new=QAction("New", self)
+        action_new=QAction("New File", self)
         action_new.setShortcut("Ctrl+N")
         action_new.triggered.connect(self.cmd_new)
-        action_open=QAction("Open", self)
+        action_open=QAction("Open File", self)
         action_open2=QAction(icon_open, "Open", self)
         action_open.setShortcut("Ctrl+O")
         action_open.triggered.connect(self.cmd_open)
         action_open2.triggered.connect(self.cmd_open)
-        action_save=QAction("Save", self)
+        action_save=QAction("Save File", self)
         action_save2=QAction(icon_save, "Save", self)
         action_save.setShortcut("Ctrl+S")
         action_save.triggered.connect(self.cmd_save)
@@ -539,53 +568,61 @@ class MainWindow(QMainWindow):
         action_save_as=QAction("Save As", self)
         action_save_as.setShortcut("Ctrl+Shift+S")
         action_save_as.triggered.connect(self.cmd_save_as)
-        action_refresh=QAction("Refresh", self)
+        action_refresh=QAction("Refresh Interface", self)
         action_refresh.setShortcut("F5")
         action_refresh2=QAction(icon_refresh, "Refresh", self)
         action_refresh.triggered.connect(self.cmd_refresh)
         action_refresh2.triggered.connect(self.cmd_refresh)
-        action_quit=QAction("Quit", self)
+        action_quit=QAction("Quit MedScript", self)
         action_quit.setShortcut("Ctrl+Q")
         action_quit.triggered.connect(self.cmd_quit)
-        action_render=QAction("Render", self)
+        action_render=QAction("Render Prescription", self)
         action_render.setShortcut("Ctrl+R")
         action_render2=QAction(icon_render, "Render", self)
         action_render.triggered.connect(self.cmd_render)
         action_render2.triggered.connect(self.cmd_render)
-        action_sign=QAction("Sign", self)
+        action_unrender=QAction("Quick Display", self)
+        action_unrender.setShortcut("Ctrl+D")
+        action_unrender2=QAction(icon_view, "Display", self)
+        action_unrender.triggered.connect(self.cmd_unrender)
+        action_unrender2.triggered.connect(self.cmd_unrender)
+        action_sign=QAction("Sign Prescription", self)
         action_sign.triggered.connect(self.cmd_sign)
-        action_unsign=QAction("Unsign", self)
+        action_unsign=QAction("Delete Signature", self)
         action_unsign.triggered.connect(self.cmd_unsign)
-        action_verify=QAction("Verify", self)
+        action_verify=QAction("Verify Signature", self)
         action_verify.triggered.connect(self.cmd_verify)
-        action_configuration=QAction("Configuration", self)
+        action_configuration=QAction("Edit Configuration", self)
         action_configuration.triggered.connect(self.cmd_configuration)
-        action_prescriber=QAction("Prescriber", self)
-        action_prescriber.triggered.connect(self.cmd_prescriber)
-        action_switch=QAction("Switch", self)
-        action_switch.triggered.connect(self.cmd_switch)
-        action_preset=QAction("Preset", self)
+        action_preset=QAction("Edit Presets", self)
         action_preset.triggered.connect(self.cmd_preset)
-        action_tabular=QAction("Tabular", self)
-        action_tabular.triggered.connect(self.cmd_tabular)
-        action_index=QAction("Index", self)
+        action_prescriber=QAction("Select Prescriber", self)
+        action_prescriber.triggered.connect(self.cmd_prescriber)
+        action_installer=QAction("Package Installer", self)
+        action_installer.triggered.connect(self.cmd_installer)
+        action_index=QAction("Show Index", self)
         action_index.triggered.connect(self.cmd_index)
-        action_update=QAction("Update", self)
+        action_index.setShortcut("Ctrl+I")
+        action_index2=QAction(icon_index, "Index", self)
+        action_index2.triggered.connect(self.cmd_index)
+        action_update=QAction("Check Update", self)
         action_update.triggered.connect(self.cmd_update)
-        action_about=QAction("About", self)
+        action_about=QAction("About MedScript", self)
         action_about.triggered.connect(self.cmd_about)
-        action_help=QAction("Help", self)
+        action_help=QAction("Show Help", self)
         action_help.setShortcut("F1")
         action_help.triggered.connect(self.cmd_help)
 
         menubar=self.menuBar()
         menu_file=menubar.addMenu("File")
+        menu_file.addAction(action_index)
         menu_file.addAction(action_new)
         menu_file.addAction(action_open)
         menu_file.addAction(action_save)
         menu_file.addAction(action_save_as)
         menu_file.addAction(action_quit)
-        menu_prepare=menubar.addMenu("Prepare")
+        menu_prepare=menubar.addMenu("Process")
+        menu_prepare.addAction(action_unrender)
         menu_prepare.addAction(action_render)
         menu_prepare.addAction(action_refresh)
         if(config["smime"]):
@@ -594,12 +631,9 @@ class MainWindow(QMainWindow):
             menu_prepare.addAction(action_verify)
         menu_settings=menubar.addMenu("Settings")
         menu_settings.addAction(action_configuration)
-        menu_settings.addAction(action_prescriber)
-        menu_settings.addAction(action_switch)
         menu_settings.addAction(action_preset)
-        menu_data=menubar.addMenu("Data")
-        menu_data.addAction(action_index)
-        menu_data.addAction(action_tabular)
+        menu_settings.addAction(action_prescriber)
+        menu_settings.addAction(action_installer)
 
         if(config["enable_plugin"]):
             action_plugin=[]
@@ -610,7 +644,7 @@ class MainWindow(QMainWindow):
                     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)
+                logging.exception(e)
             menu_plugin=menubar.addMenu("Plugin")
             for i in action_plugin:
                 menu_plugin.addAction(i)
@@ -622,9 +656,11 @@ class MainWindow(QMainWindow):
 
         toolbar=QToolBar("Main Toolbar", floatable=False, movable=False)
         toolbar.setIconSize(QSize(16, 16))
+        toolbar.addAction(action_index2)
         toolbar.addAction(action_open2)
         toolbar.addAction(action_save2)
         toolbar.addAction(action_refresh2)
+        toolbar.addAction(action_unrender2)
         toolbar.addAction(action_render2)
         toolbar.addSeparator()
         label_template=QLabel("Template:")
@@ -636,7 +672,7 @@ class MainWindow(QMainWindow):
             templates.remove(os.path.basename(config["template"]))
             templates.insert(0, os.path.basename(config["template"]))
         except Exception as e:
-            print(e)
+            logging.exception(e)
         self.input_template.addItems(templates)
         toolbar.addWidget(self.input_template)
         spacer=QWidget(self)
@@ -655,7 +691,9 @@ class MainWindow(QMainWindow):
         self.input_date.setCalendarWidget(QCalendarWidget())
         layout_info.addRow("Date", self.input_date)
         self.input_id=QLineEdit(self)
-        layout_info.addRow("ID", self.input_id)
+        layout_info.addRow("Prescription ID", self.input_id)
+        self.input_pid=QLineEdit(self)
+        layout_info.addRow("Patient ID", self.input_pid)
         self.input_name=QLineEdit(self)
         layout_info.addRow("Name", self.input_name)
 
@@ -880,6 +918,8 @@ class MainWindow(QMainWindow):
         tab.addTab(tab_certificate, "Certificate")
         if(config["enable_form"]):
             tab.addTab(tab_custom, "Custom")
+        else:
+            tab_custom.hide()
         tab.addTab(tab_attachment, "Attachment")
 
         self.setCentralWidget(tab)
@@ -888,18 +928,22 @@ class MainWindow(QMainWindow):
         self.setStatusBar(self.statusbar)
 
         self.renderbox=RenderBox()
+        self.unrenderbox=UnrenderBox()
         self.signal_view.connect(self.renderbox.update)
-        self.edit_configuration=EditConfiguration()
-        self.edit_prescriber=EditPrescriber()
-        self.edit_prescriber.signal_save.connect(self.change_prescriber)
-        self.select_prescriber=SelectPrescriber()
-        self.select_prescriber.signal_edit.connect(self.cmd_prescriber)
-        self.select_prescriber.signal_select.connect(self.change_prescriber)
+        self.editConfiguration=EditConfiguration()
+        self.editPrescriber=EditPrescriber()
+        self.editPrescriber.signal_save.connect(self.change_prescriber)
+        self.selectPrescriber=SelectPrescriber()
+        self.selectPrescriber.signal_edit.connect(self.edit_prescriber)
+        self.selectPrescriber.signal_select.connect(self.change_prescriber)
         self.viewbox=ViewBox()
         self.index=Index()
-        self.edit_preset=EditPreset()
+        self.editPreset=EditPreset()
+        self.editPreset.presetEdited.connect(self.reload_presets)
+        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()
@@ -907,10 +951,11 @@ class MainWindow(QMainWindow):
             self.cmd_open(config["filename"])
 
         if(len(self.prescription.prescriber.name.strip())<1):
-            self.cmd_prescriber()
+            self.edit_prescriber()
 
         if(config["check_update"]):
             threading.Thread(target=self.cmd_update, args=[True]).start()
 
+
         self.setWindowIcon(QIcon(os.path.join(config["resource"], "icon_medscript.ico")))
         self.showMaximized()