Changeset 3b3b40b in sasview
- Timestamp:
- Mar 21, 2018 4:17:04 AM (7 years ago)
- Branches:
- ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- 8b480d27
- Parents:
- e4c475b7
- git-author:
- Piotr Rozyczko <rozyczko@…> (02/08/18 04:19:04)
- git-committer:
- Piotr Rozyczko <rozyczko@…> (03/21/18 04:17:04)
- Files:
-
- 17 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
setup.py
- Property mode changed from 100644 to 100755
r14ec91c5 r3b3b40b 351 351 "src", "sas", "qtgui", "Utilities") 352 352 packages.append("sas.qtgui.Utilities") 353 package_dir["sas.qtgui.UtilitiesUI"] = os.path.join( 354 "src", "sas", "qtgui", "Utilities","UI") 355 packages.append("sas.qtgui.Utilities.UI") 353 356 354 357 package_dir["sas.qtgui.Calculators"] = os.path.join( -
src/sas/qtgui/GUITests.py
rda9a0722 r3b3b40b 44 44 from Utilities.UnitTesting import GuiUtilsTest 45 45 from Utilities.UnitTesting import SasviewLoggerTest 46 from Utilities.UnitTesting import GridPanelTest 47 from Utilities.UnitTesting import ModelEditorTest 48 from Utilities.UnitTesting import PluginDefinitionTest 49 from Utilities.UnitTesting import TabbedModelEditorTest 46 50 47 51 # Unit Testing … … 99 103 unittest.makeSuite(GuiUtilsTest.DoubleValidatorTest, 'test'), 100 104 unittest.makeSuite(GuiUtilsTest.HashableStandardItemTest, 'test'), 105 unittest.makeSuite(GridPanelTest.BatchOutputPanelTest, 'test'), 106 unittest.makeSuite(ModelEditorTest.ModelEditorTest, 'test'), 107 unittest.makeSuite(PluginDefinitionTest.PluginDefinitionTest, 'test'), 108 unittest.makeSuite(TabbedModelEditorTest.TabbedModelEditorTest,'test'), 101 109 102 110 # Calculators -
src/sas/qtgui/MainWindow/DataExplorer.py
re90988c r3b3b40b 476 476 self.chkBatch.setEnabled(self.parent.perspective().allowBatch()) 477 477 478 def display Data(self, data_list):478 def displayFile(self, filename=None, is_data=True): 479 479 """ 480 480 Forces display of charts for the given filename 481 481 """ 482 plot_to_show = data_list[0] 483 484 # passed plot is used ONLY to figure out its title, 485 # so all the charts related by it can be pulled from 486 # the data explorer indices. 487 filename = plot_to_show.filename 488 model = self.model if plot_to_show.is_data else self.theory_model 489 482 model = self.model if is_data else self.theory_model 490 483 # Now query the model item for available plots 491 484 plots = GuiUtils.plotsFromFilename(filename, model) … … 506 499 if new_plots: 507 500 self.plotData(new_plots) 501 502 def displayData(self, data_list): 503 """ 504 Forces display of charts for the given data set 505 """ 506 plot_to_show = data_list[0] 507 # passed plot is used ONLY to figure out its title, 508 # so all the charts related by it can be pulled from 509 # the data explorer indices. 510 filename = plot_to_show.filename 511 self.displayFile(filename=filename, is_data=plot_to_show.is_data) 508 512 509 513 def addDataPlot2D(self, plot_set, item): -
src/sas/qtgui/MainWindow/GuiManager.py
r14ec91c5 r3b3b40b 19 19 20 20 import sas.qtgui.Utilities.ObjectLibrary as ObjectLibrary 21 from sas.qtgui.Utilities.TabbedModelEditor import TabbedModelEditor 22 from sas.qtgui.Utilities.PluginManager import PluginManager 21 23 from sas.qtgui.MainWindow.UI.AcknowledgementsUI import Ui_Acknowledgements 22 24 from sas.qtgui.MainWindow.AboutBox import AboutBox … … 358 360 self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 359 361 self.communicate.plotRequestedSignal.connect(self.showPlot) 362 self.communicate.plotFromFilenameSignal.connect(self.showPlotFromFilename) 360 363 self.communicate.updateModelFromDataOperationPanelSignal.connect(self.updateModelFromDataOperationPanel) 361 364 … … 406 409 self._workspace.actionFit_Results.triggered.connect(self.actionFit_Results) 407 410 self._workspace.actionChain_Fitting.triggered.connect(self.actionChain_Fitting) 411 self._workspace.actionAdd_Custom_Model.triggered.connect(self.actionAdd_Custom_Model) 408 412 self._workspace.actionEdit_Custom_Model.triggered.connect(self.actionEdit_Custom_Model) 413 self._workspace.actionManage_Custom_Models.triggered.connect(self.actionManage_Custom_Models) 409 414 # Window 410 415 self._workspace.actionCascade.triggered.connect(self.actionCascade) … … 662 667 pass 663 668 669 def actionAdd_Custom_Model(self): 670 """ 671 """ 672 self.model_editor = TabbedModelEditor(self) 673 self.model_editor.show() 674 664 675 def actionEdit_Custom_Model(self): 665 676 """ 666 677 """ 667 print("actionEdit_Custom_Model TRIGGERED") 668 pass 678 self.model_editor = TabbedModelEditor(self, edit_only=True) 679 self.model_editor.show() 680 681 def actionManage_Custom_Models(self): 682 """ 683 """ 684 self.model_manager = PluginManager(self) 685 self.model_manager.show() 669 686 670 687 #============ ANALYSIS ================= … … 779 796 self.filesWidget.model.appendRow(new_item) 780 797 self._data_manager.add_data(new_datalist_item) 798 799 def showPlotFromFilename(self, filename): 800 """ 801 Pass the show plot request to the data explorer 802 """ 803 if hasattr(self, "filesWidget"): 804 self.filesWidget.displayFile(filename=filename, is_data=True) 781 805 782 806 def showPlot(self, plot): -
src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
r1543f0c r3b3b40b 8 8 <y>0</y> 9 9 <width>915</width> 10 <height> 527</height>10 <height>762</height> 11 11 </rect> 12 12 </property> … … 25 25 <y>0</y> 26 26 <width>915</width> 27 <height>2 1</height>27 <height>26</height> 28 28 </rect> 29 29 </property> … … 108 108 <addaction name="actionChain_Fitting"/> 109 109 <addaction name="separator"/> 110 <addaction name="actionAdd_Custom_Model"/> 110 111 <addaction name="actionEdit_Custom_Model"/> 112 <addaction name="actionManage_Custom_Models"/> 111 113 </widget> 112 114 <widget class="QMenu" name="menuWindow"> … … 505 507 </property> 506 508 </action> 509 <action name="actionAdd_Custom_Model"> 510 <property name="text"> 511 <string>Add Custom Model</string> 512 </property> 513 </action> 514 <action name="actionManage_Custom_Models"> 515 <property name="text"> 516 <string>Manage Custom Models</string> 517 </property> 518 </action> 507 519 </widget> 508 520 <resources/> -
src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py
re4c475b7 r3b3b40b 111 111 112 112 # Disconnect all local slots 113 tab_object.disconnect()113 #tab_object.disconnect() 114 114 115 115 # Reconnect tab signals to local slots … … 178 178 "Not all tabs chosen for fitting have parameters selected for fitting." 179 179 QtWidgets.QMessageBox.warning(self, 180 181 182 180 'Warning', 181 no_params_msg, 182 QtWidgets.QMessageBox.Ok) 183 183 184 184 return … … 674 674 675 675 constraint.func = constraint_text 676 # param1 is the parameter we're constraining 676 677 constraint.param = param1 678 677 679 # Find the right tab 678 680 constrained_tab = self.getObjectByName(model1) -
src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
r14ec91c5 r3b3b40b 8 8 from bumps import fitters 9 9 10 import sas.qtgui.Utilities.LocalConfig as LocalConfig 10 11 import sas.qtgui.Utilities.ObjectLibrary as ObjectLibrary 11 12 … … 116 117 tab = FittingWidget(parent=self.parent, data=data, tab_id=self.maxIndex+1) 117 118 tab.is_batch_fitting = is_batch 119 118 120 # Add this tab to the object library so it can be retrieved by scripting/jupyter 119 121 tab_name = self.getTabName(is_batch=is_batch) … … 123 125 self.updateFitDict(data, tab_name) 124 126 self.maxIndex += 1 125 self.addTab(tab, tab_name) 127 icon = QtGui.QIcon() 128 if is_batch: 129 icon.addPixmap(QtGui.QPixmap("src/sas/qtgui/images/icons/layers.svg")) 130 self.addTab(tab, icon, tab_name) 131 # Show the new tab 132 self.setCurrentIndex(self.maxIndex-1) 133 # Notify listeners 126 134 self.tabsModifiedSignal.emit() 127 135 … … 140 148 ObjectLibrary.addObject(tab_name, tab) 141 149 self.tabs.append(tab) 142 self.addTab(tab, tab_name) 150 icon = QtGui.QIcon() 151 icon.addPixmap(QtGui.QPixmap("src/sas/qtgui/images/icons/link.svg")) 152 self.addTab(tab, icon, tab_name) 153 154 # This will be the last tab, so set the index accordingly 155 self.setCurrentIndex(self.count()-1) 143 156 144 157 def updateFitDict(self, item_key, tab_name): -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
re4c475b7 r3b3b40b 24 24 import sas.qtgui.Utilities.GuiUtils as GuiUtils 25 25 import sas.qtgui.Utilities.LocalConfig as LocalConfig 26 from sas.qtgui.Utilities.GridPanel import BatchOutputPanel 26 27 from sas.qtgui.Utilities.CategoryInstaller import CategoryInstaller 27 28 from sas.qtgui.Plotting.PlotterData import Data1D … … 36 37 from sas.qtgui.Perspectives.Fitting.FittingLogic import FittingLogic 37 38 from sas.qtgui.Perspectives.Fitting import FittingUtilities 39 from sas.qtgui.Perspectives.Fitting import ModelUtilities 38 40 from sas.qtgui.Perspectives.Fitting.SmearingWidget import SmearingWidget 39 41 from sas.qtgui.Perspectives.Fitting.OptionsWidget import OptionsWidget … … 50 52 CATEGORY_DEFAULT = "Choose category..." 51 53 CATEGORY_STRUCTURE = "Structure Factor" 54 CATEGORY_CUSTOM = "Plugin Models" 52 55 STRUCTURE_DEFAULT = "None" 53 56 … … 83 86 constraintAddedSignal = QtCore.pyqtSignal(list) 84 87 newModelSignal = QtCore.pyqtSignal() 88 fittingFinishedSignal = QtCore.pyqtSignal(tuple) 89 batchFittingFinishedSignal = QtCore.pyqtSignal(tuple) 90 85 91 def __init__(self, parent=None, data=None, tab_id=1): 86 92 … … 211 217 self.page_stack = [] 212 218 self.all_data = [] 219 # custom plugin models 220 # {model.name:model} 221 self.custom_models = self.customModels() 213 222 # Polydisp widget table default index for function combobox 214 223 self.orig_poly_index = 3 … … 415 424 self.onSelectModel() 416 425 426 def customModels(self): 427 """ Reads in file names in the custom plugin directory """ 428 return ModelUtilities._find_models() 429 417 430 def initializeControls(self): 418 431 """ … … 465 478 self._poly_model.itemChanged.connect(self.onPolyModelChange) 466 479 self._magnet_model.itemChanged.connect(self.onMagnetModelChange) 480 self.lstParams.selectionModel().selectionChanged.connect(self.onSelectionChanged) 481 482 # Local signals 483 self.batchFittingFinishedSignal.connect(self.batchFitComplete) 484 self.fittingFinishedSignal.connect(self.fitComplete) 467 485 468 486 # Signals from separate tabs asking for replot 469 487 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 488 489 # Signals from other widgets 490 self.communicate.customModelDirectoryChanged.connect(self.onCustomModelChange) 470 491 471 492 def modelName(self): … … 576 597 # widget.params[0] is the parameter we're constraining 577 598 constraint.param = mc_widget.params[0] 578 # Functionshould have the model name preamble599 # parameter should have the model name preamble 579 600 model_name = self.kernel_module.name 580 constraint.func = model_name + "." + c_text 601 # param_used is the parameter we're using in constraining function 602 param_used = mc_widget.params[1] 603 # Replace param_used with model_name.param_used 604 updated_param_used = model_name + "." + param_used 605 new_func = c_text.replace(param_used, updated_param_used) 606 constraint.func = new_func 581 607 # Which row is the constrained parameter in? 582 608 row = self.getRowFromName(constraint.param) … … 677 703 Delete constraints from selected parameters. 678 704 """ 679 self.deleteConstraintOnParameter(param=None) 705 params = [s.data() for s in self.lstParams.selectionModel().selectedRows() 706 if self.isCheckable(s.row())] 707 for param in params: 708 self.deleteConstraintOnParameter(param=param) 680 709 681 710 def deleteConstraintOnParameter(self, param=None): … … 686 715 max_col = self.lstParams.itemDelegate().param_max 687 716 for row in range(self._model_model.rowCount()): 717 if not self.rowHasConstraint(row): 718 continue 688 719 # Get the Constraint object from of the model item 689 720 item = self._model_model.item(row, 1) 690 if not item.hasChildren(): 691 continue 692 constraint = item.child(0).data() 721 constraint = self.getConstraintForRow(row) 693 722 if constraint is None: 694 723 continue … … 816 845 return constraints 817 846 847 def getConstraintsForFitting(self): 848 """ 849 Return a list of constraints in format ready for use in fiting 850 """ 851 # Get constraints 852 constraints = self.getComplexConstraintsForModel() 853 # See if there are any constraints across models 854 multi_constraints = [cons for cons in constraints if self.isConstraintMultimodel(cons[1])] 855 856 if multi_constraints: 857 # Let users choose what to do 858 msg = "The current fit contains constraints relying on other fit pages.\n" 859 msg += "Parameters with those constraints are:\n" +\ 860 '\n'.join([cons[0] for cons in multi_constraints]) 861 msg += "\n\nWould you like to remove these constraints or cancel fitting?" 862 msgbox = QtWidgets.QMessageBox(self) 863 msgbox.setIcon(QtWidgets.QMessageBox.Warning) 864 msgbox.setText(msg) 865 msgbox.setWindowTitle("Existing Constraints") 866 # custom buttons 867 button_remove = QtWidgets.QPushButton("Remove") 868 msgbox.addButton(button_remove, QtWidgets.QMessageBox.YesRole) 869 button_cancel = QtWidgets.QPushButton("Cancel") 870 msgbox.addButton(button_cancel, QtWidgets.QMessageBox.RejectRole) 871 retval = msgbox.exec_() 872 if retval == QtWidgets.QMessageBox.RejectRole: 873 # cancel fit 874 raise ValueError("Fitting cancelled") 875 else: 876 # remove constraint 877 for cons in multi_constraints: 878 self.deleteConstraintOnParameter(param=cons[0]) 879 # re-read the constraints 880 constraints = self.getComplexConstraintsForModel() 881 882 return constraints 883 818 884 def showModelDescription(self): 819 885 """ … … 874 940 self.respondToModelStructure(model=model, structure_factor=structure) 875 941 942 def onCustomModelChange(self): 943 """ 944 Reload the custom model combobox 945 """ 946 self.custom_models = self.customModels() 947 self.readCustomCategoryInfo() 948 # See if we need to update the combo in-place 949 if self.cbCategory.currentText() != CATEGORY_CUSTOM: return 950 951 current_text = self.cbModel.currentText() 952 self.cbModel.blockSignals(True) 953 self.cbModel.clear() 954 self.cbModel.blockSignals(False) 955 self.enableModelCombo() 956 self.disableStructureCombo() 957 # Retrieve the list of models 958 model_list = self.master_category_dict[CATEGORY_CUSTOM] 959 # Populate the models combobox 960 self.cbModel.addItems(sorted([model for (model, _) in model_list])) 961 new_index = self.cbModel.findText(current_text) 962 if new_index != -1: 963 self.cbModel.setCurrentIndex(self.cbModel.findText(current_text)) 964 965 def onSelectionChanged(self): 966 """ 967 React to parameter selection 968 """ 969 rows = self.lstParams.selectionModel().selectedRows() 970 # Clean previous messages 971 self.communicate.statusBarUpdateSignal.emit("") 972 if len(rows) == 1: 973 # Show constraint, if present 974 row = rows[0].row() 975 if self.rowHasConstraint(row): 976 func = self.getConstraintForRow(row).func 977 if func is not None: 978 self.communicate.statusBarUpdateSignal.emit("Active constrain: "+func) 979 876 980 def replaceConstraintName(self, old_name, new_name=""): 877 981 """ … … 886 990 new_func = func.replace(old_name, new_name) 887 991 self._model_model.item(row, 1).child(0).data().func = new_func 992 993 def isConstraintMultimodel(self, constraint): 994 """ 995 Check if the constraint function text contains current model name 996 """ 997 current_model_name = self.kernel_module.name 998 if current_model_name in constraint: 999 return False 1000 else: 1001 return True 888 1002 889 1003 def updateData(self): … … 937 1051 self._model_model.clear() 938 1052 return 939 1053 940 1054 # Safely clear and enable the model combo 941 1055 self.cbModel.blockSignals(True) … … 1105 1219 except ValueError as ex: 1106 1220 # This should not happen! GUI explicitly forbids this situation 1107 self.communicate.statusBarUpdateSignal.emit( 'Fitting attempt without parameters.')1221 self.communicate.statusBarUpdateSignal.emit(str(ex)) 1108 1222 return 1109 1223 1110 1224 # Create the fitting thread, based on the fitter 1111 completefn = self.batchFit Complete if self.is_batch_fitting else self.fitComplete1225 completefn = self.batchFittingCompleted if self.is_batch_fitting else self.fittingCompleted 1112 1226 1113 1227 calc_fit = FitThread(handler=handler, … … 1146 1260 pass 1147 1261 1262 def batchFittingCompleted(self, result): 1263 """ 1264 Send the finish message from calculate threads to main thread 1265 """ 1266 self.batchFittingFinishedSignal.emit(result) 1267 1148 1268 def batchFitComplete(self, result): 1149 1269 """ … … 1152 1272 #re-enable the Fit button 1153 1273 self.setFittingStopped() 1274 # Show the grid panel 1275 self.grid_window = BatchOutputPanel(parent=self, output_data=result[0]) 1276 self.grid_window.show() 1277 1278 def fittingCompleted(self, result): 1279 """ 1280 Send the finish message from calculate threads to main thread 1281 """ 1282 self.fittingFinishedSignal.emit(result) 1154 1283 1155 1284 def fitComplete(self, result): … … 1162 1291 1163 1292 if result is None: 1164 msg = "Fitting failed after: %s s.\n" % GuiUtils.formatNumber(elapsed)1293 msg = "Fitting failed." 1165 1294 self.communicate.statusBarUpdateSignal.emit(msg) 1166 1295 return … … 1228 1357 smearing, accuracy, smearing_min, smearing_max = self.smearing_widget.state() 1229 1358 1230 constraints = self.getComplexConstraintsForModel() 1359 constraints = self.getConstraintsForFitting() 1360 1231 1361 smearer = None 1232 1362 handler = None … … 1242 1372 constraints=constraints) 1243 1373 except ValueError as ex: 1244 logging.error("Setting model parameters failed with: %s" % ex) 1245 return 1374 raise ValueError("Setting model parameters failed with: %s" % ex) 1246 1375 1247 1376 qmin, qmax, _ = self.logic.computeRangeFromData(data) … … 1409 1538 if not dict: 1410 1539 return 1411 if self._m odel_model.rowCount() == 0:1540 if self._magnet_model.rowCount() == 0: 1412 1541 return 1413 1542 … … 1555 1684 self.models[model.name] = model 1556 1685 1686 self.readCustomCategoryInfo() 1687 1688 def readCustomCategoryInfo(self): 1689 """ 1690 Reads the custom model category 1691 """ 1692 #Looking for plugins 1693 self.plugins = list(self.custom_models.values()) 1694 plugin_list = [] 1695 for name, plug in self.custom_models.items(): 1696 self.models[name] = plug 1697 plugin_list.append([name, True]) 1698 self.master_category_dict[CATEGORY_CUSTOM] = plugin_list 1699 1557 1700 def regenerateModelDict(self): 1558 1701 """ … … 1662 1805 Setting model parameters into QStandardItemModel based on selected _model_ 1663 1806 """ 1664 kernel_module = generate.load_kernel_module(model_name) 1807 name = model_name 1808 if self.cbCategory.currentText() == CATEGORY_CUSTOM: 1809 # custom kernel load requires full path 1810 name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py") 1811 kernel_module = generate.load_kernel_module(name) 1665 1812 self.model_parameters = modelinfo.make_parameter_table(getattr(kernel_module, 'parameters', [])) 1666 1813 -
src/sas/qtgui/Perspectives/Fitting/ModelUtilities.py
- Property mode changed from 100755 to 100644
rb3e8629 r3b3b40b 179 179 plugins = {} 180 180 for filename in os.listdir(directory): 181 181 182 name, ext = os.path.splitext(filename) 182 183 if ext == '.py' and not name == '__init__': … … 184 185 try: 185 186 model = load_custom_model(path) 186 model.name = PLUGIN_NAME_BASE + model.name187 #model.name = PLUGIN_NAME_BASE + model.name 187 188 plugins[model.name] = model 188 189 except Exception: … … 415 416 implement model 416 417 """ 417 __modelmanager = ModelManagerBase() 418 cat_model_list = [__modelmanager.model_dictionary[model_name] for model_name \ 419 in list(__modelmanager.model_dictionary.keys()) \ 420 if model_name not in list(__modelmanager.stored_plugins.keys())] 421 422 CategoryInstaller.check_install(model_list=cat_model_list) 418 def __init__(self): 419 self.__modelmanager = ModelManagerBase() 420 self.cat_model_list = [self.__modelmanager.model_dictionary[model_name] for model_name \ 421 in list(self.__modelmanager.model_dictionary.keys()) \ 422 if model_name not in list(self.__modelmanager.stored_plugins.keys())] 423 424 CategoryInstaller.check_install(model_list=self.cat_model_list) 425 423 426 def findModels(self): 424 427 return self.__modelmanager.findModels() -
src/sas/qtgui/Perspectives/Fitting/MultiConstraint.py
r14ec91c5 r3b3b40b 114 114 115 115 # 3. parameter name should be a separate word, but can have "()[]*+-/ " around 116 valid_neighbours = "()[]*+-/ "117 start_loc = parameter_string_start -1118 end_loc = parameter_string_end119 if not any([constraint_text[start_loc] == ch for ch in valid_neighbours]):120 return False121 if end_loc < len(constraint_text):122 if not any([constraint_text[end_loc] == ch for ch in valid_neighbours]):123 return False116 #valid_neighbours = "()[]*+-/ " 117 #start_loc = parameter_string_start -1 118 #end_loc = parameter_string_end 119 #if not any([constraint_text[start_loc] == ch for ch in valid_neighbours]): 120 # return False 121 #if end_loc < len(constraint_text): 122 # if not any([constraint_text[end_loc] == ch for ch in valid_neighbours]): 123 # return False 124 124 125 125 # 4. replace parameter name with "1" and try to evaluate the expression -
src/sas/qtgui/Perspectives/Fitting/UI/FittingWidgetUI.ui
re4c475b7 r3b3b40b 7 7 <x>0</x> 8 8 <y>0</y> 9 <width> 568</width>9 <width>680</width> 10 10 <height>605</height> 11 11 </rect> -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/ConstraintWidgetTest.py
- Property mode changed from 100755 to 100644
r725d9c06 r3b3b40b 22 22 if not QtWidgets.QApplication.instance(): 23 23 app = QtWidgets.QApplication(sys.argv) 24 #app = QtWidgets.QApplication(sys.argv)25 24 26 25 class ConstraintWidgetTest(unittest.TestCase): … … 71 70 # click on "batch" 72 71 QTest.mouseClick(self.widget.btnBatch, QtCore.Qt.LeftButton) 73 app.processEvents()72 QtWidgets.QApplication.processEvents() 74 73 # See what the current type is now 75 74 self.assertEqual(self.widget.currentType, "BatchPage") … … 78 77 # Go back to single fit 79 78 QTest.mouseClick(self.widget.btnSingle, QtCore.Qt.LeftButton) 80 app.processEvents()79 QtWidgets.QApplication.processEvents() 81 80 # See what the current type is now 82 81 self.assertEqual(self.widget.currentType, "FitPage") -
src/sas/qtgui/Utilities/GuiUtils.py
r63319b0 r3b3b40b 213 213 plotRequestedSignal = QtCore.pyqtSignal(list) 214 214 215 # Plot from file names 216 plotFromFilenameSignal = QtCore.pyqtSignal(str) 217 215 218 # Plot update requested from a perspective 216 219 plotUpdateSignal = QtCore.pyqtSignal(list) … … 236 239 # Send result of Data Operation Utility panel to Data Explorer 237 240 updateModelFromDataOperationPanelSignal = QtCore.pyqtSignal(QtGui.QStandardItem, dict) 241 242 # Notify about a new custom plugin being written/deleted/modified 243 customModelDirectoryChanged = QtCore.pyqtSignal() 238 244 239 245 def updateModelItemWithPlot(item, update_data, name=""): … … 872 878 raise TypeError 873 879 880 def findNextFilename(filename, directory): 881 """ 882 Finds the next available (non-existing) name for 'filename' in 'directory'. 883 plugin.py -> plugin (n).py - for first 'n' for which the file doesn't exist 884 """ 885 basename, ext = os.path.splitext(filename) 886 # limit the number of copies 887 MAX_FILENAMES = 1000 888 # Start with (1) 889 number_ext = 1 890 proposed_filename = "" 891 found_filename = False 892 # Find the next available filename or exit if too many copies 893 while not found_filename or number_ext > MAX_FILENAMES: 894 proposed_filename = basename + " ("+str(number_ext)+")" + ext 895 if os.path.exists(os.path.join(directory, proposed_filename)): 896 number_ext += 1 897 else: 898 found_filename = True 899 900 return proposed_filename 901 902 874 903 class DoubleValidator(QtGui.QDoubleValidator): 875 904 """ -
src/sas/qtgui/Utilities/LocalConfig.py
rc3eb858 r3b3b40b 141 141 # Time out for updating sasview 142 142 UPDATE_TIMEOUT = 2 143 144 # Logging levels to disable, if any 145 DISABLE_LOGGING = logging.DEBUG 146 143 147 def printEVT(message): 144 148 """
Note: See TracChangeset
for help on using the changeset viewer.