[3b3b40b] | 1 | # global |
---|
| 2 | import os |
---|
| 3 | from shutil import copyfile |
---|
| 4 | |
---|
| 5 | from PyQt5 import QtWidgets |
---|
| 6 | |
---|
| 7 | from sas.sascalc.fit import models |
---|
| 8 | from sas.qtgui.Perspectives.Fitting import ModelUtilities |
---|
| 9 | from sas.qtgui.Utilities.TabbedModelEditor import TabbedModelEditor |
---|
| 10 | import sas.qtgui.Utilities.GuiUtils as GuiUtils |
---|
| 11 | |
---|
| 12 | from sas.qtgui.Utilities.UI.PluginManagerUI import Ui_PluginManagerUI |
---|
| 13 | |
---|
| 14 | |
---|
| 15 | class PluginManager(QtWidgets.QDialog, Ui_PluginManagerUI): |
---|
| 16 | """ |
---|
| 17 | Class describing the model plugin manager. |
---|
| 18 | This is a simple list widget allowing for viewing/adding/deleting custom models. |
---|
| 19 | """ |
---|
| 20 | def __init__(self, parent=None): |
---|
| 21 | super(PluginManager, self).__init__() |
---|
| 22 | self.setupUi(self) |
---|
| 23 | |
---|
| 24 | self.parent = parent |
---|
| 25 | self.cmdDelete.setEnabled(False) |
---|
| 26 | self.cmdEdit.setEnabled(False) |
---|
| 27 | self.cmdDuplicate.setEnabled(False) |
---|
| 28 | |
---|
| 29 | # globals |
---|
| 30 | self.readModels() |
---|
| 31 | |
---|
| 32 | # internal representation of the parameter list |
---|
| 33 | # {<row>: (<parameter>, <value>)} |
---|
| 34 | self.plugin_dict = {} |
---|
| 35 | |
---|
| 36 | # Initialize signals |
---|
| 37 | self.addSignals() |
---|
| 38 | |
---|
| 39 | def readModels(self): |
---|
| 40 | """ |
---|
| 41 | Read in custom models from the default location |
---|
| 42 | """ |
---|
| 43 | self.lstModels.clear() |
---|
| 44 | plugins = ModelUtilities._find_models() |
---|
| 45 | models = list(plugins.keys()) |
---|
| 46 | self.lstModels.addItems(models) |
---|
| 47 | |
---|
| 48 | def addSignals(self): |
---|
| 49 | """ |
---|
| 50 | Define slots for widget signals |
---|
| 51 | """ |
---|
| 52 | self.cmdOK.clicked.connect(self.accept) |
---|
| 53 | self.cmdDelete.clicked.connect(self.onDelete) |
---|
| 54 | self.cmdAdd.clicked.connect(self.onAdd) |
---|
| 55 | self.cmdDuplicate.clicked.connect(self.onDuplicate) |
---|
| 56 | self.cmdEdit.clicked.connect(self.onEdit) |
---|
| 57 | self.cmdHelp.clicked.connect(self.onHelp) |
---|
| 58 | self.lstModels.selectionModel().selectionChanged.connect(self.onSelectionChanged) |
---|
| 59 | self.parent.communicate.customModelDirectoryChanged.connect(self.readModels) |
---|
| 60 | |
---|
| 61 | def onSelectionChanged(self): |
---|
| 62 | """ |
---|
| 63 | Respond to row selection |
---|
| 64 | """ |
---|
| 65 | rows = len(self.lstModels.selectionModel().selectedRows()) |
---|
| 66 | self.cmdDelete.setEnabled(rows>0) |
---|
| 67 | self.cmdEdit.setEnabled(rows==1) |
---|
| 68 | self.cmdDuplicate.setEnabled(rows>0) |
---|
| 69 | |
---|
| 70 | def onDelete(self): |
---|
| 71 | """ |
---|
| 72 | Remove the file containing the selected plugin |
---|
| 73 | """ |
---|
| 74 | plugins_to_delete = [s.data() for s in self.lstModels.selectionModel().selectedRows()] |
---|
| 75 | |
---|
| 76 | delete_msg = "Are you sure you want to remove the selected plugins?" |
---|
| 77 | reply = QtWidgets.QMessageBox.question( |
---|
| 78 | self, |
---|
| 79 | 'Warning', |
---|
| 80 | delete_msg, |
---|
| 81 | QtWidgets.QMessageBox.Yes, |
---|
| 82 | QtWidgets.QMessageBox.No) |
---|
| 83 | |
---|
| 84 | # Exit if no |
---|
| 85 | if reply == QtWidgets.QMessageBox.No: |
---|
| 86 | return |
---|
| 87 | |
---|
| 88 | for plugin in plugins_to_delete: |
---|
| 89 | name = os.path.join(ModelUtilities.find_plugins_dir(), plugin + ".py") |
---|
| 90 | os.remove(name) |
---|
| 91 | |
---|
| 92 | self.parent.communicate.customModelDirectoryChanged.emit() |
---|
| 93 | |
---|
| 94 | def onAdd(self): |
---|
| 95 | """ |
---|
| 96 | Show the add new model dialog |
---|
| 97 | """ |
---|
| 98 | self.add_widget = TabbedModelEditor(parent=self.parent) |
---|
| 99 | self.add_widget.show() |
---|
| 100 | |
---|
| 101 | def onDuplicate(self): |
---|
| 102 | """ |
---|
| 103 | Creates a copy of the selected model(s) |
---|
| 104 | """ |
---|
| 105 | |
---|
| 106 | plugins_to_copy = [s.data() for s in self.lstModels.selectionModel().selectedRows()] |
---|
| 107 | plugin_dir = ModelUtilities.find_plugins_dir() |
---|
| 108 | for plugin in plugins_to_copy: |
---|
| 109 | src_filename = plugin + ".py" |
---|
| 110 | src_file = os.path.join(plugin_dir, src_filename) |
---|
| 111 | dst_filename = GuiUtils.findNextFilename(src_filename, plugin_dir) |
---|
| 112 | if not dst_filename: |
---|
| 113 | logging.error("Could not find appropriate filename for "+src_file) |
---|
| 114 | dst_file = os.path.join(plugin_dir, dst_filename) |
---|
| 115 | copyfile(src_file, dst_file) |
---|
| 116 | self.parent.communicate.customModelDirectoryChanged.emit() |
---|
| 117 | |
---|
| 118 | def onEdit(self): |
---|
| 119 | """ |
---|
| 120 | Show the edit existing model dialog |
---|
| 121 | """ |
---|
| 122 | plugin_location = models.find_plugins_dir() |
---|
| 123 | # GUI assured only one row selected. Pick up the only element in list. |
---|
| 124 | try: |
---|
| 125 | model_to_edit = self.lstModels.selectionModel().selectedRows()[0].data() |
---|
| 126 | except Exception: |
---|
| 127 | # Something wrong with model, return |
---|
| 128 | return |
---|
| 129 | name = os.path.join(plugin_location, model_to_edit + ".py") |
---|
| 130 | self.edit_widget = TabbedModelEditor(parent=self.parent, edit_only=True) |
---|
| 131 | self.edit_widget.loadFile(name) |
---|
| 132 | self.edit_widget.show() |
---|
| 133 | |
---|
| 134 | def onHelp(self): |
---|
| 135 | """ |
---|
| 136 | Show the help page in the default browser |
---|
| 137 | """ |
---|
| 138 | location = "/user/sasgui/perspectives/fitting/fitting_help.html#new-plugin-model" |
---|
| 139 | self.parent.showHelp(location) |
---|
| 140 | |
---|