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 | |
---|