1 | # global |
---|
2 | import os |
---|
3 | from shutil import copyfile |
---|
4 | |
---|
5 | from PyQt5 import QtWidgets, QtCore |
---|
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__(parent._parent) |
---|
22 | self.setupUi(self) |
---|
23 | |
---|
24 | # disable the context help icon |
---|
25 | self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) |
---|
26 | |
---|
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 | """ |
---|
141 | location = "/user/qtgui/Perspectives/Fitting/fitting_help.html#new-plugin-model" |
---|
142 | self.parent.showHelp(location) |
---|
143 | |
---|