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