Changeset d744767 in sasview
- Timestamp:
- Mar 16, 2018 2:05:42 PM (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:
- 47bf906
- Parents:
- 477c473 (diff), e4c475b7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 32 added
- 197 edited
Legend:
- Unmodified
- Added
- Removed
-
docs/sphinx-docs/build_sphinx.py
rdf72475 re90988c 220 220 print("=== Build HTML Docs from ReST Files ===") 221 221 subprocess.call(["sphinx-build", 222 "-b", " html", # Builder name. TODO: accept as arg to setup.py.222 "-b", "qthelp", # Builder name. TODO: accept as arg to setup.py. 223 223 "-d", joinpath(SPHINX_BUILD, "doctrees"), 224 224 SPHINX_SOURCE, -
installers/installer_generator.py
- Property mode changed from 100644 to 100755
-
run.py
r856cf59 rd744767 118 118 # Import the sasview package from root/sasview as sas.sasview. It would 119 119 # be better to just store the package in src/sas/sasview. 120 import sas 121 #sas.sasview = import_package('sas.sasview', joinpath(root, 'sasview')) 122 sas.sasview = import_package('sas.sasview', joinpath(root, 'src','sas','sasview')) 120 #import sas 121 #sas.sasview = import_package('sas.sasview', joinpath(root, 'src','sas','sasview')) 123 122 124 123 # Compiled modules need to be pulled from the build directory. … … 138 137 import sas.sascalc.calculator 139 138 sas.sascalc.calculator.core = import_package('sas.sascalc.calculator.core', 140 139 joinpath(build_path, 'sas', 'sascalc', 'calculator', 'core')) 141 140 142 141 sys.path.append(build_path) -
setup.py
rf4a1433 r14ec91c5 53 53 if os.path.isfile(f_path): 54 54 os.remove(f_path) 55 f_path = os.path.join(sas_dir, "categories.json")56 if os.path.isfile(f_path):57 os.remove(f_path)55 #f_path = os.path.join(sas_dir, "categories.json") 56 #if os.path.isfile(f_path): 57 # os.remove(f_path) 58 58 f_path = os.path.join(sas_dir, 'config', "custom_config.py") 59 59 if os.path.isfile(f_path): … … 380 380 "src", "sas", "qtgui", "Perspectives", "Fitting", "UI") 381 381 packages.extend(["sas.qtgui.Perspectives.Fitting", "sas.qtgui.Perspectives.Fitting.UI"]) 382 383 package_dir["sas.qtgui.Perspectives.Inversion"] = os.path.join( 384 "src", "sas", "qtgui", "Perspectives", "Inversion") 385 package_dir["sas.qtgui.Perspectives.Inversion.UI"] = os.path.join( 386 "src", "sas", "qtgui", "Perspectives", "Inversion", "UI") 387 packages.extend(["sas.qtgui.Perspectives.Inversion", "sas.qtgui.Perspectives.Inversion.UI"]) 388 389 package_dir["sas.qtgui.Perspectives.Corfunc"] = os.path.join( 390 "src", "sas", "qtgui", "Perspectives", "Corfunc") 391 package_dir["sas.qtgui.Perspectives.Corfunc.UI"] = os.path.join( 392 "src", "sas", "qtgui", "Perspectives", "Corfunc", "UI") 393 packages.extend(["sas.qtgui.Perspectives.Corfunc", "sas.qtgui.Perspectives.Corfunc.UI"]) 382 394 383 395 ## Plotting … … 451 463 452 464 required = [ 453 'bumps>=0.7.5.9', 'periodictable>=1.5.0', 'pyparsing<2.0.0', 454 455 # 'lxml>=2.2.2', 465 'bumps>=0.7.5.9', 'periodictable>=1.5.0', 456 466 'lxml', 'h5py', 457 467 -
src/sas/logger_config.py
rf4a1433 rcee5c78 49 49 ''' 50 50 for handler in logger.handlers or logger.parent.handlers: 51 handler.setLevel(logging.DEBUG) 51 #handler.setLevel(logging.DEBUG) 52 handler.setLevel(logging.WARNING) 52 53 for name, _ in logging.Logger.manager.loggerDict.items(): 53 logging.getLogger(name).setLevel(logging.DEBUG) 54 #logging.getLogger(name).setLevel(logging.DEBUG) 55 logging.getLogger(name).setLevel(logging.WARNING) 54 56 55 57 def _find_config_file(self, filename="logging.ini"): -
src/sas/qtgui/Calculators/DataOperationUtilityPanel.py
r7d9c83c re90988c 4 4 import copy 5 5 6 from PyQt4 import QtGui 7 from PyQt4 import QtCore 6 from PyQt5 import QtCore 7 from PyQt5 import QtGui 8 from PyQt5 import QtWidgets 8 9 9 10 from sas.qtgui.Plotting.PlotterData import Data1D … … 13 14 import sas.qtgui.Utilities.GuiUtils as GuiUtils 14 15 15 from UI.DataOperationUtilityUI import Ui_DataOperationUtility16 from .UI.DataOperationUtilityUI import Ui_DataOperationUtility 16 17 17 18 BG_WHITE = "background-color: rgb(255, 255, 255);" … … 19 20 20 21 21 class DataOperationUtilityPanel(Qt Gui.QDialog, Ui_DataOperationUtility):22 class DataOperationUtilityPanel(QtWidgets.QDialog, Ui_DataOperationUtility): 22 23 def __init__(self, parent=None): 23 24 super(DataOperationUtilityPanel, self).__init__() … … 55 56 56 57 # validator for coefficient 57 self.txtNumber.setValidator( QtGui.QDoubleValidator())58 59 self.layoutOutput = Qt Gui.QHBoxLayout()60 self.layoutData1 = Qt Gui.QHBoxLayout()61 self.layoutData2 = Qt Gui.QHBoxLayout()58 self.txtNumber.setValidator(GuiUtils.DoubleValidator()) 59 60 self.layoutOutput = QtWidgets.QHBoxLayout() 61 self.layoutData1 = QtWidgets.QHBoxLayout() 62 self.layoutData2 = QtWidgets.QHBoxLayout() 62 63 63 64 # Create default layout for initial graphs (when they are still empty) … … 76 77 self.filenames = filenames 77 78 78 if filenames.keys():79 if list(filenames.keys()): 79 80 # clear contents of comboboxes 80 81 self.cbData1.clear() … … 85 86 list_datafiles = [] 86 87 87 for key_id in filenames.keys():88 for key_id in list(filenames.keys()): 88 89 if filenames[key_id].get_data().title: 89 90 # filenames with titles … … 109 110 documentation tree (after /doc/ ....". 110 111 """ 111 try: 112 location = GuiUtils.HELP_DIRECTORY_LOCATION + \ 113 "/user/sasgui/perspectives/calculator/data_operator_help.html" 114 self.manager._helpView.load(QtCore.QUrl(location)) 115 self.manager._helpView.show() 116 117 except AttributeError: 118 # No manager defined - testing and standalone runs 119 pass 112 location = "/user/sasgui/perspectives/calculator/data_operator_help.html" 113 self.manager.showHelp(location) 120 114 121 115 def onClose(self): … … 139 133 data1 = self.data1 140 134 data2 = self.data2 141 exec "output = data1 %s data2" % operator 142 except: 143 raise 135 output = eval("data1 %s data2" % operator) 136 except Exception as ex: 137 logging.error(ex) 138 return 144 139 145 140 self.output = output … … 158 153 """ Prepare datasets to be added to DataExplorer and DataManager """ 159 154 new_item = GuiUtils.createModelItemWithPlot( 160 QtCore.QVariant(self.output),155 self.output, 161 156 name=self.txtOutputData.text()) 162 157 … … 273 268 msg = 'DataOperation: Number requires a float number' 274 269 logging.warning(msg) 275 self.txtNumber.setStyleSheet( QtCore.QString(BG_RED))270 self.txtNumber.setStyleSheet(BG_RED) 276 271 277 272 elif float(self.txtNumber.text()) == 0.: … … 279 274 msg = 'DataOperation: Number requires a non zero number' 280 275 logging.warning(msg) 281 self.txtNumber.setStyleSheet( QtCore.QString(BG_RED))276 self.txtNumber.setStyleSheet(BG_RED) 282 277 283 278 else: 284 self.txtNumber.setStyleSheet( QtCore.QString(BG_WHITE))279 self.txtNumber.setStyleSheet(BG_WHITE) 285 280 self.data2 = float(self.txtNumber.text()) 286 281 self.updatePlot(self.graphData2, self.layoutData2, self.data2) … … 293 288 else: 294 289 if self.cbData2.currentText() == 'Number': 295 self.cbData1.setStyleSheet( QtCore.QString(BG_WHITE))296 self.cbData2.setStyleSheet( QtCore.QString(BG_WHITE))290 self.cbData1.setStyleSheet(BG_WHITE) 291 self.cbData2.setStyleSheet(BG_WHITE) 297 292 return True 298 293 299 294 elif self.data1.__class__.__name__ != self.data2.__class__.__name__: 300 self.cbData1.setStyleSheet( QtCore.QString(BG_RED))301 self.cbData2.setStyleSheet( QtCore.QString(BG_RED))302 print self.data1.__class__.__name__ != self.data2.__class__.__name__295 self.cbData1.setStyleSheet(BG_RED) 296 self.cbData2.setStyleSheet(BG_RED) 297 print(self.data1.__class__.__name__ != self.data2.__class__.__name__) 303 298 logging.warning('Cannot compute data of different dimensions') 304 299 return False … … 308 303 not all(i == j for i, j in zip(self.data1.x, self.data2.x))): 309 304 logging.warning('Cannot compute 1D data of different lengths') 310 self.cbData1.setStyleSheet( QtCore.QString(BG_RED))311 self.cbData2.setStyleSheet( QtCore.QString(BG_RED))305 self.cbData1.setStyleSheet(BG_RED) 306 self.cbData2.setStyleSheet(BG_RED) 312 307 return False 313 308 … … 320 315 zip(self.data1.qy_data, self.data2.qy_data)) 321 316 ): 322 self.cbData1.setStyleSheet( QtCore.QString(BG_RED))323 self.cbData2.setStyleSheet( QtCore.QString(BG_RED))317 self.cbData1.setStyleSheet(BG_RED) 318 self.cbData2.setStyleSheet(BG_RED) 324 319 logging.warning('Cannot compute 2D data of different lengths') 325 320 return False 326 321 327 322 else: 328 self.cbData1.setStyleSheet( QtCore.QString(BG_WHITE))329 self.cbData2.setStyleSheet( QtCore.QString(BG_WHITE))323 self.cbData1.setStyleSheet(BG_WHITE) 324 self.cbData2.setStyleSheet(BG_WHITE) 330 325 return True 331 326 … … 333 328 """ Check that name of output does not already exist """ 334 329 name_to_check = str(self.txtOutputData.text()) 335 self.txtOutputData.setStyleSheet( QtCore.QString(BG_WHITE))330 self.txtOutputData.setStyleSheet(BG_WHITE) 336 331 337 332 if name_to_check is None or name_to_check == '': 338 self.txtOutputData.setStyleSheet( QtCore.QString(BG_RED))333 self.txtOutputData.setStyleSheet(BG_RED) 339 334 logging.warning('No output name') 340 335 return False 341 336 342 337 elif name_to_check in self.list_data_items: 343 self.txtOutputData.setStyleSheet( QtCore.QString(BG_RED))338 self.txtOutputData.setStyleSheet(BG_RED) 344 339 logging.warning('The Output data name already exists') 345 340 return False 346 341 347 342 else: 348 self.txtOutputData.setStyleSheet( QtCore.QString(BG_WHITE))343 self.txtOutputData.setStyleSheet(BG_WHITE) 349 344 return True 350 345 … … 354 349 def _findId(self, name): 355 350 """ find id of name in list of filenames """ 356 isinstance(name, basestring)357 358 for key_id in self.filenames.keys():351 isinstance(name, str) 352 353 for key_id in list(self.filenames.keys()): 359 354 # data with title 360 355 if self.filenames[key_id].get_data().title: … … 383 378 def newPlot(self, graph, layout): 384 379 """ Create template for graphs with default '?' layout""" 385 assert isinstance(graph, Qt Gui.QGraphicsView)386 assert isinstance(layout, Qt Gui.QHBoxLayout)380 assert isinstance(graph, QtWidgets.QGraphicsView) 381 assert isinstance(layout, QtWidgets.QHBoxLayout) 387 382 388 383 # clear layout … … 399 394 """ plot data in graph after clearing its layout """ 400 395 401 assert isinstance(graph, Qt Gui.QGraphicsView)402 assert isinstance(layout, Qt Gui.QHBoxLayout)396 assert isinstance(graph, QtWidgets.QGraphicsView) 397 assert isinstance(layout, QtWidgets.QHBoxLayout) 403 398 404 399 # clear layout … … 455 450 def prepareSubgraphWithData(self, data): 456 451 """ Create graphics view containing scene with string """ 457 scene = Qt Gui.QGraphicsScene()452 scene = QtWidgets.QGraphicsScene() 458 453 scene.addText(str(data)) 459 454 460 subgraph = Qt Gui.QGraphicsView()455 subgraph = QtWidgets.QGraphicsView() 461 456 subgraph.setScene(scene) 462 457 -
src/sas/qtgui/Calculators/DensityPanel.py
rb0c5e8c re90988c 2 2 import logging 3 3 import functools 4 from PyQt4 import QtGui, QtCore 4 from PyQt5 import QtCore 5 from PyQt5 import QtGui 6 from PyQt5 import QtWidgets 5 7 6 8 from periodictable import formula as Formula … … 13 15 from sas.qtgui.Calculators.UI.DensityPanel import Ui_DensityPanel 14 16 15 def enum(*sequential, **named): 16 enums = dict(zip(sequential, range(len(sequential))), **named) 17 return type('Enum', (), enums) 17 from sas.qtgui.Utilities.GuiUtils import enum 18 18 19 19 MODEL = enum( … … 39 39 40 40 41 class DensityPanel(Qt Gui.QDialog):41 class DensityPanel(QtWidgets.QDialog): 42 42 43 43 def __init__(self, parent=None): … … 58 58 59 59 # set validators 60 self.ui.editMolecularFormula.setValidator(FormulaValidator(self.ui.editMolecularFormula))60 #self.ui.editMolecularFormula.setValidator(FormulaValidator(self.ui.editMolecularFormula)) 61 61 62 62 rx = QtCore.QRegExp("[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?") … … 68 68 self.ui.editMassDensity.textEdited.connect(functools.partial(self.setMode, MODES.DENSITY_TO_VOLUME)) 69 69 70 self.ui.buttonBox.button(Qt Gui.QDialogButtonBox.Reset).clicked.connect(self.modelReset)71 self.ui.buttonBox.button(Qt Gui.QDialogButtonBox.Help).clicked.connect(self.displayHelp)70 self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.modelReset) 71 self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.displayHelp) 72 72 73 73 def setupModel(self): … … 83 83 84 84 def setupMapper(self): 85 self.mapper = Qt Gui.QDataWidgetMapper(self)85 self.mapper = QtWidgets.QDataWidgetMapper(self) 86 86 self.mapper.setModel(self.model) 87 87 self.mapper.setOrientation(QtCore.Qt.Vertical) … … 95 95 96 96 def dataChanged(self, top, bottom): 97 for index in xrange(top.row(), bottom.row() + 1):97 for index in range(top.row(), bottom.row() + 1): 98 98 if index == MODEL.MOLECULAR_FORMULA: 99 99 molarMass = toMolarMass(self.model.item(MODEL.MOLECULAR_FORMULA).text()) … … 137 137 138 138 def modelReset(self): 139 #self.model.beginResetModel()140 139 try: 141 140 self.setMode(None) … … 145 144 finally: 146 145 pass 147 #self.model.endResetModel()148 146 149 147 def displayHelp(self): 150 try: 151 location = HELP_DIRECTORY_LOCATION + \ 152 "/user/sasgui/perspectives/calculator/density_calculator_help.html" 148 location = "/user/sasgui/perspectives/calculator/density_calculator_help.html" 149 self.manager.showHelp(location) 153 150 154 self.manager._helpView.load(QtCore.QUrl(location)) 155 self.manager._helpView.show() 156 except AttributeError: 157 # No manager defined - testing and standalone runs 158 pass 151 -
src/sas/qtgui/Calculators/GenericScatteringCalculator.py
rfef38e8 re90988c 5 5 import time 6 6 7 from PyQt4 import QtGui 8 from PyQt4 import QtCore 7 from PyQt5 import QtCore 8 from PyQt5 import QtGui 9 from PyQt5 import QtWidgets 10 9 11 from twisted.internet import threads 10 12 … … 22 24 23 25 # Local UI 24 from UI.GenericScatteringCalculator import Ui_GenericScatteringCalculator26 from .UI.GenericScatteringCalculator import Ui_GenericScatteringCalculator 25 27 26 28 _Q1D_MIN = 0.001 27 29 28 30 29 class GenericScatteringCalculator(Qt Gui.QDialog, Ui_GenericScatteringCalculator):31 class GenericScatteringCalculator(QtWidgets.QDialog, Ui_GenericScatteringCalculator): 30 32 31 33 trigger_plot_3d = QtCore.pyqtSignal() … … 119 121 TODO Temporary solution to display information about option 'Ellipsoid' 120 122 """ 121 print "The option Ellipsoid has not been implemented yet."123 print("The option Ellipsoid has not been implemented yet.") 122 124 self.communicator.statusBarUpdateSignal.emit( 123 125 "The option Ellipsoid has not been implemented yet.") … … 129 131 """ 130 132 try: 131 self.datafile = Qt Gui.QFileDialog.getOpenFileName(133 self.datafile = QtWidgets.QFileDialog.getOpenFileName( 132 134 self, "Choose a file", "", "All Gen files (*.OMF *.omf) ;;" 133 135 "SLD files (*.SLD *.sld);;PDB files (*.pdb *.PDB);; " 134 136 "OMF files (*.OMF *.omf);; " 135 "All files (*.*)") 137 "All files (*.*)")[0] 136 138 if self.datafile: 137 139 self.default_shape = str(self.cbShape.currentText()) … … 165 167 self.reader.queue() 166 168 except (RuntimeError, IOError): 167 log_msg = "Generic SAS Calculator: %s" % sys.exc_ value169 log_msg = "Generic SAS Calculator: %s" % sys.exc_info()[1] 168 170 logging.info(log_msg) 169 171 raise … … 235 237 """Check range of text edits for QMax and Number of Qbins """ 236 238 text_edit = self.sender() 237 text_edit.setStyleSheet( 238 QtCore.QString.fromUtf8('background-color: rgb(255, 255, 255);')) 239 text_edit.setStyleSheet('background-color: rgb(255, 255, 255);') 239 240 if text_edit.text(): 240 241 value = float(str(text_edit.text())) 241 242 if text_edit == self.txtQxMax: 242 243 if value <= 0 or value > 1000: 243 text_edit.setStyleSheet(QtCore.QString.fromUtf8( 244 'background-color: rgb(255, 182, 193);')) 244 text_edit.setStyleSheet('background-color: rgb(255, 182, 193);') 245 245 else: 246 text_edit.setStyleSheet(QtCore.QString.fromUtf8( 247 'background-color: rgb(255, 255, 255);')) 246 text_edit.setStyleSheet('background-color: rgb(255, 255, 255);') 248 247 elif text_edit == self.txtNoQBins: 249 248 if value < 2 or value > 1000: 250 self.txtNoQBins.setStyleSheet(QtCore.QString.fromUtf8( 251 'background-color: rgb(255, 182, 193);')) 249 self.txtNoQBins.setStyleSheet('background-color: rgb(255, 182, 193);') 252 250 else: 253 self.txtNoQBins.setStyleSheet(QtCore.QString.fromUtf8( 254 'background-color: rgb(255, 255, 255);')) 251 self.txtNoQBins.setStyleSheet('background-color: rgb(255, 255, 255);') 255 252 256 253 def update_gui(self): … … 385 382 documentation tree (after /doc/ ....". 386 383 """ 387 try: 388 location = GuiUtils.HELP_DIRECTORY_LOCATION + \ 389 "/user/sasgui/perspectives/calculator/sas_calculator_help.html" 390 self.manager._helpView.load(QtCore.QUrl(location)) 391 self.manager._helpView.show() 392 except AttributeError: 393 # No manager defined - testing and standalone runs 394 pass 384 location = "/user/sasgui/perspectives/calculator/sas_calculator_help.html" 385 self.manager.showHelp(location) 395 386 396 387 def onReset(self): … … 555 546 # Add deferred callback for call return 556 547 d.addCallback(self.plot_1_2d) 548 d.addErrback(self.calculateFailed) 557 549 except: 558 log_msg = "{}. stop".format(sys.exc_ value)550 log_msg = "{}. stop".format(sys.exc_info()[1]) 559 551 logging.info(log_msg) 560 552 return … … 564 556 Copied from previous version 565 557 """ 558 pass 559 560 def calculateFailed(self, reason): 561 """ 562 """ 563 print("Calculate Failed with:\n", reason) 566 564 pass 567 565 … … 605 603 'directory': default_name, 606 604 'filter': 'SLD file (*.sld)', 607 'options': Qt Gui.QFileDialog.DontUseNativeDialog}605 'options': QtWidgets.QFileDialog.DontUseNativeDialog} 608 606 # Query user for filename. 609 filename = str(QtGui.QFileDialog.getSaveFileName(**kwargs)) 607 filename_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 608 filename = filename_tuple[0] 610 609 if filename: 611 610 try: 612 if os.path.splitext(filename)[1].lower() == '.sld': 613 sas_gen.SLDReader().write(filename, self.sld_data) 614 else: 615 sas_gen.SLDReader().write('.'.join((filename, 'sld')), 616 self.sld_data) 611 _, extension = os.path.splitext(filename) 612 if not extension: 613 filename = '.'.join((filename, 'sld')) 614 sas_gen.SLDReader().write(filename, self.sld_data) 617 615 except: 618 616 raise … … 644 642 self.graph_num += 1 645 643 # TODO 646 print 'TRANSFER OF DATA TO MAIN PANEL TO BE IMPLEMENTED'644 print('TRANSFER OF DATA TO MAIN PANEL TO BE IMPLEMENTED') 647 645 return plot1D 648 646 else: … … 662 660 self.graph_num += 1 663 661 # TODO 664 print 'TRANSFER OF DATA TO MAIN PANEL TO BE IMPLEMENTED'662 print('TRANSFER OF DATA TO MAIN PANEL TO BE IMPLEMENTED') 665 663 return plot2D 666 664 … … 744 742 # II. Plot selective points in color 745 743 other_color = numpy.ones(len(pix_symbol), dtype='bool') 746 for key in color_dic.keys():744 for key in list(color_dic.keys()): 747 745 chosen_color = pix_symbol == key 748 746 if numpy.any(chosen_color): … … 758 756 # Get atom names not in the list 759 757 a_names = [symb for symb in pix_symbol \ 760 if symb not in color_dic.keys()]758 if symb not in list(color_dic.keys())] 761 759 a_name = a_names[0] 762 760 for name in a_names: … … 828 826 829 827 830 class Plotter3D(Qt Gui.QDialog, Plotter3DWidget):828 class Plotter3D(QtWidgets.QDialog, Plotter3DWidget): 831 829 def __init__(self, parent=None, graph_title=''): 832 830 self.graph_title = graph_title 833 Qt Gui.QDialog.__init__(self)831 QtWidgets.QDialog.__init__(self) 834 832 Plotter3DWidget.__init__(self, manager=parent) 835 833 self.setWindowTitle(self.graph_title) -
src/sas/qtgui/Calculators/KiessigPanel.py
rb0c5e8c re90988c 1 from PyQt4 import QtGui 2 from PyQt4 import QtCore 1 from PyQt5 import QtCore 2 from PyQt5 import QtGui 3 from PyQt5 import QtWidgets 3 4 4 5 from sas.qtgui.UI import main_resources_rc 5 from UI.KiessigPanel import Ui_KiessigPanel6 from .UI.KiessigPanel import Ui_KiessigPanel 6 7 import sas.qtgui.Utilities.GuiUtils as GuiUtils 7 8 … … 10 11 11 12 12 class KiessigPanel(Qt Gui.QDialog, Ui_KiessigPanel):13 class KiessigPanel(QtWidgets.QDialog, Ui_KiessigPanel): 13 14 def __init__(self, parent=None): 14 15 super(KiessigPanel, self).__init__() … … 37 38 documentation tree (after /doc/ ....". 38 39 """ 39 try: 40 location = GuiUtils.HELP_DIRECTORY_LOCATION + \ 41 "/user/sasgui/perspectives/calculator/kiessig_calculator_help.html" 42 43 self.manager._helpView.load(QtCore.QUrl(location)) 44 self.manager._helpView.show() 45 except AttributeError: 46 # No manager defined - testing and standalone runs 47 pass 40 location = "/user/sasgui/perspectives/calculator/kiessig_calculator_help.html" 41 self.manager.showHelp(location) 48 42 49 43 def onCompute(self): … … 54 48 self.thickness.set_deltaq(dq=float(self.deltaq_in.text())) 55 49 kiessing_result = self.thickness.compute_thickness() 56 float_as_str = "{:.3f}".format(kiessing_result) 57 self.lengthscale_out.setText(float_as_str) 50 if kiessing_result: 51 float_as_str = "{:.3f}".format(kiessing_result) 52 self.lengthscale_out.setText(float_as_str) 53 else: 54 # error or division by zero 55 self.lengthscale_out.setText("") 56 58 57 except (ArithmeticError, ValueError): 59 58 self.lengthscale_out.setText("") -
src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py
r170e95d re90988c 4 4 instrumental parameters. 5 5 """ 6 from PyQt4 import QtGui 7 from PyQt4 import QtCore 6 from PyQt5 import QtCore 7 from PyQt5 import QtGui 8 from PyQt5 import QtWidgets 8 9 9 10 from twisted.internet import threads … … 20 21 import re 21 22 22 from UI.ResolutionCalculatorPanelUI import Ui_ResolutionCalculatorPanel23 from .UI.ResolutionCalculatorPanelUI import Ui_ResolutionCalculatorPanel 23 24 24 25 _SOURCE_MASS = {'Alpha': 6.64465620E-24, … … 33 34 34 35 35 class ResolutionCalculatorPanel(Qt Gui.QDialog, Ui_ResolutionCalculatorPanel):36 class ResolutionCalculatorPanel(QtWidgets.QDialog, Ui_ResolutionCalculatorPanel): 36 37 """ 37 38 compute resolution in 2D … … 105 106 106 107 # double validator 107 self.txtSource2SampleDistance.setValidator( QtGui.QDoubleValidator())108 self.txtSample2DetectorDistance.setValidator( QtGui.QDoubleValidator())109 self.txtSampleOffset.setValidator( QtGui.QDoubleValidator())108 self.txtSource2SampleDistance.setValidator(GuiUtils.DoubleValidator()) 109 self.txtSample2DetectorDistance.setValidator(GuiUtils.DoubleValidator()) 110 self.txtSampleOffset.setValidator(GuiUtils.DoubleValidator()) 110 111 111 112 # call compute to calculate with default values 112 113 self.createTemplate2DPlot() 113 self.onCompute()114 #self.onCompute() 114 115 115 116 # ################################# … … 123 124 text_edit = self.txtWavelength # self.sender() 124 125 if text_edit.isModified(): 125 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))126 text_edit.setStyleSheet(BG_WHITE) 126 127 input_string = str(text_edit.text()) 127 128 if self.cbWaveColor.currentText() != 'TOF': 128 129 input_wavelength = re.match('\d+\.?\d*', input_string) 129 130 if input_wavelength is None: 130 text_edit.setStyleSheet( QtCore.QString(BG_RED))131 text_edit.setStyleSheet(BG_RED) 131 132 self.cmdCompute.setEnabled(False) 132 133 logging.info('Wavelength has to be a number.') 133 134 else: 134 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))135 text_edit.setStyleSheet(BG_WHITE) 135 136 self.cmdCompute.setEnabled(True) 136 137 else: … … 139 140 140 141 if interval_wavelength is None: 141 text_edit.setStyleSheet( QtCore.QString(BG_RED))142 text_edit.setStyleSheet(BG_RED) 142 143 self.cmdCompute.setEnabled(False) 143 144 logging.info("Wavelength's input has to be an interval: " … … 149 150 150 151 if float(wavelength_min) >= float(wavelength_max): 151 text_edit.setStyleSheet( QtCore.QString(BG_RED))152 text_edit.setStyleSheet(BG_RED) 152 153 self.cmdCompute.setEnabled(False) 153 154 logging.info("Wavelength: min must be smaller than max.") 154 155 155 156 else: 156 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))157 text_edit.setStyleSheet(BG_WHITE) 157 158 self.cmdCompute.setEnabled(True) 158 159 … … 163 164 164 165 if text_edit.isModified(): 165 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))166 text_edit.setStyleSheet(BG_WHITE) 166 167 if self.cbWaveColor.currentText() != 'TOF': 167 168 pattern = '^\d+\.?\d*(|;\s*\d+)$' … … 170 171 171 172 if wavelength_spread_input is None: 172 text_edit.setStyleSheet( QtCore.QString(BG_RED))173 text_edit.setStyleSheet(BG_RED) 173 174 self.cmdCompute.setEnabled(False) 174 175 logging.info('Wavelength spread has to be specified: ' … … 178 179 split_input = wavelength_spread_input.group().split(';') 179 180 self.num_wave = split_input[1] if len(split_input) > 1 else 10 180 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))181 text_edit.setStyleSheet(BG_WHITE) 181 182 self.cmdCompute.setEnabled(True) 182 183 else: … … 186 187 187 188 if wavelength_spread_input is None: 188 text_edit.setStyleSheet( QtCore.QString(BG_RED))189 text_edit.setStyleSheet(BG_RED) 189 190 self.cmdCompute.setEnabled(False) 190 191 logging.info("Wavelength spread has to be specified: " … … 197 198 self.num_wave = split_input[1] if len( 198 199 split_input) > 1 else 10 199 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))200 text_edit.setStyleSheet(BG_WHITE) 200 201 self.cmdCompute.setEnabled(True) 201 202 … … 205 206 206 207 if text_edit.isModified(): 207 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))208 text_edit.setStyleSheet(BG_WHITE) 208 209 pattern = '^\d+\.?\d*,\s*\d+\.?\d*$' 209 210 input_string = str(text_edit.text()) … … 211 212 212 213 if pixels_input is None: 213 text_edit.setStyleSheet( QtCore.QString(BG_RED))214 text_edit.setStyleSheet(BG_RED) 214 215 self.cmdCompute.setEnabled(False) 215 216 logging.info('The input for the detector should contain 2 ' … … 217 218 218 219 else: 219 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))220 text_edit.setStyleSheet(BG_WHITE) 220 221 self.cmdCompute.setEnabled(True) 221 222 … … 229 230 q_input = re.match(pattern, input_string) 230 231 if q_input is None: 231 text_edit.setStyleSheet( QtCore.QString(BG_RED))232 text_edit.setStyleSheet(BG_RED) 232 233 self.cmdCompute.setEnabled(False) 233 234 logging.info('Qx and Qy should contain one or more comma-separated numbers.') 234 235 else: 235 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))236 text_edit.setStyleSheet(BG_WHITE) 236 237 self.cmdCompute.setEnabled(True) 237 238 qx = str(self.txtQx.text()).split(',') … … 247 248 248 249 elif len(qx) != len(qy): 249 text_edit.setStyleSheet( QtCore.QString(BG_RED))250 text_edit.setStyleSheet(BG_RED) 250 251 self.cmdCompute.setEnabled(False) 251 252 logging.info( … … 253 254 254 255 else: 255 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))256 text_edit.setStyleSheet(BG_WHITE) 256 257 self.cmdCompute.setEnabled(True) 257 258 … … 261 262 262 263 if text_edit.isModified(): 263 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))264 text_edit.setStyleSheet(BG_WHITE) 264 265 input_string = str(text_edit.text()) 265 266 pattern = '^\d+\.?\d*(|,\s*\d+)$' … … 267 268 268 269 if aperture_input is None: 269 text_edit.setStyleSheet( QtCore.QString(BG_RED))270 text_edit.setStyleSheet(BG_RED) 270 271 self.cmdCompute.setEnabled(False) 271 272 logging.info('A circular aperture is defined by a single ' … … 274 275 275 276 else: 276 text_edit.setStyleSheet( QtCore.QString(BG_WHITE))277 text_edit.setStyleSheet(BG_WHITE) 277 278 self.cmdCompute.setEnabled(True) 278 279 … … 315 316 """ On Spectrum Combobox event""" 316 317 if self.cbCustomSpectrum.currentText() == 'Add New': 317 datafile = Qt Gui.QFileDialog.getOpenFileName(318 self, "Choose a spectral distribution file", 319 "All files (*.*)", 320 None, QtGui.QFileDialog.DontUseNativeDialog)318 datafile = QtWidgets.QFileDialog.getOpenFileName( 319 self, "Choose a spectral distribution file","", 320 "All files (*.*)", None, 321 QtWidgets.QFileDialog.DontUseNativeDialog)[0] 321 322 322 323 if datafile is None or str(datafile) == '': … … 328 329 try: 329 330 basename = os.path.basename(datafile) 330 if basename not in self.spectrum_dic.keys():331 if basename not in list(self.spectrum_dic.keys()): 331 332 self.cbCustomSpectrum.addItem(basename) 332 333 … … 365 366 documentation tree (after /doc/ ....". 366 367 """ 367 try: 368 location = GuiUtils.HELP_DIRECTORY_LOCATION + \ 369 "/user/sasgui/perspectives/calculator/resolution_calculator_help.html" 370 self.manager._helpView.load(QtCore.QUrl(location)) 371 self.manager._helpView.show() 372 373 except AttributeError: 374 # No manager defined - testing and standalone runs 375 pass 368 location = "/user/sasgui/perspectives/calculator/resolution_calculator_help.html" 369 self.manager.showHelp(location) 376 370 377 371 def onReset(self): … … 524 518 525 519 cal_res.addCallback(self.complete) 520 cal_res.addErrback(self.calculateFailed) 526 521 527 522 # logging.info("Computation is in progress...") … … 531 526 raise 532 527 528 def calculateFailed(self, reason): 529 print("calculateFailed Failed with:\n", reason) 530 pass 531 533 532 def complete(self, image): 534 533 """ … … 562 561 : return: image (numpy array) 563 562 """ 564 image = map(func, qx, qy,563 image = list(map(func, qx, qy, 565 564 qx_min, qx_max, 566 qy_min, qy_max)[0] 565 qy_min, qy_max))[0] 566 567 567 return image 568 568 … … 604 604 msg = "The numbers must be one or two (separated by ',')" 605 605 logging.info(msg) 606 raise RuntimeError , msg606 raise RuntimeError(msg) 607 607 608 608 return new_numbers_list … … 618 618 new_list = [float(t) for t in string_split] 619 619 except: 620 logging.error(sys.exc_ value)620 logging.error(sys.exc_info()[1]) 621 621 return new_list 622 622 … … 658 658 return out 659 659 except: 660 logging.error(sys.exc_ value)660 logging.error(sys.exc_info()[1]) 661 661 662 662 def _validate_q_input(self, qx, qy): … … 713 713 self.plotter.scale = 'linear' 714 714 self.plotter.cmap = None 715 layout = Qt Gui.QHBoxLayout()715 layout = QtWidgets.QHBoxLayout() 716 716 layout.setContentsMargins(0, 0, 0, 0) 717 717 self.graphicsView.setLayout(layout) … … 742 742 self.plotter.plot() 743 743 self.plotter.show() 744 self.plotter.update() 744 745 745 746 def drawLines(self): -
src/sas/qtgui/Calculators/SldPanel.py
rb0c5e8c re90988c 1 1 # global 2 2 import logging 3 from PyQt4 import QtGui, QtCore 3 from PyQt5 import QtCore 4 from PyQt5 import QtGui 5 from PyQt5 import QtWidgets 4 6 5 7 from periodictable import formula as Formula … … 14 16 from sas.qtgui.Calculators.UI.SldPanel import Ui_SldPanel 15 17 16 def enum(*sequential, **named): 17 enums = dict(zip(sequential, range(len(sequential))), **named) 18 return type('Enum', (), enums) 18 from sas.qtgui.Utilities.GuiUtils import enum 19 19 20 20 MODEL = enum( … … 60 60 if len(formula.atoms) != 1: 61 61 raise NotImplementedError() 62 energy = xray_energy( formula.atoms.keys()[0].K_alpha)62 energy = xray_energy(list(formula.atoms.keys())[0].K_alpha) 63 63 return xray_sld_from_atoms( 64 64 sld_formula.atoms, … … 97 97 98 98 99 class SldPanel(Qt Gui.QDialog):99 class SldPanel(QtWidgets.QDialog): 100 100 101 101 def __init__(self, parent=None): … … 126 126 127 127 # set validators 128 self.ui.editMolecularFormula.setValidator(GuiUtils.FormulaValidator(self.ui.editMolecularFormula)) 128 # TODO: GuiUtils.FormulaValidator() crashes with Qt5 - fix 129 #self.ui.editMolecularFormula.setValidator(GuiUtils.FormulaValidator(self.ui.editMolecularFormula)) 129 130 130 131 rx = QtCore.QRegExp("[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?") … … 133 134 134 135 # signals 135 self.ui.buttonBox.button(Qt Gui.QDialogButtonBox.Reset).clicked.connect(self.modelReset)136 self.ui.buttonBox.button(Qt Gui.QDialogButtonBox.Help).clicked.connect(self.displayHelp)136 self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.modelReset) 137 self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.displayHelp) 137 138 138 139 def setupModel(self): … … 142 143 self.model.setItem(MODEL.WAVELENGTH , QtGui.QStandardItem()) 143 144 144 for key in self._getOutputs().keys():145 for key in list(self._getOutputs().keys()): 145 146 self.model.setItem(key, QtGui.QStandardItem()) 146 147 147 QtCore.QObject.connect( 148 self.model, 149 QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), 150 self.dataChanged) 148 self.model.dataChanged.connect(self.dataChanged) 151 149 152 150 self.modelReset() 153 151 154 152 def setupMapper(self): 155 self.mapper = Qt Gui.QDataWidgetMapper(self)153 self.mapper = QtWidgets.QDataWidgetMapper(self) 156 154 self.mapper.setModel(self.model) 157 155 self.mapper.setOrientation(QtCore.Qt.Vertical) 158 159 156 self.mapper.addMapping(self.ui.editMolecularFormula, MODEL.MOLECULAR_FORMULA) 160 157 self.mapper.addMapping(self.ui.editMassDensity , MODEL.MASS_DENSITY) 161 158 self.mapper.addMapping(self.ui.editWavelength , MODEL.WAVELENGTH) 162 159 163 for key, edit in self._getOutputs().ite ritems():160 for key, edit in self._getOutputs().items(): 164 161 self.mapper.addMapping(edit, key) 165 162 … … 168 165 def dataChanged(self, top, bottom): 169 166 update = False 170 for index in xrange(top.row(), bottom.row() + 1):167 for index in range(top.row(), bottom.row() + 1): 171 168 if (index == MODEL.MOLECULAR_FORMULA) or (index == MODEL.MASS_DENSITY) or (index == MODEL.WAVELENGTH): 172 169 update = True … … 202 199 pass 203 200 204 for key in self._getOutputs().keys():201 for key in list(self._getOutputs().keys()): 205 202 self.model.item(key).setText("") 206 203 … … 213 210 finally: 214 211 pass 215 212 #self.model.endResetModel() 216 213 217 214 def displayHelp(self): 218 try: 219 location = GuiUtils.HELP_DIRECTORY_LOCATION + \ 220 "/user/sasgui/perspectives/calculator/sld_calculator_help.html" 221 self.manager._helpView.load(QtCore.QUrl(location)) 222 self.manager._helpView.show() 223 except AttributeError: 224 # No manager defined - testing and standalone runs 225 pass 226 215 location = "/user/sasgui/perspectives/calculator/sld_calculator_help.html" 216 self.manager.showHelp(location) 217 218 -
src/sas/qtgui/Calculators/SlitSizeCalculator.py
rf4a1433 re90988c 4 4 import os 5 5 import sys 6 import logging 6 7 7 from PyQt4 import QtGui 8 from PyQt4 import QtCore 8 from PyQt5 import QtCore 9 from PyQt5 import QtGui 10 from PyQt5 import QtWidgets 9 11 10 12 from sas.qtgui.UI import main_resources_rc 11 13 import sas.qtgui.Utilities.GuiUtils as GuiUtils 12 14 13 from UI.SlitSizeCalculator import Ui_SlitSizeCalculator15 from .UI.SlitSizeCalculator import Ui_SlitSizeCalculator 14 16 from sas.sascalc.dataloader.loader import Loader 15 17 from sas.sascalc.calculator.slit_length_calculator import SlitlengthCalculator 16 18 17 19 18 class SlitSizeCalculator(Qt Gui.QDialog, Ui_SlitSizeCalculator):20 class SlitSizeCalculator(QtWidgets.QDialog, Ui_SlitSizeCalculator): 19 21 """ 20 22 Provides the slit length calculator GUI. … … 45 47 documentation tree (after /doc/ ....". 46 48 """ 47 try: 48 location = GuiUtils.HELP_DIRECTORY_LOCATION + \ 49 "/user/sasgui/perspectives/calculator/slit_calculator_help.html" 50 51 self._parent._helpView.load(QtCore.QUrl(location)) 52 self._parent._helpView.show() 53 except AttributeError: 54 # No manager defined - testing and standalone runs 55 pass 49 location = "/user/sasgui/perspectives/calculator/slit_calculator_help.html" 50 self._parent.showHelp(location) 56 51 57 52 def onBrowse(self): … … 63 58 return 64 59 loader = Loader() 65 data = loader.load(path_str)[0] 60 try: 61 data = loader.load(path_str) 62 data = data[0] 63 # Can return multiple exceptions - gather them all under one umbrella and complain 64 except Exception as ex: 65 logging.error(ex) 66 return 66 67 67 68 self.data_file.setText(os.path.basename(path_str)) … … 75 76 # Location is automatically saved - no need to keep track of the last dir 76 77 # But only with Qt built-in dialog (non-platform native) 77 path = QtGui.QFileDialog.getOpenFileName(self, "Choose a file", "", 78 "SAXSess 1D data (*.txt *.TXT *.dat *.DAT)", None, 79 QtGui.QFileDialog.DontUseNativeDialog) 80 81 if path is None: 82 return 83 84 if isinstance(path, QtCore.QString): 85 path = str(path) 86 78 path = QtWidgets.QFileDialog.getOpenFileName(self, "Choose a file", "", 79 "SAXSess 1D data (*.txt *.TXT *.dat *.DAT)", 80 None, 81 QtWidgets.QFileDialog.DontUseNativeDialog)[0] 87 82 return path 88 83 … … 107 102 self.clearResults() 108 103 msg = "ERROR: Data hasn't been loaded correctly" 109 raise RuntimeError, msg 104 logging.error(msg) 105 return 110 106 111 107 if data.__class__.__name__ == 'Data2D': 112 108 self.clearResults() 113 109 msg = "Slit Length cannot be computed for 2D Data" 114 raise RuntimeError, msg 110 logging.error(msg) 111 return 115 112 116 113 #compute the slit size … … 118 115 xdata = data.x 119 116 ydata = data.y 120 if xdata == [] or xdata is None or ydata == [] or ydata is None: 117 #if xdata == [] or xdata is None or ydata == [] or ydata is None: 118 if (not xdata or xdata is None) or (not ydata or ydata is None): 121 119 msg = "The current data is empty please check x and y" 122 raise ValueError, msg 120 logging.error(msg) 121 return 123 122 slit_length_calculator = SlitlengthCalculator() 124 123 slit_length_calculator.set_data(x=xdata, y=ydata) … … 126 125 except: 127 126 self.clearResults() 128 msg = "Slit Size Calculator: %s" % (sys.exc_value) 129 raise RuntimeError, msg 127 msg = "Slit Size Calculator: %s" % (sys.exc_info()[1]) 128 logging.error(msg) 129 return 130 130 131 131 slit_length_str = "{:.5f}".format(slit_length) -
src/sas/qtgui/Calculators/UnitTesting/DataOperationUtilityTest.py
r0c468bf re90988c 4 4 import logging 5 5 import unittest 6 from PyQt4 import QtGui 7 from PyQt4 import QtCore 8 from PyQt4.QtTest import QTest 9 from PyQt4.QtCore import Qt 10 from mock import MagicMock 11 from mock import patch 6 import webbrowser 7 8 from PyQt5 import QtGui, QtWidgets 9 from PyQt5 import QtCore 10 from PyQt5.QtTest import QTest 11 from PyQt5.QtCore import Qt 12 from unittest.mock import MagicMock 13 from unittest.mock import patch 12 14 13 15 from twisted.internet import threads … … 19 21 from sas.qtgui.MainWindow.DataState import DataState 20 22 21 if not Qt Gui.QApplication.instance():22 app = Qt Gui.QApplication(sys.argv)23 if not QtWidgets.QApplication.instance(): 24 app = QtWidgets.QApplication(sys.argv) 23 25 24 26 BG_COLOR_ERR = 'background-color: rgb(244, 170, 164);' … … 43 45 """Test the GUI in its default state""" 44 46 45 self.assertIsInstance(self.widget, Qt Gui.QDialog)47 self.assertIsInstance(self.widget, QtWidgets.QDialog) 46 48 47 49 self.assertEqual(self.widget.windowTitle(), "Data Operation") … … 98 100 self.assertFalse(self.widget.txtNumber.isEnabled()) 99 101 100 self.assertIsInstance(self.widget.layoutOutput,Qt Gui.QHBoxLayout)101 self.assertIsInstance(self.widget.layoutData1,Qt Gui.QHBoxLayout)102 self.assertIsInstance(self.widget.layoutData2,Qt Gui.QHBoxLayout)102 self.assertIsInstance(self.widget.layoutOutput,QtWidgets.QHBoxLayout) 103 self.assertIsInstance(self.widget.layoutData1,QtWidgets.QHBoxLayout) 104 self.assertIsInstance(self.widget.layoutData2,QtWidgets.QHBoxLayout) 103 105 104 106 # To store input datafiles … … 119 121 def testHelp(self): 120 122 """ Assure help file is shown """ 121 # this should not rise123 self.widget.manager.showHelp = MagicMock() 122 124 self.widget.onHelp() 125 self.assertTrue(self.widget.manager.showHelp.called_once()) 126 args = self.widget.manager.showHelp.call_args 127 self.assertIn('data_operator_help.html', args[0][0]) 123 128 124 129 def testOnReset(self): -
src/sas/qtgui/Calculators/UnitTesting/DensityCalculatorTest.py
r464cd07 re90988c 3 3 import webbrowser 4 4 5 from PyQt 4 import QtGui6 from PyQt 4.QtTest import QTest7 from PyQt 4import QtCore8 from mock import MagicMock5 from PyQt5 import QtGui, QtWidgets 6 from PyQt5.QtTest import QTest 7 from PyQt5 import QtCore 8 from unittest.mock import MagicMock 9 9 10 10 ####### TEMP … … 19 19 import sas.qtgui.Utilities.LocalConfig 20 20 21 if not Qt Gui.QApplication.instance():22 app = Qt Gui.QApplication(sys.argv)21 if not QtWidgets.QApplication.instance(): 22 app = QtWidgets.QApplication(sys.argv) 23 23 24 24 class ToMolarMassTest(unittest.TestCase): … … 45 45 self.widget = DensityPanel(None) 46 46 47 # temporarily set the text here 48 self.widget.ui.editMolecularFormula.setText("H2O") 49 47 50 def tearDown(self): 48 51 '''Destroy the DensityCalculator''' … … 52 55 def testDefaults(self): 53 56 '''Test the GUI in its default state''' 54 self.assertIsInstance(self.widget, Qt Gui.QWidget)57 self.assertIsInstance(self.widget, QtWidgets.QWidget) 55 58 self.assertEqual(self.widget.windowTitle(), "Density/Volume Calculator") 56 self.assertIsInstance(self.widget.ui.editMolecularFormula.validator(), FormulaValidator) 59 # temporarily commented out until FormulaValidator fixed for Qt5 60 #self.assertIsInstance(self.widget.ui.editMolecularFormula.validator(), FormulaValidator) 57 61 self.assertEqual(self.widget.ui.editMolecularFormula.styleSheet(), '') 58 62 self.assertEqual(self.widget.model.columnCount(), 1) 59 63 self.assertEqual(self.widget.model.rowCount(), 4) 60 self.assertEqual(self.widget.sizePolicy().Policy(), Qt Gui.QSizePolicy.Fixed)64 self.assertEqual(self.widget.sizePolicy().Policy(), QtWidgets.QSizePolicy.Fixed) 61 65 62 66 def testSimpleEntry(self): … … 71 75 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 72 76 QTest.qWait(100) 77 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 73 78 74 79 # Assure the mass density field is set … … 99 104 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 100 105 QTest.qWait(100) 106 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 101 107 102 108 # Assure the mass density field is set … … 115 121 def testHelp(self): 116 122 """ Assure help file is shown """ 117 118 # this should not rise123 self.widget.manager = QtWidgets.QWidget() 124 self.widget.manager.showHelp = MagicMock() 119 125 self.widget.displayHelp() 126 self.assertTrue(self.widget.manager.showHelp.called_once()) 127 args = self.widget.manager.showHelp.call_args 128 self.assertIn('density_calculator_help.html', args[0][0]) 120 129 121 130 if __name__ == "__main__": -
src/sas/qtgui/Calculators/UnitTesting/GenericScatteringCalculatorTest.py
rf4a1433 re90988c 3 3 import numpy 4 4 import unittest 5 from PyQt 4 import QtGui6 from PyQt 4.QtTest import QTest7 8 from PyQt 4.QtCore import Qt9 from mock import MagicMock10 from mock import patch5 from PyQt5 import QtGui, QtWidgets 6 from PyQt5.QtTest import QTest 7 8 from PyQt5.QtCore import Qt 9 from unittest.mock import MagicMock 10 from unittest.mock import patch 11 11 12 12 # set up import paths … … 15 15 from mpl_toolkits.mplot3d import Axes3D 16 16 from UnitTesting.TestUtils import QtSignalSpy 17 from matplotlib.backends.backend_qt 4agg import FigureCanvasQTAgg as FigureCanvas17 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 18 18 from sas.qtgui.Calculators.GenericScatteringCalculator import GenericScatteringCalculator 19 19 from sas.qtgui.Calculators.GenericScatteringCalculator import Plotter3D … … 24 24 from sas.sascalc.calculator import sas_gen 25 25 26 if not QtGui.QApplication.instance(): 27 app = QtGui.QApplication(sys.argv) 28 26 if not QtWidgets.QApplication.instance(): 27 app = QtWidgets.QApplication(sys.argv) 29 28 30 29 class GenericScatteringCalculatorTest(unittest.TestCase): … … 46 45 def testDefaults(self): 47 46 """Test the GUI in its default state""" 48 self.assertIsInstance(self.widget, Qt Gui.QWidget)47 self.assertIsInstance(self.widget, QtWidgets.QWidget) 49 48 self.assertEqual(self.widget.windowTitle(), "Generic SAS Calculator") 50 49 … … 105 104 def testHelpButton(self): 106 105 """ Assure help file is shown """ 106 self.widget.manager.showHelp = MagicMock() 107 107 self.widget.onHelp() 108 self.assertTrue(self.widget.manager.showHelp.called_once()) 109 args = self.widget.manager.showHelp.call_args 110 self.assertIn('sas_calculator_help.html', args[0][0]) 108 111 109 112 def testValidator(self): … … 175 178 """ 176 179 filename = os.path.join("UnitTesting", "sld_file.sld") 177 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)180 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, '']) 178 181 self.widget.loadFile() 179 182 … … 239 242 filename = os.path.join("UnitTesting", "diamdsml.pdb") 240 243 241 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)244 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, '']) 242 245 self.widget.loadFile() 243 246 … … 302 305 filename = os.path.join("UnitTesting", "A_Raw_Example-1.omf") 303 306 304 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)307 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, '']) 305 308 self.widget.loadFile() 306 309 self.assertEqual(self.widget.cmdLoad.text(), 'Loading...') … … 369 372 filename = os.path.join("UnitTesting", "diamdsml.pdb") 370 373 371 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)374 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, '']) 372 375 self.widget.loadFile() 373 376 time.sleep(1) … … 388 391 self.assertFalse(self.widget.cmdDraw.isEnabled()) 389 392 filename = os.path.join("UnitTesting", "diamdsml.pdb") 390 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)393 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename,'']) 391 394 self.widget.loadFile() 392 395 self.assertEqual(self.widget.cmdLoad.text(), 'Loading...') 393 396 time.sleep(1) 397 394 398 self.assertTrue(self.widget.cmdDraw.isEnabled()) 395 399 QTest.mouseClick(self.widget.cmdDraw, Qt.LeftButton) … … 408 412 filename = os.path.join("UnitTesting", "sld_file.sld") 409 413 410 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)414 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, '']) 411 415 self.widget.loadFile() 412 416 … … 414 418 415 419 filename1 = "test" 416 Qt Gui.QFileDialog.getSaveFileName = MagicMock(return_value=filename1)420 QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=[filename1, '']) 417 421 418 422 QTest.mouseClick(self.widget.cmdSave, Qt.LeftButton) -
src/sas/qtgui/Calculators/UnitTesting/KiessigCalculatorTest.py
r464cd07 re90988c 1 1 import sys 2 2 import unittest 3 from PyQt 4 import QtGui4 from PyQt 4.QtTest import QTest5 from PyQt 4.QtCore import Qt3 from PyQt5 import QtGui, QtWidgets 4 from PyQt5.QtTest import QTest 5 from PyQt5.QtCore import Qt 6 6 7 # TEMP 8 import sas.qtgui.path_prepare 9 7 import path_prepare 8 from unittest.mock import MagicMock 10 9 11 10 from sas.qtgui.Calculators.KiessigPanel import KiessigPanel 12 11 13 if not Qt Gui.QApplication.instance():14 app = Qt Gui.QApplication(sys.argv)12 if not QtWidgets.QApplication.instance(): 13 app = QtWidgets.QApplication(sys.argv) 15 14 16 15 … … 28 27 def testDefaults(self): 29 28 """Test the GUI in its default state""" 30 self.assertIsInstance(self.widget, Qt Gui.QWidget)29 self.assertIsInstance(self.widget, QtWidgets.QWidget) 31 30 self.assertEqual(self.widget.windowTitle(), "Kiessig Thickness Calculator") 32 self.assertEqual(self.widget.sizePolicy().Policy(), Qt Gui.QSizePolicy.Fixed)31 self.assertEqual(self.widget.sizePolicy().Policy(), QtWidgets.QSizePolicy.Fixed) 33 32 34 33 def testHelp(self): 35 34 """ Assure help file is shown """ 36 37 # this should not rise35 self.widget.manager = QtWidgets.QWidget() 36 self.widget.manager.showHelp = MagicMock() 38 37 self.widget.onHelp() 38 self.assertTrue(self.widget.manager.showHelp.called_once()) 39 args = self.widget.manager.showHelp.call_args 40 self.assertIn('kiessig_calculator_help.html', args[0][0]) 39 41 40 42 def testComplexEntryNumbers(self): -
src/sas/qtgui/Calculators/UnitTesting/ResolutionCalculatorPanelTest.py
r170e95d re90988c 4 4 import logging 5 5 import unittest 6 from PyQt4 import QtGui 7 from PyQt4 import QtCore 8 from PyQt4.QtTest import QTest 9 from PyQt4.QtCore import Qt 10 from mock import MagicMock 11 from mock import patch 6 from PyQt5 import QtGui, QtWidgets 7 from PyQt5 import QtCore 8 from PyQt5.QtTest import QTest 9 from PyQt5.QtCore import Qt 10 from unittest.mock import MagicMock 12 11 13 12 from twisted.internet import threads … … 28 27 29 28 30 if not Qt Gui.QApplication.instance():31 app = Qt Gui.QApplication(sys.argv)29 if not QtWidgets.QApplication.instance(): 30 app = QtWidgets.QApplication(sys.argv) 32 31 33 32 … … 48 47 """Test the GUI in its default state""" 49 48 50 self.assertIsInstance(self.widget, Qt Gui.QDialog)49 self.assertIsInstance(self.widget, QtWidgets.QDialog) 51 50 self.assertEqual(self.widget.windowTitle(), "Q Resolution Estimator") 52 51 # size … … 231 230 def testOnSelectCustomSpectrum(self): 232 231 """ Test Custom Spectrum: load file if 'Add New' """ 233 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=None)232 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=("","")) 234 233 self.widget.cbCustomSpectrum.setCurrentIndex(1) 235 234 236 235 # Test the getOpenFileName() dialog called once 237 self.assertTrue(Qt Gui.QFileDialog.getOpenFileName.called)238 Qt Gui.QFileDialog.getOpenFileName.assert_called_once()236 self.assertTrue(QtWidgets.QFileDialog.getOpenFileName.called) 237 QtWidgets.QFileDialog.getOpenFileName.assert_called_once() 239 238 240 239 def testHelp(self): 241 240 """ Assure help file is shown """ 242 241 # this should not rise 242 self.widget.manager = QtWidgets.QWidget() 243 self.widget.manager.showHelp = MagicMock() 243 244 self.widget.onHelp() 245 self.assertTrue(self.widget.manager.showHelp.called_once()) 246 args = self.widget.manager.showHelp.call_args 247 self.assertIn('resolution_calculator_help.html', args[0][0]) 244 248 245 249 def testOnReset(self): -
src/sas/qtgui/Calculators/UnitTesting/SLDCalculatorTest.py
rf4a1433 re90988c 3 3 import webbrowser 4 4 5 from PyQt 4 import QtGui6 from PyQt 4.QtTest import QTest7 from PyQt 4import QtCore8 from mock import MagicMock5 from PyQt5 import QtGui, QtWidgets 6 from PyQt5.QtTest import QTest 7 from PyQt5 import QtCore 8 from unittest.mock import MagicMock 9 9 10 10 ####### TEMP … … 20 20 import sas.qtgui.Utilities.LocalConfig 21 21 22 if not QtGui.QApplication.instance(): 23 app = QtGui.QApplication(sys.argv) 22 #if not QtWidgets.QApplication.instance(): 23 # app = QtWidgets.QApplication(sys.argv) 24 app = QtWidgets.QApplication(sys.argv) 24 25 25 26 class SldResultTest(unittest.TestCase): … … 75 76 def testDefaults(self): 76 77 '''Test the GUI in its default state''' 77 self.assertIsInstance(self.widget, QtGui.QWidget) 78 self.assertEqual(self.widget.windowTitle(), "SLD Calculator") 79 self.assertIsInstance(self.widget.ui.editMolecularFormula.validator(), FormulaValidator) 78 self.assertIsInstance(self.widget, QtWidgets.QWidget) 79 # temporarily commented out until FormulaValidator fixed for Qt5 80 # self.assertEqual(self.widget.windowTitle(), "SLD Calculator") 81 # self.assertIsInstance(self.widget.ui.editMolecularFormula.validator(), FormulaValidator) 80 82 self.assertEqual(self.widget.ui.editMolecularFormula.styleSheet(), '') 81 83 self.assertEqual(self.widget.model.columnCount(), 1) 82 84 self.assertEqual(self.widget.model.rowCount(), 12) 83 self.assertEqual(self.widget.sizePolicy().Policy(), Qt Gui.QSizePolicy.Fixed)85 self.assertEqual(self.widget.sizePolicy().Policy(), QtWidgets.QSizePolicy.Fixed) 84 86 85 87 def testSimpleEntry(self): … … 94 96 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 95 97 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 96 Qt Gui.qApp.processEvents()98 QtWidgets.qApp.processEvents() 97 99 QTest.qWait(100) 98 100 … … 107 109 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 108 110 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 109 Qt Gui.qApp.processEvents()111 QtWidgets.qApp.processEvents() 110 112 QTest.qWait(100) 111 113 … … 126 128 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 127 129 QTest.qWait(100) 130 QTest.keyEvent(QTest.Press, self.widget, key, QtCore.Qt.NoModifier) 128 131 129 132 # Assure the mass density field is set … … 139 142 def testHelp(self): 140 143 """ Assure help file is shown """ 141 142 # this should not rise144 self.widget.manager = QtWidgets.QWidget() 145 self.widget.manager.showHelp = MagicMock() 143 146 self.widget.displayHelp() 147 self.assertTrue(self.widget.manager.showHelp.called_once()) 148 args = self.widget.manager.showHelp.call_args 149 self.assertIn('sld_calculator_help.html', args[0][0]) 144 150 145 151 if __name__ == "__main__": -
src/sas/qtgui/Calculators/UnitTesting/SlitSizeCalculatorTest.py
rf4a1433 re90988c 1 1 import sys 2 2 import unittest 3 from PyQt4 import QtGui 4 from PyQt4.QtTest import QTest 5 from PyQt4.QtCore import Qt 6 from mock import MagicMock 3 import logging 4 5 from PyQt5 import QtGui, QtWidgets 6 from PyQt5.QtTest import QTest 7 from PyQt5.QtCore import Qt 8 from unittest.mock import MagicMock 7 9 8 10 # set up import paths … … 12 14 from sas.sascalc.dataloader.loader import Loader 13 15 14 if not Qt Gui.QApplication.instance():15 app = Qt Gui.QApplication(sys.argv)16 if not QtWidgets.QApplication.instance(): 17 app = QtWidgets.QApplication(sys.argv) 16 18 17 19 … … 29 31 def testDefaults(self): 30 32 """Test the GUI in its default state""" 31 self.assertIsInstance(self.widget, Qt Gui.QWidget)33 self.assertIsInstance(self.widget, QtWidgets.QWidget) 32 34 self.assertEqual(self.widget.windowTitle(), "Slit Size Calculator") 33 self.assertEqual(self.widget.sizePolicy().Policy(), Qt Gui.QSizePolicy.Fixed)35 self.assertEqual(self.widget.sizePolicy().Policy(), QtWidgets.QSizePolicy.Fixed) 34 36 35 37 def testHelp(self): 36 38 """ Assure help file is shown """ 37 38 # this should not rise39 self.widget._parent = QtWidgets.QWidget() 40 self.widget._parent.showHelp = MagicMock() 39 41 self.widget.onHelp() 42 self.assertTrue(self.widget._parent.showHelp.called_once()) 43 args = self.widget._parent.showHelp.call_args 44 self.assertIn('slit_calculator_help.html', args[0][0]) 40 45 41 46 def testBrowseButton(self): … … 45 50 46 51 # Return no files. 47 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=None)52 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=('','')) 48 53 49 54 # Click on the Browse button … … 51 56 52 57 # Test the getOpenFileName() dialog called once 53 self.assertTrue(Qt Gui.QFileDialog.getOpenFileName.called)54 Qt Gui.QFileDialog.getOpenFileName.assert_called_once()58 self.assertTrue(QtWidgets.QFileDialog.getOpenFileName.called) 59 QtWidgets.QFileDialog.getOpenFileName.assert_called_once() 55 60 56 61 # Now, return a single file 57 Qt Gui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)62 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=(filename,'')) 58 63 59 64 # Click on the Load button 60 65 QTest.mouseClick(browseButton, Qt.LeftButton) 61 Qt Gui.qApp.processEvents()66 QtWidgets.qApp.processEvents() 62 67 63 68 # Test the getOpenFileName() dialog called once 64 self.assertTrue(Qt Gui.QFileDialog.getOpenFileName.called)65 Qt Gui.QFileDialog.getOpenFileName.assert_called_once()69 self.assertTrue(QtWidgets.QFileDialog.getOpenFileName.called) 70 QtWidgets.QFileDialog.getOpenFileName.assert_called_once() 66 71 67 72 … … 81 86 """ Test on wrong input data """ 82 87 83 filename = " P123_D2O_10_percent.dat"88 filename = "Dec07031.ASC" 84 89 loader = Loader() 85 90 data = loader.load(filename)[0] 86 self.assertRaisesRegexp(RuntimeError, 87 "Slit Length cannot be computed for 2D Data", 88 self.widget.calculateSlitSize, data) 91 92 logging.error = MagicMock() 93 94 self.widget.calculateSlitSize(data) 95 96 self.assertTrue(logging.error.called_once()) 89 97 90 98 data = None 91 self.assertRaisesRegexp(RuntimeError, 92 "ERROR: Data hasn't been loaded correctly", 93 self.widget.calculateSlitSize, data) 99 self.widget.calculateSlitSize(data) 100 self.assertTrue(logging.error.call_count == 2) 94 101 95 102 -
src/sas/qtgui/GUITests.py
rf4a1433 rda9a0722 1 1 import unittest 2 2 import sys 3 from PyQt4 import QtGui 3 from PyQt5 import QtGui 4 from PyQt5 import QtWidgets 4 5 5 6 # Prepare the general QApplication instance 6 app = Qt Gui.QApplication(sys.argv)7 app = QtWidgets.QApplication(sys.argv) 7 8 8 9 # Main Window … … 14 15 from MainWindow.UnitTesting import MainWindowTest 15 16 16 # Plotting17 ## Plotting 17 18 from Plotting.UnitTesting import AddTextTest 18 19 from Plotting.UnitTesting import PlotHelperTest 19 from Plotting.UnitTesting import PlotterBaseTest 20 from Plotting.UnitTesting import PlotterTest 21 from Plotting.UnitTesting import Plotter2DTest 20 from Plotting.UnitTesting import WindowTitleTest 22 21 from Plotting.UnitTesting import ScalePropertiesTest 23 from Plotting.UnitTesting import WindowTitleTest24 22 from Plotting.UnitTesting import SetGraphRangeTest 25 23 from Plotting.UnitTesting import LinearFitTest … … 30 28 from Plotting.UnitTesting import SlicerModelTest 31 29 from Plotting.UnitTesting import SlicerParametersTest 30 from Plotting.UnitTesting import PlotterBaseTest 31 from Plotting.UnitTesting import PlotterTest 32 from Plotting.UnitTesting import Plotter2DTest 32 33 33 34 # Calculators … … 48 49 49 50 # Perspectives 50 import path_prepare 51 # Fitting 51 52 from Perspectives.Fitting.UnitTesting import FittingWidgetTest 52 53 from Perspectives.Fitting.UnitTesting import FittingPerspectiveTest … … 55 56 from Perspectives.Fitting.UnitTesting import FitPageTest 56 57 from Perspectives.Fitting.UnitTesting import FittingOptionsTest 58 from Perspectives.Fitting.UnitTesting import MultiConstraintTest 59 from Perspectives.Fitting.UnitTesting import ComplexConstraintTest 60 from Perspectives.Fitting.UnitTesting import ConstraintWidgetTest 61 62 # Invariant 63 from Perspectives.Invariant.UnitTesting import InvariantPerspectiveTest 64 65 # Inversion 66 from Perspectives.Inversion.UnitTesting import InversionPerspectiveTest 57 67 58 68 def suite(): 59 69 suites = ( 60 70 # Plotting 71 unittest.makeSuite(Plotter2DTest.Plotter2DTest, 'test'), 61 72 unittest.makeSuite(PlotHelperTest.PlotHelperTest, 'test'), 62 unittest.makeSuite( PlotterTest.PlotterTest, 'test'),73 unittest.makeSuite(AddTextTest.AddTextTest, 'test'), 63 74 unittest.makeSuite(WindowTitleTest.WindowTitleTest, 'test'), 64 unittest.makeSuite(PlotterBaseTest.PlotterBaseTest, 'test'),65 unittest.makeSuite(Plotter2DTest.Plotter2DTest, 'test'),66 unittest.makeSuite(AddTextTest.AddTextTest, 'test'),67 75 unittest.makeSuite(ScalePropertiesTest.ScalePropertiesTest, 'test'), 68 76 unittest.makeSuite(SetGraphRangeTest.SetGraphRangeTest, 'test'), … … 74 82 unittest.makeSuite(SlicerModelTest.SlicerModelTest, 'test'), 75 83 unittest.makeSuite(SlicerParametersTest.SlicerParametersTest, 'test'), 84 unittest.makeSuite(PlotterBaseTest.PlotterBaseTest, 'test'), 85 unittest.makeSuite(PlotterTest.PlotterTest, 'test'), 76 86 77 87 # Main window 78 88 unittest.makeSuite(DataExplorerTest.DataExplorerTest, 'test'), 89 unittest.makeSuite(DroppableDataLoadWidgetTest.DroppableDataLoadWidgetTest, 'test'), 90 unittest.makeSuite(MainWindowTest.MainWindowTest, 'test'), 79 91 unittest.makeSuite(GuiManagerTest.GuiManagerTest, 'test'), 80 unittest.makeSuite(GuiUtilsTest.GuiUtilsTest, 'test'),81 92 unittest.makeSuite(AboutBoxTest.AboutBoxTest, 'test'), 82 93 unittest.makeSuite(WelcomePanelTest.WelcomePanelTest, 'test'), 83 unittest.makeSuite(DroppableDataLoadWidgetTest.DroppableDataLoadWidgetTest, 'test'),84 unittest.makeSuite(MainWindowTest.MainWindowTest, 'test'),85 94 86 95 # Utilities 87 unittest.makeSuite(TestUtilsTest.TestUtilsTest, 'test'), 88 unittest.makeSuite(SasviewLoggerTest.SasviewLoggerTest, 'test'), 96 unittest.makeSuite(TestUtilsTest.TestUtilsTest, 'test'), 97 unittest.makeSuite(SasviewLoggerTest.SasviewLoggerTest, 'test'), 98 unittest.makeSuite(GuiUtilsTest.GuiUtilsTest, 'test'), 99 unittest.makeSuite(GuiUtilsTest.DoubleValidatorTest, 'test'), 100 unittest.makeSuite(GuiUtilsTest.HashableStandardItemTest, 'test'), 89 101 90 102 # Calculators … … 98 110 99 111 # Perspectives 112 # Fitting 100 113 unittest.makeSuite(FittingPerspectiveTest.FittingPerspectiveTest, 'test'), 101 114 unittest.makeSuite(FittingWidgetTest.FittingWidgetTest, 'test'), … … 104 117 unittest.makeSuite(FitPageTest.FitPageTest, 'test'), 105 118 unittest.makeSuite(FittingOptionsTest.FittingOptionsTest, 'test'), 106 ) 119 unittest.makeSuite(MultiConstraintTest.MultiConstraintTest, 'test'), 120 unittest.makeSuite(ConstraintWidgetTest.ConstraintWidgetTest, 'test'), 121 unittest.makeSuite(ComplexConstraintTest.ComplexConstraintTest, 'test'), 122 123 # Invariant 124 unittest.makeSuite(InvariantPerspectiveTest.InvariantPerspectiveTest, 'test'), 125 # Inversion 126 unittest.makeSuite(InversionPerspectiveTest.InversionTest, 'test'), 127 ) 107 128 return unittest.TestSuite(suites) 108 129 -
src/sas/qtgui/MainWindow/AboutBox.py
rcd2cc745 r4992ff2 1 1 import functools 2 from PyQt 4 import QtGui2 from PyQt5 import QtWidgets 3 3 4 4 import sas.sasview … … 8 8 from sas.qtgui.UI import main_resources_rc 9 9 10 from UI.AboutUI import Ui_AboutUI10 from .UI.AboutUI import Ui_AboutUI 11 11 12 class AboutBox(Qt Gui.QDialog, Ui_AboutUI):12 class AboutBox(QtWidgets.QDialog, Ui_AboutUI): 13 13 def __init__(self, parent=None): 14 14 super(AboutBox, self).__init__(parent) -
src/sas/qtgui/MainWindow/DataExplorer.py
r88e1f57 re90988c 5 5 import logging 6 6 7 from PyQt4 import QtCore 8 from PyQt4 import QtGui 9 from PyQt4 import QtWebKit 10 from PyQt4.Qt import QMutex 7 from PyQt5 import QtCore 8 from PyQt5 import QtGui 9 from PyQt5 import QtWidgets 11 10 12 11 from twisted.internet import threads … … 30 29 import sas.qtgui.Perspectives as Perspectives 31 30 31 DEFAULT_PERSPECTIVE = "Fitting" 32 32 33 class DataExplorerWindow(DroppableDataLoadWidget): 33 34 # The controller which is responsible for managing signal slots connections … … 48 49 self.loader = Loader() 49 50 self.manager = manager if manager is not None else DataManager() 50 self.txt_widget = Qt Gui.QTextEdit(None)51 self.txt_widget = QtWidgets.QTextEdit(None) 51 52 52 53 # Be careful with twisted threads. 53 self.mutex = Q Mutex()54 self.mutex = QtCore.QMutex() 54 55 55 56 # Active plots … … 68 69 self.cmdHelp_2.clicked.connect(self.displayHelp) 69 70 70 # Display HTML content71 self._helpView = QtWebKit.QWebView()72 73 71 # Fill in the perspectives combo 74 72 self.initPerspectives() … … 98 96 99 97 # Proxy model for showing a subset of Data1D/Data2D content 100 self.data_proxy = Qt Gui.QSortFilterProxyModel(self)98 self.data_proxy = QtCore.QSortFilterProxyModel(self) 101 99 self.data_proxy.setSourceModel(self.model) 102 100 … … 108 106 109 107 # Proxy model for showing a subset of Theory content 110 self.theory_proxy = Qt Gui.QSortFilterProxyModel(self)108 self.theory_proxy = QtCore.QSortFilterProxyModel(self) 111 109 self.theory_proxy.setSourceModel(self.theory_model) 112 110 … … 139 137 Show the "Loading data" section of help 140 138 """ 141 tree_location = GuiUtils.HELP_DIRECTORY_LOCATION +\ 142 "/user/sasgui/guiframe/data_explorer_help.html" 143 self._helpView.load(QtCore.QUrl(tree_location)) 144 self._helpView.show() 139 tree_location = "/user/sasgui/guiframe/data_explorer_help.html" 140 self.parent.showHelp(tree_location) 145 141 146 142 def enableGraphCombo(self, combo_text): … … 155 151 Populate the Perspective combobox and define callbacks 156 152 """ 157 available_perspectives = sorted([p for p in Perspectives.PERSPECTIVES.keys()])153 available_perspectives = sorted([p for p in list(Perspectives.PERSPECTIVES.keys())]) 158 154 if available_perspectives: 159 155 self.cbFitting.clear() … … 161 157 self.cbFitting.currentIndexChanged.connect(self.updatePerspectiveCombo) 162 158 # Set the index so we see the default (Fitting) 163 self. updatePerspectiveCombo(0)159 self.cbFitting.setCurrentIndex(self.cbFitting.findText(DEFAULT_PERSPECTIVE)) 164 160 165 161 def _perspective(self): … … 175 171 load_thread = threads.deferToThread(self.readData, url) 176 172 load_thread.addCallback(self.loadComplete) 173 load_thread.addErrback(self.loadFailed) 177 174 178 175 def loadFile(self, event=None): … … 191 188 Opens the Qt "Open Folder..." dialog 192 189 """ 193 folder = Qt Gui.QFileDialog.getExistingDirectory(self, "Choose a directory", "",194 Qt Gui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontUseNativeDialog)190 folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Choose a directory", "", 191 QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog) 195 192 if folder is None: 196 193 return … … 215 212 'caption' : 'Open Project', 216 213 'filter' : 'Project (*.json);;All files (*.*)', 217 'options' : Qt Gui.QFileDialog.DontUseNativeDialog214 'options' : QtWidgets.QFileDialog.DontUseNativeDialog 218 215 } 219 filename = str(QtGui.QFileDialog.getOpenFileName(**kwargs))216 filename = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0] 220 217 if filename: 221 218 load_thread = threads.deferToThread(self.readProject, filename) 222 219 load_thread.addCallback(self.readProjectComplete) 220 load_thread.addErrback(self.readProjectFailed) 221 222 def loadFailed(self, reason): 223 """ 224 """ 225 print("file load FAILED: ", reason) 226 pass 227 228 def readProjectFailed(self, reason): 229 """ 230 """ 231 print("readProjectFailed FAILED: ", reason) 232 pass 223 233 224 234 def readProject(self, filename): … … 240 250 241 251 self.manager.assign(manager) 242 for id, item in self.manager.get_all_data().iteritems(): 252 self.model.beginResetModel() 253 for id, item in self.manager.get_all_data().items(): 243 254 self.updateModel(item.data, item.path) 244 255 245 self.model. reset()256 self.model.endResetModel() 246 257 247 258 def saveProject(self): … … 253 264 'caption' : 'Save Project', 254 265 'filter' : 'Project (*.json)', 255 'options' : Qt Gui.QFileDialog.DontUseNativeDialog266 'options' : QtWidgets.QFileDialog.DontUseNativeDialog 256 267 } 257 filename = str(QtGui.QFileDialog.getSaveFileName(**kwargs)) 268 name_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 269 filename = name_tuple[0] 258 270 if filename: 271 _, extension = os.path.splitext(filename) 272 if not extension: 273 filename = '.'.join((filename, 'json')) 259 274 self.communicator.statusBarUpdateSignal.emit("Saving Project... %s\n" % os.path.basename(filename)) 260 275 with open(filename, 'w') as outfile: … … 268 283 delete_msg = "This operation will delete the checked data sets and all the dependents." +\ 269 284 "\nDo you want to continue?" 270 reply = Qt Gui.QMessageBox.question(self,285 reply = QtWidgets.QMessageBox.question(self, 271 286 'Warning', 272 287 delete_msg, 273 Qt Gui.QMessageBox.Yes,274 Qt Gui.QMessageBox.No)275 276 if reply == Qt Gui.QMessageBox.No:288 QtWidgets.QMessageBox.Yes, 289 QtWidgets.QMessageBox.No) 290 291 if reply == QtWidgets.QMessageBox.No: 277 292 return 278 293 … … 308 323 delete_msg = "This operation will delete the checked data sets and all the dependents." +\ 309 324 "\nDo you want to continue?" 310 reply = Qt Gui.QMessageBox.question(self,325 reply = QtWidgets.QMessageBox.question(self, 311 326 'Warning', 312 327 delete_msg, 313 Qt Gui.QMessageBox.Yes,314 Qt Gui.QMessageBox.No)315 316 if reply == Qt Gui.QMessageBox.No:328 QtWidgets.QMessageBox.Yes, 329 QtWidgets.QMessageBox.No) 330 331 if reply == QtWidgets.QMessageBox.No: 317 332 return 318 333 … … 345 360 # Figure out which rows are checked 346 361 selected_items = [self.model.item(index) 347 for index in xrange(self.model.rowCount())362 for index in range(self.model.rowCount()) 348 363 if isItemReady(index)] 349 364 … … 354 369 if len(selected_items) > 1 and not self._perspective().allowBatch(): 355 370 msg = self._perspective().title() + " does not allow multiple data." 356 msgbox = Qt Gui.QMessageBox()357 msgbox.setIcon(Qt Gui.QMessageBox.Critical)371 msgbox = QtWidgets.QMessageBox() 372 msgbox.setIcon(QtWidgets.QMessageBox.Critical) 358 373 msgbox.setText(msg) 359 msgbox.setStandardButtons(Qt Gui.QMessageBox.Ok)374 msgbox.setStandardButtons(QtWidgets.QMessageBox.Ok) 360 375 retval = msgbox.exec_() 361 376 return … … 382 397 if outer_item.isCheckable() and \ 383 398 outer_item.checkState() == QtCore.Qt.Checked: 399 self.model.beginResetModel() 384 400 theories_copied += 1 385 401 new_item = self.recursivelyCloneItem(outer_item) … … 389 405 new_item.setText(new_name) 390 406 self.model.appendRow(new_item) 391 self.model.reset() 407 self.model.endResetModel() 408 #self.model.reset() 392 409 393 410 freeze_msg = "" … … 400 417 else: 401 418 freeze_msg = "Unexpected number of theories copied: %i" % theories_copied 402 raise AttributeError , freeze_msg419 raise AttributeError(freeze_msg) 403 420 self.communicator.statusBarUpdateSignal.emit(freeze_msg) 404 421 # Actively switch tabs … … 411 428 new_item = item.clone() 412 429 # clone doesn't do deepcopy :( 413 for child_index in xrange(item.rowCount()):430 for child_index in range(item.rowCount()): 414 431 child_item = self.recursivelyCloneItem(item.child(child_index)) 415 432 new_item.setChild(child_index, child_item) … … 435 452 return 436 453 new_plots = [PlotHelper.plotById(plot) for plot in graph_list] 437 active_plots_copy = self.active_plots.keys()454 active_plots_copy = list(self.active_plots.keys()) 438 455 for plot in active_plots_copy: 439 456 if self.active_plots[plot] in new_plots: … … 478 495 for plot in plots: 479 496 plot_id = plot.id 480 if plot_id in self.active_plots.keys():497 if plot_id in list(self.active_plots.keys()): 481 498 self.active_plots[plot_id].replacePlot(plot_id, plot) 482 499 else: … … 530 547 else: 531 548 msg = "Incorrect data type passed to Plotting" 532 raise AttributeError , msg549 raise AttributeError(msg) 533 550 534 551 if 'new_plot' in locals() and \ … … 561 578 562 579 # Add the plot to the workspace 563 self.parent.workspace().add Window(new_plot)580 self.parent.workspace().addSubWindow(new_plot) 564 581 565 582 # Show the plot 566 583 new_plot.show() 584 new_plot.canvas.draw() 567 585 568 586 # Update the active chart list … … 597 615 598 616 id = data.id 599 if data.id in self.active_plots.keys():617 if data.id in list(self.active_plots.keys()): 600 618 self.active_plots[id].replacePlot(id, data) 601 619 … … 609 627 # Location is automatically saved - no need to keep track of the last dir 610 628 # But only with Qt built-in dialog (non-platform native) 611 paths = Qt Gui.QFileDialog.getOpenFileNames(self, "Choose a file", "",612 wlist, None, Qt Gui.QFileDialog.DontUseNativeDialog)613 if paths is None:629 paths = QtWidgets.QFileDialog.getOpenFileNames(self, "Choose a file", "", 630 wlist, None, QtWidgets.QFileDialog.DontUseNativeDialog)[0] 631 if not paths: 614 632 return 615 616 if isinstance(paths, QtCore.QStringList):617 paths = [str(f) for f in paths]618 633 619 634 if not isinstance(paths, list): … … 673 688 self.mutex.lock() 674 689 self.updateModel(new_data, p_file) 675 self.model.reset()676 Qt Gui.qApp.processEvents()690 #self.model.reset() 691 QtWidgets.QApplication.processEvents() 677 692 self.mutex.unlock() 678 693 … … 687 702 688 703 except Exception as ex: 689 logging.error(sys.exc_ value)704 logging.error(sys.exc_info()[1]) 690 705 691 706 any_error = True … … 747 762 if not isinstance(index, int): 748 763 msg = "Incorrect type passed to DataExplorer.selectData()" 749 raise AttributeError , msg764 raise AttributeError(msg) 750 765 751 766 # Respond appropriately … … 773 788 except AttributeError: 774 789 msg = "Bad structure of the data model." 775 raise RuntimeError , msg790 raise RuntimeError(msg) 776 791 777 792 if is1D: … … 787 802 except AttributeError: 788 803 msg = "Bad structure of the data model." 789 raise RuntimeError , msg804 raise RuntimeError(msg) 790 805 791 806 if item.isCheckable() and item.checkState() == QtCore.Qt.Checked and is1D: … … 801 816 except AttributeError: 802 817 msg = "Bad structure of the data model." 803 raise RuntimeError , msg818 raise RuntimeError(msg) 804 819 805 820 if is2D: … … 815 830 except AttributeError: 816 831 msg = "Bad structure of the data model." 817 raise RuntimeError , msg832 raise RuntimeError(msg) 818 833 819 834 if item.isCheckable() and item.checkState() == QtCore.Qt.Checked and is2D: … … 823 838 msg = "Incorrect value in the Selection Option" 824 839 # Change this to a proper logging action 825 raise Exception , msg840 raise Exception(msg) 826 841 827 842 def contextMenu(self): … … 830 845 """ 831 846 # Create a custom menu based on actions defined in the UI file 832 self.context_menu = Qt Gui.QMenu(self)847 self.context_menu = QtWidgets.QMenu(self) 833 848 self.context_menu.addAction(self.actionDataInfo) 834 849 self.context_menu.addAction(self.actionSaveAs) … … 837 852 self.context_menu.addAction(self.actionQuick3DPlot) 838 853 self.context_menu.addAction(self.actionEditMask) 854 self.context_menu.addSeparator() 855 self.context_menu.addAction(self.actionDelete) 856 839 857 840 858 # Define the callbacks … … 844 862 self.actionQuick3DPlot.triggered.connect(self.quickData3DPlot) 845 863 self.actionEditMask.triggered.connect(self.showEditDataMask) 864 self.actionDelete.triggered.connect(self.deleteItem) 846 865 847 866 def onCustomContextMenu(self, position): … … 894 913 # Move the slider all the way up, if present 895 914 vertical_scroll_bar = self.txt_widget.verticalScrollBar() 896 vertical_scroll_bar.triggerAction(Qt Gui.QScrollBar.SliderToMinimum)915 vertical_scroll_bar.triggerAction(QtWidgets.QScrollBar.SliderToMinimum) 897 916 898 917 def saveDataAs(self): … … 975 994 mask_editor.exec_() 976 995 996 def deleteItem(self): 997 """ 998 Delete the current item 999 """ 1000 # Assure this is indeed wanted 1001 delete_msg = "This operation will delete the selected data sets." +\ 1002 "\nDo you want to continue?" 1003 reply = QtWidgets.QMessageBox.question(self, 1004 'Warning', 1005 delete_msg, 1006 QtWidgets.QMessageBox.Yes, 1007 QtWidgets.QMessageBox.No) 1008 1009 if reply == QtWidgets.QMessageBox.No: 1010 return 1011 1012 indices = self.current_view.selectedIndexes() 1013 proxy = self.current_view.model() 1014 model = proxy.sourceModel() 1015 1016 for index in indices: 1017 row_index = proxy.mapToSource(index) 1018 item_to_delete = model.itemFromIndex(row_index) 1019 if item_to_delete and item_to_delete.isCheckable(): 1020 row = row_index.row() 1021 if item_to_delete.parent(): 1022 # We have a child item - delete from it 1023 item_to_delete.parent().removeRow(row) 1024 else: 1025 # delete directly from model 1026 model.removeRow(row) 1027 pass 1028 977 1029 def loadComplete(self, output): 978 1030 """ … … 982 1034 983 1035 # Reset the model so the view gets updated. 984 self.model.reset()1036 #self.model.reset() 985 1037 self.communicator.progressBarUpdateSignal.emit(-1) 986 1038 … … 991 1043 self.communicator.fileDataReceivedSignal.emit(output_data) 992 1044 self.manager.add_data(data_list=output_data) 1045 1046 def loadFailed(self, reason): 1047 print("File Load Failed with:\n", reason) 1048 pass 993 1049 994 1050 def updateModel(self, data, p_file): … … 1009 1065 1010 1066 # Top-level item: checkbox with label 1011 checkbox_item = QtGui.QStandardItem(True)1067 checkbox_item = GuiUtils.HashableStandardItem() 1012 1068 checkbox_item.setCheckable(True) 1013 1069 checkbox_item.setCheckState(QtCore.Qt.Checked) … … 1015 1071 1016 1072 # Add the actual Data1D/Data2D object 1017 object_item = QtGui.QStandardItem()1018 object_item.setData( QtCore.QVariant(data))1073 object_item = GuiUtils.HashableStandardItem() 1074 object_item.setData(data) 1019 1075 1020 1076 checkbox_item.setChild(0, object_item) … … 1030 1086 1031 1087 # New row in the model 1088 self.model.beginResetModel() 1032 1089 self.model.appendRow(checkbox_item) 1090 self.model.endResetModel() 1033 1091 1034 1092 def updateModelFromPerspective(self, model_item): … … 1040 1098 if not isinstance(model_item, QtGui.QStandardItem): 1041 1099 msg = "Wrong data type returned from calculations." 1042 raise AttributeError , msg1100 raise AttributeError(msg) 1043 1101 1044 1102 # TODO: Assert other properties 1045 1103 1046 1104 # Reset the view 1047 self.model.reset()1105 ##self.model.reset() 1048 1106 # Pass acting as a debugger anchor 1049 1107 pass … … 1057 1115 if not isinstance(model_item, QtGui.QStandardItem): 1058 1116 msg = "Wrong data type returned from calculations." 1059 raise AttributeError , msg1117 raise AttributeError(msg) 1060 1118 1061 1119 # Check if there are any other items for this tab 1062 1120 # If so, delete them 1063 1121 # TODO: fix this to resemble GuiUtils.updateModelItemWithPlot 1064 # 1065 current_tab_name = model_item.text()[:2] 1066 for current_index in xrange(self.theory_model.rowCount()): 1067 if current_tab_name in self.theory_model.item(current_index).text(): 1068 self.theory_model.removeRow(current_index) 1069 break 1070 1071 # Reset the view 1072 self.model.reset() 1122 # 1123 ##self.model.beginResetModel() 1124 ##current_tab_name = model_item.text()[:2] 1125 ##for current_index in range(self.theory_model.rowCount()): 1126 #if current_tab_name in self.theory_model.item(current_index).text(): 1127 # return 1128 ## self.theory_model.removeRow(current_index) 1129 ## break 1130 1131 ### Reset the view 1132 ##self.model.endResetModel() 1073 1133 1074 1134 # Reset the view … … 1080 1140 1081 1141 if __name__ == "__main__": 1082 app = Qt Gui.QApplication([])1142 app = QtWidgets.QApplication([]) 1083 1143 dlg = DataExplorerWindow() 1084 1144 dlg.show() -
src/sas/qtgui/MainWindow/DataManager.py
- Property mode changed from 100644 to 100755
rf4a1433 r0261bc1 24 24 import json 25 25 import time 26 from StringIOimport StringIO26 from io import StringIO 27 27 import numpy as np 28 28 … … 66 66 _str += "No of states is %s \n" % str(len(self.stored_data)) 67 67 n_count = 0 68 for value in self.stored_data.values():68 for value in list(self.stored_data.values()): 69 69 n_count += 1 70 70 _str += "State No %s \n" % str(n_count) … … 126 126 rename data 127 127 """ 128 ## name of the data allow to differentiate data when plotted 129 name = GuiUtils.parseName(name=name, expression="_") 128 # name of the data allow to differentiate data when plotted 129 try: 130 name = GuiUtils.parseName(name=name, expression="_") 131 except TypeError: 132 # bad name sent to rename 133 return None 130 134 131 135 max_char = name.find("[") … … 146 150 receive a list of 147 151 """ 148 for id, data in data_list.ite ritems():152 for id, data in data_list.items(): 149 153 if id in self.stored_data: 150 154 msg = "Data manager already stores %s" % str(data.name) … … 162 166 """ 163 167 """ 164 if prev_data.id not in self.stored_data.keys():168 if prev_data.id not in list(self.stored_data.keys()): 165 169 return None, {} 166 170 data_state = self.stored_data[prev_data.id] 167 171 self.stored_data[new_data.id] = data_state.clone() 168 172 self.stored_data[new_data.id].data = new_data 169 if prev_data.id in self.stored_data.keys():173 if prev_data.id in list(self.stored_data.keys()): 170 174 del self.stored_data[prev_data.id] 171 175 return prev_data.id, {new_data.id: self.stored_data[new_data.id]} … … 177 181 if data_id is None and theory is not None: 178 182 uid = theory.id 179 if uid in self.stored_data.keys():183 if uid in list(self.stored_data.keys()): 180 184 data_state = self.stored_data[uid] 181 185 else: … … 207 211 if search_id == d_id: 208 212 _selected_data[search_id] = data 209 if search_id in theory_list.keys():213 if search_id in list(theory_list.keys()): 210 214 _selected_theory_list[search_id] = theory_list[search_id] 211 215 … … 216 220 """ 217 221 """ 218 return self.freeze_theory( self.stored_data.keys(), theory_id)222 return self.freeze_theory(list(self.stored_data.keys()), theory_id) 219 223 220 224 def freeze_theory(self, data_id, theory_id): … … 227 231 theory_list = data_state.get_theory() 228 232 for t_id in theory_id: 229 if t_id in theory_list.keys():233 if t_id in list(theory_list.keys()): 230 234 theory_data, theory_state = theory_list[t_id] 231 235 new_theory = copy.deepcopy(theory_data) … … 247 251 """ 248 252 for d_id in data_id: 249 if d_id in self.stored_data.keys():253 if d_id in list(self.stored_data.keys()): 250 254 data_state = self.stored_data[d_id] 251 255 if data_state.data.name in self.data_name_dict: … … 265 269 data_state = self.stored_data[d_id] 266 270 theory_list = data_state.get_theory() 267 if theory_id in theory_list.keys():271 if theory_id in list(theory_list.keys()): 268 272 del theory_list[theory_id] 269 273 #del pure theory … … 284 288 _selected_data = {} 285 289 for selected_name in name_list: 286 for id, data_state in self.stored_data.ite ritems():290 for id, data_state in self.stored_data.items(): 287 291 if data_state.data.name == selected_name: 288 292 _selected_data[id] = data_state.data … … 294 298 """ 295 299 for selected_name in name_list: 296 for id, data_state in self.stored_data.ite ritems():300 for id, data_state in self.stored_data.items(): 297 301 if data_state.data.name == selected_name: 298 302 del self.stored_data[id] … … 303 307 # Take the copy of current, possibly shorter stored_data dict 304 308 stored_data = copy.deepcopy(self.stored_data) 305 for idx in stored_data.keys():309 for idx in list(stored_data.keys()): 306 310 if str(selected_name) in str(idx): 307 311 del self.stored_data[idx] … … 313 317 _selected_data_state = {} 314 318 for id in data_id: 315 if id in self.stored_data.keys():319 if id in list(self.stored_data.keys()): 316 320 _selected_data_state[id] = self.stored_data[id] 317 321 return _selected_data_state … … 396 400 class Empty(object): 397 401 def __init__(self): 398 for key, value in data.ite ritems():402 for key, value in data.items(): 399 403 setattr(self, key, generate(value, level)) 400 404 … … 451 455 # if dictionary doesn't have __type__ then it is assumed to be just an ordinary dictionary 452 456 o = {} 453 for key, value in data.ite ritems():457 for key, value in data.items(): 454 458 o[key] = generate(value, level) 455 459 return o … … 463 467 464 468 new_stored_data = {} 465 for id, data in json.load(fp).ite ritems():469 for id, data in json.load(fp).items(): 466 470 try: 467 471 new_stored_data[id] = generate(data, 0) -
src/sas/qtgui/MainWindow/DataState.py
re7a0b2f rb3e8629 37 37 _str += "Theories available: %s \n" % len(self.theory_list) 38 38 if self.theory_list: 39 for id, item in self.theory_list.ite ritems():39 for id, item in self.theory_list.items(): 40 40 theory_data, theory_state = item 41 41 _str += "Theory name : %s \n" % str(theory_data.name) … … 53 53 obj.message = self.message 54 54 obj.id = self.id 55 for id, item in self.theory_list.ite ritems():55 for id, item in self.theory_list.items(): 56 56 theory_data, theory_state = item 57 57 state = None … … 95 95 """ 96 96 self.theory_list[theory_data.id] = [theory_data, theory_state] 97 data, state = self.theory_list.values()[0]97 data, state = list(self.theory_list.values())[0] 98 98 99 99 def get_theory(self): -
src/sas/qtgui/MainWindow/DroppableDataLoadWidget.py
rcd2cc745 r53c771e 1 1 # global 2 from PyQt4 import QtGui, QtCore 2 from PyQt5 import QtCore 3 from PyQt5 import QtGui 4 from PyQt5 import QtWidgets 3 5 4 6 # UI … … 6 8 from sas.qtgui.MainWindow.UI.DataExplorerUI import Ui_DataLoadWidget 7 9 8 class DroppableDataLoadWidget(Qt Gui.QTabWidget, Ui_DataLoadWidget):10 class DroppableDataLoadWidget(QtWidgets.QTabWidget, Ui_DataLoadWidget): 9 11 """ 10 12 Overwrite drag and drop methods in the base class … … 56 58 filenames=[] 57 59 for url in event.mimeData().urls(): 58 filenames.append( str(url.toLocalFile()))60 filenames.append(url.toLocalFile()) 59 61 self.communicator.fileReadSignal.emit(filenames) 60 62 event.accept() -
src/sas/qtgui/MainWindow/GuiManager.py
ra657de3 r14ec91c5 6 6 import webbrowser 7 7 8 from PyQt 4 import QtCore9 from PyQt 4 import QtGui10 from PyQt 4 import QtWebKit8 from PyQt5.QtWidgets import * 9 from PyQt5.QtGui import * 10 from PyQt5.QtCore import Qt, QLocale, QUrl 11 11 12 12 from twisted.internet import reactor … … 36 36 import sas.qtgui.Perspectives as Perspectives 37 37 from sas.qtgui.Perspectives.Fitting.FittingPerspective import FittingWindow 38 from sas.qtgui.MainWindow.DataExplorer import DataExplorerWindow 39 40 class Acknowledgements(Q tGui.QDialog, Ui_Acknowledgements):38 from sas.qtgui.MainWindow.DataExplorer import DataExplorerWindow, DEFAULT_PERSPECTIVE 39 40 class Acknowledgements(QDialog, Ui_Acknowledgements): 41 41 def __init__(self, parent=None): 42 Q tGui.QDialog.__init__(self, parent)42 QDialog.__init__(self, parent) 43 43 self.setupUi(self) 44 44 … … 55 55 self._parent = parent 56 56 57 # Decide on a locale 58 QLocale.setDefault(QLocale('en_US')) 59 57 60 # Add signal callbacks 58 61 self.addCallbacks() … … 65 68 self.addTriggers() 66 69 67 # Populate menus with dynamic data 68 # 69 # Analysis/Perspectives - potentially 70 # Window/current windows 71 # 72 # Widgets 73 # 74 # Current displayed perspective 70 # Currently displayed perspective 75 71 self._current_perspective = None 76 72 77 # Invoke the initial perspective 78 self.perspectiveChanged("Fitting") 79 73 # Populate the main window with stuff 80 74 self.addWidgets() 81 75 … … 92 86 self.statusBarSetup() 93 87 94 # Show the Welcome panel95 self.welcomePanel = WelcomePanel()96 self._workspace.workspace.addWindow(self.welcomePanel)97 98 # Current help file99 self._helpView = QtWebKit.QWebView()100 88 # Needs URL like path, so no path.join() here 101 89 self._helpLocation = GuiUtils.HELP_DIRECTORY_LOCATION + "/index.html" … … 105 93 "_downloads", 106 94 "Tutorial.pdf")) 95 107 96 def addWidgets(self): 108 97 """ … … 116 105 ObjectLibrary.addObject('DataExplorer', self.filesWidget) 117 106 118 self.dockedFilesWidget = QtGui.QDockWidget("Data Explorer", self._workspace) 107 self.dockedFilesWidget = QDockWidget("Data Explorer", self._workspace) 108 self.dockedFilesWidget.setFloating(False) 119 109 self.dockedFilesWidget.setWidget(self.filesWidget) 120 110 121 111 # Disable maximize/minimize and close buttons 122 self.dockedFilesWidget.setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) 123 self._workspace.addDockWidget(QtCore.Qt.LeftDockWidgetArea, 124 self.dockedFilesWidget) 112 self.dockedFilesWidget.setFeatures(QDockWidget.NoDockWidgetFeatures) 113 114 #self._workspace.workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget) 115 self._workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget) 125 116 126 117 # Add the console window as another docked widget 127 self.logDockWidget = Q tGui.QDockWidget("Log Explorer", self._workspace)118 self.logDockWidget = QDockWidget("Log Explorer", self._workspace) 128 119 self.logDockWidget.setObjectName("LogDockWidget") 129 self.listWidget = QtGui.QTextBrowser() 120 121 self.listWidget = QTextBrowser() 130 122 self.logDockWidget.setWidget(self.listWidget) 131 self._workspace.addDockWidget(QtCore.Qt.BottomDockWidgetArea, 132 self.logDockWidget) 123 self._workspace.addDockWidget(Qt.BottomDockWidgetArea, self.logDockWidget) 133 124 134 125 # Add other, minor widgets 135 126 self.ackWidget = Acknowledgements() 136 127 self.aboutWidget = AboutBox() 128 self.welcomePanel = WelcomePanel() 137 129 138 130 # Add calculators - floating for usability … … 152 144 Progress bar invisible until explicitly shown 153 145 """ 154 self.progress = Q tGui.QProgressBar()146 self.progress = QProgressBar() 155 147 self._workspace.statusbar.setSizeGripEnabled(False) 156 148 157 self.statusLabel = Q tGui.QLabel()149 self.statusLabel = QLabel() 158 150 self.statusLabel.setText("Welcome to SasView") 159 151 self._workspace.statusbar.addPermanentWidget(self.statusLabel, 1) … … 170 162 pass 171 163 164 def showHelp(self, url): 165 """ 166 Open a local url in the default browser 167 """ 168 location = GuiUtils.HELP_DIRECTORY_LOCATION + url 169 try: 170 webbrowser.open('file://' + os.path.realpath(location)) 171 except webbrowser.Error as ex: 172 logging.warning("Cannot display help. %s" % ex) 173 172 174 def workspace(self): 173 175 """ … … 180 182 Respond to change of the perspective signal 181 183 """ 184 185 # Save users from themselves... 186 #if isinstance(self._current_perspective, Perspectives.PERSPECTIVES[str(perspective_name)]): 187 self.setupPerspectiveMenubarOptions(self._current_perspective) 188 # return 189 182 190 # Close the previous perspective 183 if self._current_perspective is not None: 191 self.clearPerspectiveMenubarOptions(self._current_perspective) 192 if self._current_perspective: 184 193 self._current_perspective.setClosable() 194 #self._workspace.workspace.removeSubWindow(self._current_perspective) 185 195 self._current_perspective.close() 196 self._workspace.workspace.removeSubWindow(self._current_perspective) 186 197 # Default perspective 187 198 self._current_perspective = Perspectives.PERSPECTIVES[str(perspective_name)](parent=self) 188 199 189 self._workspace.workspace.addWindow(self._current_perspective) 200 subwindow = self._workspace.workspace.addSubWindow(self._current_perspective) 201 190 202 # Resize to the workspace height 191 203 workspace_height = self._workspace.workspace.sizeHint().height() 192 204 perspective_size = self._current_perspective.sizeHint() 193 if workspace_height < perspective_size.height: 194 perspective_width = perspective_size.width() 195 self._current_perspective.resize(perspective_width, workspace_height-10) 205 perspective_width = perspective_size.width() 206 self._current_perspective.resize(perspective_width, workspace_height-10) 207 # Resize the mdi area to match the widget within 208 subwindow.resize(subwindow.minimumSizeHint()) 209 196 210 self._current_perspective.show() 197 211 … … 202 216 assert isinstance(data, list) 203 217 if self._current_perspective is not None: 204 self._current_perspective.setData( data.values())218 self._current_perspective.setData(list(data.values())) 205 219 else: 206 220 msg = "No perspective is currently active." … … 246 260 """ 247 261 if self._current_perspective is not None: 248 self._current_perspective.setData( data.values())262 self._current_perspective.setData(list(data.values())) 249 263 else: 250 264 msg = "Guiframe does not have a current perspective" … … 257 271 # Display confirmation messagebox 258 272 quit_msg = "Are you sure you want to exit the application?" 259 reply = Q tGui.QMessageBox.question(273 reply = QMessageBox.question( 260 274 self._parent, 261 275 'Information', 262 276 quit_msg, 263 Q tGui.QMessageBox.Yes,264 Q tGui.QMessageBox.No)277 QMessageBox.Yes, 278 QMessageBox.No) 265 279 266 280 # Exit if yes 267 if reply == Q tGui.QMessageBox.Yes:281 if reply == QMessageBox.Yes: 268 282 reactor.callFromThread(reactor.stop) 269 283 return True … … 289 303 version_info = json.loads(content) 290 304 self.processVersion(version_info) 291 except ValueError ,ex:305 except ValueError as ex: 292 306 logging.info("Failed to connect to www.sasview.org:", ex) 293 307 … … 308 322 self.communicate.statusBarUpdateSignal.emit(msg) 309 323 310 elif cmp(version, LocalConfig.__version__) > 0:324 elif version.__gt__(LocalConfig.__version__): 311 325 msg = "Version %s is available! " % str(version) 312 326 if "download_url" in version_info: … … 321 335 except: 322 336 msg = "guiframe: could not get latest application" 323 msg += " version number\n %s" % sys.exc_ value337 msg += " version number\n %s" % sys.exc_info()[1] 324 338 logging.error(msg) 325 339 msg = "Could not connect to the application server." 326 340 msg += " Please try again later." 327 341 self.communicate.statusBarUpdateSignal.emit(msg) 342 343 def showWelcomeMessage(self): 344 """ Show the Welcome panel """ 345 self._workspace.workspace.addSubWindow(self.welcomePanel) 346 self.welcomePanel.show() 328 347 329 348 def addCallbacks(self): … … 384 403 self._workspace.actionCombine_Batch_Fit.triggered.connect(self.actionCombine_Batch_Fit) 385 404 self._workspace.actionFit_Options.triggered.connect(self.actionFit_Options) 405 self._workspace.actionGPU_Options.triggered.connect(self.actionGPU_Options) 386 406 self._workspace.actionFit_Results.triggered.connect(self.actionFit_Results) 387 407 self._workspace.actionChain_Fitting.triggered.connect(self.actionChain_Fitting) … … 578 598 579 599 # Add the console window as another docked widget 580 self.ipDockWidget = Q tGui.QDockWidget("IPython", self._workspace)600 self.ipDockWidget = QDockWidget("IPython", self._workspace) 581 601 self.ipDockWidget.setObjectName("IPythonDockWidget") 582 602 self.ipDockWidget.setWidget(terminal) 583 self._workspace.addDockWidget(QtCore.Qt.RightDockWidgetArea, 584 self.ipDockWidget) 603 self._workspace.addDockWidget(Qt.RightDockWidgetArea, self.ipDockWidget) 585 604 586 605 def actionImage_Viewer(self): … … 603 622 def actionConstrained_Fit(self): 604 623 """ 605 """ 606 print("actionConstrained_Fit TRIGGERED") 607 pass 624 Add a new Constrained and Simult. Fit page in the fitting perspective. 625 """ 626 per = self.perspective() 627 if not isinstance(per, FittingWindow): 628 return 629 per.addConstraintTab() 608 630 609 631 def actionCombine_Batch_Fit(self): … … 620 642 pass 621 643 644 def actionGPU_Options(self): 645 """ 646 Load the OpenCL selection dialog if the fitting perspective is active 647 """ 648 if hasattr(self._current_perspective, "gpu_options_widget"): 649 self._current_perspective.gpu_options_widget.show() 650 pass 651 622 652 def actionFit_Results(self): 623 653 """ … … 641 671 def actionFitting(self): 642 672 """ 643 """644 print("actionFitting TRIGGERED")645 pass673 Change to the Fitting perspective 674 """ 675 self.perspectiveChanged("Fitting") 646 676 647 677 def actionInversion(self): 648 678 """ 649 """ 679 Change to the Inversion perspective 680 """ 681 # For now we'll just update the analysis menu status but when the inversion is implemented delete from here 682 self.checkAnalysisOption(self._workspace.actionInversion) 683 # to here and uncomment the following line 650 684 self.perspectiveChanged("Inversion") 651 pass652 685 653 686 def actionInvariant(self): 654 687 """ 655 """656 print("actionInvariant TRIGGERED")657 pass688 Change to the Invariant perspective 689 """ 690 self.perspectiveChanged("Invariant") 658 691 659 692 #============ WINDOW ================= … … 695 728 TODO: use QNetworkAccessManager to assure _helpLocation is valid 696 729 """ 697 self._helpView.load(QtCore.QUrl(self._helpLocation)) 698 self._helpView.show() 730 self.showHelp(self._helpLocation) 699 731 700 732 def actionTutorial(self): … … 740 772 :param new_datalist_item: 741 773 """ 742 if not isinstance(new_item, Q tGui.QStandardItem) or \774 if not isinstance(new_item, QStandardItem) or \ 743 775 not isinstance(new_datalist_item, dict): 744 776 msg = "Wrong data type returned from calculations." 745 raise AttributeError , msg777 raise AttributeError(msg) 746 778 747 779 self.filesWidget.model.appendRow(new_item) … … 754 786 if hasattr(self, "filesWidget"): 755 787 self.filesWidget.displayData(plot) 788 789 def uncheckAllMenuItems(self, menuObject): 790 """ 791 Uncheck all options in a given menu 792 """ 793 menuObjects = menuObject.actions() 794 795 for menuItem in menuObjects: 796 menuItem.setChecked(False) 797 798 def checkAnalysisOption(self, analysisMenuOption): 799 """ 800 Unchecks all the items in the analysis menu and checks the item passed 801 """ 802 self.uncheckAllMenuItems(self._workspace.menuAnalysis) 803 analysisMenuOption.setChecked(True) 804 805 def clearPerspectiveMenubarOptions(self, perspective): 806 """ 807 When closing a perspective, clears the menu bar 808 """ 809 for menuItem in self._workspace.menuAnalysis.actions(): 810 menuItem.setChecked(False) 811 812 if isinstance(self._current_perspective, Perspectives.PERSPECTIVES["Fitting"]): 813 self._workspace.menubar.removeAction(self._workspace.menuFitting.menuAction()) 814 815 def setupPerspectiveMenubarOptions(self, perspective): 816 """ 817 When setting a perspective, sets up the menu bar 818 """ 819 if isinstance(perspective, Perspectives.PERSPECTIVES["Fitting"]): 820 self.checkAnalysisOption(self._workspace.actionFitting) 821 # Put the fitting menu back in 822 # This is a bit involved but it is needed to preserve the menu ordering 823 self._workspace.menubar.removeAction(self._workspace.menuWindow.menuAction()) 824 self._workspace.menubar.removeAction(self._workspace.menuHelp.menuAction()) 825 self._workspace.menubar.addAction(self._workspace.menuFitting.menuAction()) 826 self._workspace.menubar.addAction(self._workspace.menuWindow.menuAction()) 827 self._workspace.menubar.addAction(self._workspace.menuHelp.menuAction()) 828 elif isinstance(perspective, Perspectives.PERSPECTIVES["Invariant"]): 829 self.checkAnalysisOption(self._workspace.actionInvariant) 830 # elif isinstance(perspective, Perspectives.PERSPECTIVES["Inversion"]): 831 # self.checkAnalysisOption(self._workspace.actionInversion) -
src/sas/qtgui/MainWindow/MainWindow.py
r2a8bd705 r8353d90 1 1 # UNLESS EXEPTIONALLY REQUIRED TRY TO AVOID IMPORTING ANY MODULES HERE 2 2 # ESPECIALLY ANYTHING IN SAS, SASMODELS NAMESPACE 3 from PyQt4 import QtGui 3 from PyQt5.QtWidgets import QMainWindow 4 from PyQt5.QtWidgets import QMdiArea 5 from PyQt5.QtWidgets import QSplashScreen 6 from PyQt5.QtWidgets import QApplication 7 from PyQt5.QtGui import QPixmap 4 8 5 9 # Local UI 6 10 from sas.qtgui.UI import main_resources_rc 7 from UI.MainWindowUI import Ui_MainWindow11 from .UI.MainWindowUI import Ui_MainWindow 8 12 9 13 # Initialize logging 10 14 import sas.qtgui.Utilities.SasviewLogger 11 15 12 class MainSasViewWindow(Q tGui.QMainWindow, Ui_MainWindow):16 class MainSasViewWindow(QMainWindow, Ui_MainWindow): 13 17 # Main window of the application 14 18 def __init__(self, parent=None): … … 17 21 18 22 # define workspace for dialogs. 19 self.workspace = Q tGui.QWorkspace(self)23 self.workspace = QMdiArea(self) 20 24 self.setCentralWidget(self.workspace) 21 25 22 26 # Create the gui manager 23 from GuiManager import GuiManager 24 self.guiManager = GuiManager(self) 27 from .GuiManager import GuiManager 28 try: 29 self.guiManager = GuiManager(self) 30 except Exception as ex: 31 import logging 32 logging.error("Application failed with: ", ex) 33 print("Application failed with: ", ex) 25 34 26 35 def closeEvent(self, event): … … 37 46 """ 38 47 # TODO: standardize path to images 39 pixmap = Q tGui.QPixmap("src/sas/qtgui/images/SVwelcome_mini.png")40 splashScreen = Q tGui.QSplashScreen(pixmap)48 pixmap = QPixmap("src/sas/qtgui/images/SVwelcome_mini.png") 49 splashScreen = QSplashScreen(pixmap) 41 50 return splashScreen 42 51 43 52 def run(): 44 app = Q tGui.QApplication([])53 app = QApplication([]) 45 54 46 55 # Main must have reference to the splash screen, so making it explicit … … 55 64 # DO NOT move the following import to the top! 56 65 # (unless you know what you're doing) 57 import qt 4reactor58 # Using the Qt 4reactor wrapper from https://github.com/ghtdak/qtreactor59 qt 4reactor.install()66 import qt5reactor 67 # Using the Qt5 reactor wrapper from https://github.com/ghtdak/qtreactor 68 qt5reactor.install() 60 69 61 70 # DO NOT move the following import to the top! … … 69 78 splash.finish(mainwindow) 70 79 80 # Time for the welcome window 81 mainwindow.guiManager.showWelcomeMessage() 82 71 83 # No need to .exec_ - the reactor takes care of it. 72 84 reactor.run() -
src/sas/qtgui/MainWindow/UI/DataExplorerUI.ui
r61a92d4 rc6fb57c 499 499 </property> 500 500 </action> 501 <action name="actionDelete"> 502 <property name="text"> 503 <string>Delete</string> 504 </property> 505 </action> 501 506 </widget> 502 507 <resources/> -
src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
rb00414d r1543f0c 103 103 <addaction name="separator"/> 104 104 <addaction name="actionFit_Options"/> 105 <addaction name="actionGPU_Options"/> 105 106 <addaction name="actionFit_Results"/> 106 107 <addaction name="separator"/> … … 499 500 </property> 500 501 </action> 502 <action name="actionGPU_Options"> 503 <property name="text"> 504 <string>GPU Options</string> 505 </property> 506 </action> 501 507 </widget> 502 508 <resources/> -
src/sas/qtgui/MainWindow/UnitTesting/AboutBoxTest.py
r464cd07 r53c771e 3 3 import webbrowser 4 4 5 from PyQt 4 import QtGui6 from PyQt 4.QtTest import QTest7 from PyQt 4import QtCore8 from mock import MagicMock5 from PyQt5 import QtGui, QtWidgets 6 from PyQt5.QtTest import QTest 7 from PyQt5 import QtCore 8 from unittest.mock import MagicMock 9 9 10 10 # set up import paths … … 15 15 import sas.qtgui.Utilities.LocalConfig as LocalConfig 16 16 17 if not Qt Gui.QApplication.instance():18 app = Qt Gui.QApplication(sys.argv)17 if not QtWidgets.QApplication.instance(): 18 app = QtWidgets.QApplication(sys.argv) 19 19 20 20 class AboutBoxTest(unittest.TestCase): … … 31 31 def testDefaults(self): 32 32 '''Test the GUI in its default state''' 33 self.assertIsInstance(self.widget, Qt Gui.QWidget)33 self.assertIsInstance(self.widget, QtWidgets.QWidget) 34 34 self.assertEqual(self.widget.windowTitle(), "About") 35 35 self.assertEqual(self.widget.cmdOK.text(), "OK") … … 45 45 """ 46 46 version = self.widget.lblVersion 47 self.assertIsInstance(version, Qt Gui.QLabel)47 self.assertIsInstance(version, QtWidgets.QLabel) 48 48 self.assertEqual(str(version.text()), str(LocalConfig.__version__)) 49 49 … … 53 53 """ 54 54 about = self.widget.lblAbout 55 self.assertIsInstance(about, Qt Gui.QLabel)55 self.assertIsInstance(about, QtWidgets.QLabel) 56 56 # build version 57 57 self.assertIn(str(LocalConfig.__build__), about.text()) … … 83 83 84 84 # Press the buttons 85 buttonList = self.widget.findChildren(Qt Gui.QPushButton)85 buttonList = self.widget.findChildren(QtWidgets.QPushButton) 86 86 for button in buttonList: 87 87 QTest.mouseClick(button, QtCore.Qt.LeftButton) -
src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py
rf7d14a1 rc6fb57c 2 2 import unittest 3 3 4 from PyQt4.QtGui import * 5 from PyQt4.QtTest import QTest 6 from PyQt4.QtCore import * 7 from mock import MagicMock 8 from mock import patch 4 from PyQt5.QtGui import * 5 from PyQt5.QtWidgets import * 6 from PyQt5.QtTest import QTest 7 from PyQt5.QtCore import * 8 from unittest.mock import MagicMock 9 from unittest.mock import patch 9 10 from mpl_toolkits.mplot3d import Axes3D 10 11 … … 25 26 import sas.qtgui.Plotting.PlotHelper as PlotHelper 26 27 27 if not QApplication.instance():28 28 #if not QApplication.instance(): 29 app = QApplication(sys.argv) 29 30 30 31 class DataExplorerTest(unittest.TestCase): … … 36 37 return Communicate() 37 38 def allowBatch(self): 38 return False39 return True 39 40 def setData(self, data_item=None, is_batch=False): 40 41 return None … … 114 115 115 116 # Return no files. 116 Q tGui.QFileDialog.getOpenFileNames = MagicMock(return_value=None)117 QFileDialog.getOpenFileNames = MagicMock(return_value=('','')) 117 118 118 119 # Click on the Load button … … 120 121 121 122 # Test the getOpenFileName() dialog called once 122 self.assertTrue(Q tGui.QFileDialog.getOpenFileNames.called)123 Q tGui.QFileDialog.getOpenFileNames.assert_called_once()123 self.assertTrue(QFileDialog.getOpenFileNames.called) 124 QFileDialog.getOpenFileNames.assert_called_once() 124 125 125 126 # Make sure the signal has not been emitted … … 127 128 128 129 # Now, return a single file 129 Q tGui.QFileDialog.getOpenFileNames = MagicMock(return_value=filename)130 QFileDialog.getOpenFileNames = MagicMock(return_value=(filename,'')) 130 131 131 132 # Click on the Load button 132 133 QTest.mouseClick(loadButton, Qt.LeftButton) 133 QtGui.qApp.processEvents()134 qApp.processEvents() 134 135 135 136 # Test the getOpenFileName() dialog called once 136 self.assertTrue(Q tGui.QFileDialog.getOpenFileNames.called)137 Q tGui.QFileDialog.getOpenFileNames.assert_called_once()137 self.assertTrue(QFileDialog.getOpenFileNames.called) 138 QFileDialog.getOpenFileNames.assert_called_once() 138 139 139 140 # Expected one spy instance … … 157 158 158 159 expected_list = [0, 0, 33, 66, -1] 159 spied_list = [spy_progress_bar_update.called()[i]['args'][0] for i in xrange(5)]160 spied_list = [spy_progress_bar_update.called()[i]['args'][0] for i in range(5)] 160 161 self.assertEqual(expected_list, spied_list) 161 162 … … 167 168 168 169 # Mock the confirmation dialog with return=No 169 Q tGui.QMessageBox.question = MagicMock(return_value=QtGui.QMessageBox.No)170 QMessageBox.question = MagicMock(return_value=QMessageBox.No) 170 171 171 172 # Populate the model … … 180 181 item2 = self.form.model.item(1) 181 182 item3 = self.form.model.item(2) 182 self.assertTrue(item1.checkState() == Qt Core.Qt.Checked)183 self.assertTrue(item2.checkState() == Qt Core.Qt.Checked)184 self.assertTrue(item3.checkState() == Qt Core.Qt.Checked)183 self.assertTrue(item1.checkState() == Qt.Checked) 184 self.assertTrue(item2.checkState() == Qt.Checked) 185 self.assertTrue(item3.checkState() == Qt.Checked) 185 186 186 187 # Click on the delete button … … 188 189 189 190 # Test the warning dialog called once 190 self.assertTrue(Q tGui.QMessageBox.question.called)191 self.assertTrue(QMessageBox.question.called) 191 192 192 193 # Assure the model still contains the items … … 194 195 195 196 # Now, mock the confirmation dialog with return=Yes 196 Q tGui.QMessageBox.question = MagicMock(return_value=QtGui.QMessageBox.Yes)197 QMessageBox.question = MagicMock(return_value=QMessageBox.Yes) 197 198 198 199 # Click on the delete button … … 200 201 201 202 # Test the warning dialog called once 202 self.assertTrue(Q tGui.QMessageBox.question.called)203 self.assertTrue(QMessageBox.question.called) 203 204 204 205 # Assure the model contains no items … … 215 216 216 217 # Mock the confirmation dialog with return=No 217 Q tGui.QMessageBox.question = MagicMock(return_value=QtGui.QMessageBox.No)218 QMessageBox.question = MagicMock(return_value=QMessageBox.No) 218 219 219 220 # Populate the model 220 item1 = Q tGui.QStandardItem(True)221 item1 = QStandardItem(True) 221 222 item1.setCheckable(True) 222 item1.setCheckState(Qt Core.Qt.Checked)223 item1.setCheckState(Qt.Checked) 223 224 item1.setText("item 1") 224 225 self.form.theory_model.appendRow(item1) 225 item2 = Q tGui.QStandardItem(True)226 item2 = QStandardItem(True) 226 227 item2.setCheckable(True) 227 item2.setCheckState(Qt Core.Qt.Unchecked)228 item2.setCheckState(Qt.Unchecked) 228 229 item2.setText("item 2") 229 230 self.form.theory_model.appendRow(item2) … … 233 234 234 235 # Assure the checkboxes are on 235 self.assertTrue(item1.checkState() == Qt Core.Qt.Checked)236 self.assertTrue(item2.checkState() == Qt Core.Qt.Unchecked)236 self.assertTrue(item1.checkState() == Qt.Checked) 237 self.assertTrue(item2.checkState() == Qt.Unchecked) 237 238 238 239 # Click on the delete button … … 240 241 241 242 # Test the warning dialog called once 242 self.assertTrue(Q tGui.QMessageBox.question.called)243 self.assertTrue(QMessageBox.question.called) 243 244 244 245 # Assure the model still contains the items … … 246 247 247 248 # Now, mock the confirmation dialog with return=Yes 248 Q tGui.QMessageBox.question = MagicMock(return_value=QtGui.QMessageBox.Yes)249 QMessageBox.question = MagicMock(return_value=QMessageBox.Yes) 249 250 250 251 # Click on the delete button … … 252 253 253 254 # Test the warning dialog called once 254 self.assertTrue(Q tGui.QMessageBox.question.called)255 self.assertTrue(QMessageBox.question.called) 255 256 256 257 # Assure the model contains 1 item … … 258 259 259 260 # Set the remaining item to checked 260 self.form.theory_model.item(0).setCheckState(Qt Core.Qt.Checked)261 self.form.theory_model.item(0).setCheckState(Qt.Checked) 261 262 262 263 # Click on the delete button again … … 306 307 307 308 # Mock the warning message 308 Q tGui.QMessageBox = MagicMock()309 QMessageBox = MagicMock() 309 310 310 311 # Click on the button … … 312 313 313 314 # Assure the message box popped up 314 Q tGui.QMessageBox.assert_called_once()315 QMessageBox.assert_called_once() 315 316 316 317 def testDataSelection(self): … … 328 329 item1D = self.form.model.item(0) 329 330 item2D = self.form.model.item(1) 330 self.assertTrue(item1D.checkState() == Qt Core.Qt.Unchecked)331 self.assertTrue(item2D.checkState() == Qt Core.Qt.Unchecked)331 self.assertTrue(item1D.checkState() == Qt.Unchecked) 332 self.assertTrue(item2D.checkState() == Qt.Unchecked) 332 333 333 334 # Select all data … … 335 336 336 337 # Test the current selection 337 self.assertTrue(item1D.checkState() == Qt Core.Qt.Checked)338 self.assertTrue(item2D.checkState() == Qt Core.Qt.Checked)338 self.assertTrue(item1D.checkState() == Qt.Checked) 339 self.assertTrue(item2D.checkState() == Qt.Checked) 339 340 340 341 # select 1d data … … 342 343 343 344 # Test the current selection 344 self.assertTrue(item1D.checkState() == Qt Core.Qt.Checked)345 self.assertTrue(item2D.checkState() == Qt Core.Qt.Unchecked)345 self.assertTrue(item1D.checkState() == Qt.Checked) 346 self.assertTrue(item2D.checkState() == Qt.Unchecked) 346 347 347 348 # unselect 1d data … … 349 350 350 351 # Test the current selection 351 self.assertTrue(item1D.checkState() == Qt Core.Qt.Unchecked)352 self.assertTrue(item2D.checkState() == Qt Core.Qt.Unchecked)352 self.assertTrue(item1D.checkState() == Qt.Unchecked) 353 self.assertTrue(item2D.checkState() == Qt.Unchecked) 353 354 354 355 # select 2d data … … 356 357 357 358 # Test the current selection 358 self.assertTrue(item1D.checkState() == Qt Core.Qt.Unchecked)359 self.assertTrue(item2D.checkState() == Qt Core.Qt.Checked)359 self.assertTrue(item1D.checkState() == Qt.Unchecked) 360 self.assertTrue(item2D.checkState() == Qt.Checked) 360 361 361 362 # unselect 2d data … … 363 364 364 365 # Test the current selection 365 self.assertTrue(item1D.checkState() == Qt Core.Qt.Unchecked)366 self.assertTrue(item2D.checkState() == Qt Core.Qt.Unchecked)366 self.assertTrue(item1D.checkState() == Qt.Unchecked) 367 self.assertTrue(item2D.checkState() == Qt.Unchecked) 367 368 368 369 # choose impossible index and assure the code raises … … 382 383 """ 383 384 # Create an item with several branches 384 item1 = Q tGui.QStandardItem()385 item2 = Q tGui.QStandardItem()386 item3 = Q tGui.QStandardItem()387 item4 = Q tGui.QStandardItem()388 item5 = Q tGui.QStandardItem()389 item6 = Q tGui.QStandardItem()385 item1 = QStandardItem() 386 item2 = QStandardItem() 387 item3 = QStandardItem() 388 item4 = QStandardItem() 389 item5 = QStandardItem() 390 item6 = QStandardItem() 390 391 391 392 item4.appendRow(item5) … … 429 430 # The 0th item header should be the name of the file 430 431 model_item = self.form.model.index(0,0) 431 model_name = s tr(self.form.model.data(model_item).toString())432 model_name = self.form.model.data(model_item) 432 433 self.assertEqual(model_name, filename[0]) 433 434 … … 442 443 # Click on the Help button 443 444 QTest.mouseClick(button1, Qt.LeftButton) 444 QtGui.qApp.processEvents()445 qApp.processEvents() 445 446 446 447 # Check the browser … … 451 452 # Click on the Help_2 button 452 453 QTest.mouseClick(button2, Qt.LeftButton) 453 QtGui.qApp.processEvents()454 qApp.processEvents() 454 455 # Check the browser 455 456 self.assertIn(partial_url, str(self.form._helpView.url())) … … 503 504 # We don't know the data ID, so need to iterate over dict 504 505 data_dict = spy_data_received.called()[0]['args'][0] 505 for data_key, data_value in data_dict.ite ritems():506 for data_key, data_value in data_dict.items(): 506 507 self.assertIsInstance(data_value, Data1D) 507 508 … … 593 594 p_file="cyl_400_20.txt" 594 595 output_object = loader.load(p_file) 595 output_item = Q tGui.QStandardItem()596 output_item = QStandardItem() 596 597 new_data = [(output_item, manager.create_gui_data(output_object[0], p_file))] 597 598 … … 641 642 Assure the model update is correct 642 643 """ 643 good_item = Q tGui.QStandardItem()644 good_item = QStandardItem() 644 645 bad_item = "I'm so bad" 645 646 … … 666 667 667 668 # Pick up the treeview index corresponding to that file 668 index = self.form.treeView.indexAt(Q tCore.QPoint(5,5))669 index = self.form.treeView.indexAt(QPoint(5,5)) 669 670 self.form.show() 670 671 … … 682 683 # Instead, send the signal directly 683 684 self.form.treeView.customContextMenuRequested.emit(rect) 684 685 # app.exec_() # debug686 685 687 686 # See that the menu has been shown … … 804 803 pass 805 804 805 def notestDeleteItem(self): 806 """ 807 Delete selected item from data explorer 808 """ 809 810 # Mock the confirmation dialog with return=No 811 QMessageBox.question = MagicMock(return_value=QMessageBox.No) 812 813 # Populate the model 814 filename = ["cyl_400_20.txt", "cyl_400_20.txt", "cyl_400_20.txt"] 815 self.form.readData(filename) 816 817 # Assure the model contains three items 818 self.assertEqual(self.form.model.rowCount(), 3) 819 820 # Add an item to first file item 821 item1 = QtGui.QStandardItem("test") 822 item1.setCheckable(True) 823 self.form.model.item(0).appendRow(item1) 824 825 # Check the new item is in 826 827 self.assertTrue(self.form.model.item(0).hasChildren()) 828 829 #select_item = self.form.model.item(0).child(3) 830 select_item = self.form.model.item(0) 831 select_index = self.form.model.indexFromItem(select_item) 832 833 # Open up items 834 self.form.current_view.expandAll() 835 836 # Select the newly created item 837 self.form.current_view.selectionModel().select(select_index, QtCore.QItemSelectionModel.Rows) 838 839 # Attempt at deleting 840 self.form.deleteItem() 841 842 # Test the warning dialog called once 843 self.assertTrue(QMessageBox.question.called) 844 845 # Assure the model still contains the items 846 self.assertEqual(self.form.model.rowCount(), 3) 847 848 # Now, mock the confirmation dialog with return=Yes 849 QMessageBox.question = MagicMock(return_value=QMessageBox.Yes) 850 851 # Select the newly created item 852 self.form.current_view.selectionModel().select(select_index, QtCore.QItemSelectionModel.Rows) 853 # delete it. now for good 854 self.form.deleteItem() 855 856 # Test the warning dialog called once 857 self.assertTrue(QMessageBox.question.called) 858 859 # Assure the model contains no items 860 self.assertEqual(self.form.model.rowCount(), 3) 861 806 862 807 863 if __name__ == "__main__": -
src/sas/qtgui/MainWindow/UnitTesting/DroppableDataLoadWidgetTest.py
r464cd07 r53c771e 2 2 import unittest 3 3 4 from PyQt 4.QtGuiimport QApplication5 from PyQt 4.QtTest import QTest6 from PyQt 4import QtCore4 from PyQt5.QtWidgets import QApplication 5 from PyQt5.QtTest import QTest 6 from PyQt5 import QtCore 7 7 8 8 # set up import paths … … 62 62 63 63 drop_event = QtGui.QDropEvent(QtCore.QPoint(0,0), 64 65 66 67 64 QtCore.Qt.CopyAction, 65 self.mime_data, 66 QtCore.Qt.LeftButton, 67 QtCore.Qt.NoModifier) 68 68 69 69 self.form.dropEvent(drop_event) 70 Q tGui.qApp.processEvents()70 QApplication.processEvents() 71 71 self.assertEqual(spy_file_read.count(), 1) 72 72 self.assertIn(self.testfile, str(spy_file_read.signal(index=0))) -
src/sas/qtgui/MainWindow/UnitTesting/GuiManagerTest.py
r8222f171 r725d9c06 5 5 import logging 6 6 7 from PyQt 4.QtGui import *8 from PyQt 4.QtTest import QTest9 from PyQt 4.QtCore import *10 from PyQt 4.QtWebKitimport *11 from mock import MagicMock7 from PyQt5.QtGui import * 8 from PyQt5.QtWidgets import * 9 from PyQt5.QtTest import QTest 10 from PyQt5.QtCore import * 11 from unittest.mock import MagicMock 12 12 13 13 # set up import paths … … 37 37 38 38 # define workspace for dialogs. 39 self.workspace = Q Workspace(self)39 self.workspace = QMdiArea(self) 40 40 self.setCentralWidget(self.workspace) 41 41 … … 74 74 # We are in the MainWindow scope, so simple 'print' will work 75 75 message = "from stdout" 76 print message76 print(message) 77 77 self.assertIn(message, self.manager.logDockWidget.widget().toPlainText()) 78 78 … … 162 162 """ 163 163 # 1. version = 0.0.0 164 version_info = { u'version' : u'0.0.0'}164 version_info = {'version' : '0.0.0'} 165 165 spy_status_update = QtSignalSpy(self.manager, self.manager.communicate.statusBarUpdateSignal) 166 166 … … 172 172 173 173 # 2. version < LocalConfig.__version__ 174 version_info = { u'version' : u'0.0.1'}174 version_info = {'version' : '0.0.1'} 175 175 spy_status_update = QtSignalSpy(self.manager, self.manager.communicate.statusBarUpdateSignal) 176 176 … … 182 182 183 183 # 3. version > LocalConfig.__version__ 184 version_info = { u'version' : u'999.0.0'}184 version_info = {'version' : '999.0.0'} 185 185 spy_status_update = QtSignalSpy(self.manager, self.manager.communicate.statusBarUpdateSignal) 186 186 webbrowser.open = MagicMock() … … 221 221 """ 222 222 # Mock the system file open method 223 QFileDialog.getOpenFileNames = MagicMock(return_value= None)223 QFileDialog.getOpenFileNames = MagicMock(return_value=('','')) 224 224 225 225 # invoke the action … … 234 234 """ 235 235 # Mock the system file open method 236 QFileDialog.getExistingDirectory = MagicMock(return_value= None)236 QFileDialog.getExistingDirectory = MagicMock(return_value=('','')) 237 237 238 238 # invoke the action … … 270 270 271 271 #### HELP #### 272 # test when PyQt5 works with html 272 273 def testActionDocumentation(self): 273 274 """ 274 275 Menu Help/Documentation 275 276 """ 276 #Mock the QWebView method 277 QWebView.show = MagicMock() 278 279 # Assure the filename is correct 280 self.assertIn("index.html", self.manager._helpLocation) 277 webbrowser.open = MagicMock() 281 278 282 279 # Invoke the action 283 280 self.manager.actionDocumentation() 284 281 285 # Check if show() got called 286 self.assertTrue(QWebView.show.called) 282 # see that webbrowser open was attempted 283 webbrowser.open.assert_called_once() 284 287 285 288 286 def skip_testActionTutorial(self): -
src/sas/qtgui/MainWindow/UnitTesting/MainWindowTest.py
r464cd07 r8353d90 1 1 import sys 2 2 import unittest 3 import logging 3 4 4 from PyQt 4 import QtGui5 from PyQt 4import QtTest6 from PyQt 4import QtCore7 from mock import MagicMock5 from PyQt5 import QtGui, QtWidgets 6 from PyQt5 import QtTest 7 from PyQt5 import QtCore 8 from unittest.mock import MagicMock 8 9 9 10 # set up import paths … … 13 14 from sas.qtgui.MainWindow.MainWindow import MainSasViewWindow 14 15 from sas.qtgui.MainWindow.MainWindow import SplashScreen 16 from sas.qtgui.MainWindow.GuiManager import GuiManager 17 from sas.qtgui.Perspectives.Fitting import FittingPerspective 15 18 16 if not Qt Gui.QApplication.instance():17 app = Qt Gui.QApplication(sys.argv)19 if not QtWidgets.QApplication.instance(): 20 app = QtWidgets.QApplication(sys.argv) 18 21 19 22 class MainWindowTest(unittest.TestCase): … … 30 33 def testDefaults(self): 31 34 """Test the GUI in its default state""" 32 self.assertIsInstance(self.widget, Qt Gui.QMainWindow)33 self.assertIsInstance(self.widget.centralWidget(), Qt Gui.QWorkspace)35 self.assertIsInstance(self.widget, QtWidgets.QMainWindow) 36 self.assertIsInstance(self.widget.centralWidget(), QtWidgets.QMdiArea) 34 37 35 38 def testSplashScreen(self): 36 39 """ Test the splash screen """ 37 40 splash = SplashScreen() 38 self.assertIsInstance(splash, QtGui.QSplashScreen) 41 self.assertIsInstance(splash, QtWidgets.QSplashScreen) 42 43 def testWidgets(self): 44 """ Test enablement/disablement of widgets """ 45 # Open the main window 46 tmp_main = MainSasViewWindow(None) 47 tmp_main.showMaximized() 48 # See that only one subwindow is up 49 self.assertEqual(len(tmp_main.workspace.subWindowList()), 1) 50 # and that the subwindow is the fitting perspective 51 self.assertIsInstance(tmp_main.workspace.subWindowList()[0].widget(), 52 FittingPerspective.FittingWindow) 53 # Show the message widget 54 tmp_main.guiManager.showWelcomeMessage() 55 # Assure it is visible and a part of the MdiArea 56 self.assertTrue(tmp_main.guiManager.welcomePanel.isVisible()) 57 self.assertEqual(len(tmp_main.workspace.subWindowList()), 2) 58 59 tmp_main.close() 39 60 40 61 def testExit(self): … … 44 65 # Must mask sys.exit, otherwise the whole testing process stops. 45 66 sys.exit = MagicMock() 46 Qt Gui.QMessageBox.question = MagicMock(return_value=QtGui.QMessageBox.Yes)67 QtWidgets.QMessageBox.question = MagicMock(return_value=QtWidgets.QMessageBox.Yes) 47 68 48 69 # Open, then close the main window … … 51 72 52 73 # See that the MessageBox method got called 53 self.assertTrue(Qt Gui.QMessageBox.question.called)74 self.assertTrue(QtWidgets.QMessageBox.question.called) 54 75 55 76 if __name__ == "__main__": -
src/sas/qtgui/MainWindow/UnitTesting/WelcomePanelTest.py
r464cd07 r53c771e 2 2 import unittest 3 3 4 from PyQt 4 import QtGui4 from PyQt5 import QtGui, QtWidgets 5 5 6 6 # set up import paths … … 10 10 from sas.qtgui.MainWindow.WelcomePanel import WelcomePanel 11 11 12 if not Qt Gui.QApplication.instance():13 app = Qt Gui.QApplication(sys.argv)12 if not QtWidgets.QApplication.instance(): 13 app = QtWidgets.QApplication(sys.argv) 14 14 15 15 class WelcomePanelTest(unittest.TestCase): … … 27 27 def testDefaults(self): 28 28 '''Test the GUI in its default state''' 29 self.assertIsInstance(self.widget, Qt Gui.QDialog)29 self.assertIsInstance(self.widget, QtWidgets.QDialog) 30 30 self.assertEqual(self.widget.windowTitle(), "Welcome") 31 31 … … 33 33 '''Test the version string''' 34 34 version = self.widget.lblVersion 35 self.assertIsInstance(version, Qt Gui.QLabel)35 self.assertIsInstance(version, QtWidgets.QLabel) 36 36 37 37 self.assertIn("SasView", version.text()) -
src/sas/qtgui/MainWindow/WelcomePanel.py
rcd2cc745 r4992ff2 2 2 import sys 3 3 import os 4 from PyQt4 import QtCore 5 from PyQt4 import QtGui 6 from PyQt4 import QtWebKit 4 5 from PyQt5 import QtWidgets 7 6 8 7 import sas.sasview … … 13 12 from sas.qtgui.MainWindow.UI.WelcomePanelUI import Ui_WelcomePanelUI 14 13 15 class WelcomePanel(Qt Gui.QDialog, Ui_WelcomePanelUI):14 class WelcomePanel(QtWidgets.QDialog, Ui_WelcomePanelUI): 16 15 def __init__(self, parent=None): 17 16 super(WelcomePanel, self).__init__(parent) -
src/sas/qtgui/Perspectives/Fitting/FitThread.py
- Property mode changed from 100755 to 100644
ree18d33 r235d766 14 14 15 15 def map_apply(arguments): 16 return a pply(arguments[0],arguments[1:])16 return arguments[0](*arguments[1:]) 17 17 18 18 class FitThread(CalcThread): … … 55 55 except KeyboardInterrupt: 56 56 msg = "Fitting: terminated by the user." 57 raise KeyboardInterrupt , msg57 raise KeyboardInterrupt(msg) 58 58 59 59 def compute(self): … … 71 71 list_q = [None]*fitter_size 72 72 73 inputs = zip(list_map_get_attr, self.fitter, list_fit_function,73 inputs = list(zip(list_map_get_attr, self.fitter, list_fit_function, 74 74 list_q, list_q, list_handler, list_curr_thread, 75 list_reset_flag) 76 result = map(map_apply, inputs)75 list_reset_flag)) 76 result = list(map(map_apply, inputs)) 77 77 results = (result, time.time()-self.starttime) 78 78 if self.handler: … … 81 81 return (results) 82 82 83 except KeyboardInterrupt ,msg:83 except KeyboardInterrupt as msg: 84 84 # Thread was interrupted, just proceed and re-raise. 85 85 # Real code should not print, but this is an example... … … 95 95 # print "ERROR IN FIT THREAD: ", traceback.format_exc() 96 96 if self.handler is not None: 97 self.handler.error(msg=traceback.format_exc()) 97 self.handler.error(msg=str(ex)) 98 self.completefn(None) 99 else: 100 return(None) 98 101 99 102 -
src/sas/qtgui/Perspectives/Fitting/FittingLogic.py
ree18d33 rb3e8629 196 196 msg = "Unable to find min/max/length of \n data named %s" % \ 197 197 self.data.filename 198 raise ValueError , msg198 raise ValueError(msg) 199 199 200 200 else: … … 206 206 msg = "Unable to find min/max of \n data named %s" % \ 207 207 self.data.filename 208 raise ValueError , msg208 raise ValueError(msg) 209 209 qmax = np.sqrt(x * x + y * y) 210 210 npts = len(data.data) -
src/sas/qtgui/Perspectives/Fitting/FittingOptions.py
- Property mode changed from 100755 to 100644
r377ade1 re90988c 3 3 import os 4 4 import types 5 6 from PyQt4 import QtCore 7 from PyQt4 import QtGui 8 from PyQt4 import QtWebKit 5 import webbrowser 6 7 from PyQt5 import QtCore 8 from PyQt5 import QtGui 9 from PyQt5 import QtWidgets 9 10 10 11 from sas.qtgui.UI import images_rc … … 21 22 22 23 23 class FittingOptions(Qt Gui.QDialog, Ui_FittingOptions):24 class FittingOptions(QtWidgets.QDialog, Ui_FittingOptions): 24 25 """ 25 26 Hard-coded version of the fit options dialog available from BUMPS. … … 52 53 53 54 # Handle the Apply button click 54 self.buttonBox.button(Qt Gui.QDialogButtonBox.Ok).clicked.connect(self.onApply)55 self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self.onApply) 55 56 # handle the Help button click 56 self.buttonBox.button(Qt Gui.QDialogButtonBox.Help).clicked.connect(self.onHelp)57 self.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.onHelp) 57 58 58 59 # Handle the combo box changes … … 71 72 72 73 # OK has to be initialized to True, after initial validator setup 73 self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True) 74 75 # Display HTML content 76 self.helpView = QtWebKit.QWebView() 74 self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True) 77 75 78 76 def assignValidators(self): … … 80 78 Use options.FIT_FIELDS to assert which line edit gets what validator 81 79 """ 82 for option in bumps.options.FIT_FIELDS. iterkeys():80 for option in bumps.options.FIT_FIELDS.keys(): 83 81 (f_name, f_type) = bumps.options.FIT_FIELDS[option] 84 82 validator = None … … 86 84 validator = QtGui.QIntValidator() 87 85 validator.setBottom(0) 88 elif f_type == types.FloatType:89 validator = QtGui.QDoubleValidator()86 elif f_type == float: 87 validator = GuiUtils.DoubleValidator() 90 88 validator.setBottom(0) 91 89 else: … … 104 102 if state == QtGui.QValidator.Acceptable: 105 103 color = '' # default 106 self.buttonBox.button(Qt Gui.QDialogButtonBox.Ok).setEnabled(True)104 self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True) 107 105 else: 108 106 color = '#fff79a' # yellow 109 self.buttonBox.button(Qt Gui.QDialogButtonBox.Ok).setEnabled(False)107 self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) 110 108 111 109 sender.setStyleSheet('QLineEdit { background-color: %s }' % color) … … 134 132 135 133 # OK has to be reinitialized to True 136 self.buttonBox.button(Qt Gui.QDialogButtonBox.Ok).setEnabled(True)134 self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True) 137 135 138 136 def onApply(self): … … 148 146 """ 149 147 widget = self.widgetFromOption(option) 150 new_value = widget.currentText() if isinstance(widget, Qt Gui.QComboBox) \148 new_value = widget.currentText() if isinstance(widget, QtWidgets.QComboBox) \ 151 149 else float(widget.text()) 152 150 self.config.values[self.current_fitter_id][option] = new_value 153 151 154 152 # Update the BUMPS singleton 155 [bumpsUpdate(o) for o in self.config.values[self.current_fitter_id]. iterkeys()]153 [bumpsUpdate(o) for o in self.config.values[self.current_fitter_id].keys()] 156 154 157 155 def onHelp(self): … … 159 157 Show the "Fitting options" section of help 160 158 """ 161 tree_location = GuiUtils.HELP_DIRECTORY_LOCATION + "/user/sasgui/perspectives/fitting/" 159 tree_location = GuiUtils.HELP_DIRECTORY_LOCATION 160 tree_location += "/user/sasgui/perspectives/fitting/" 162 161 163 162 # Actual file anchor will depend on the combo box index … … 166 165 helpfile = "optimizer.html#fit-" + self.current_fitter_id 167 166 help_location = tree_location + helpfile 168 self.helpView.load(QtCore.QUrl(help_location)) 169 self.helpView.show() 167 webbrowser.open('file://' + os.path.realpath(help_location)) 170 168 171 169 def widgetFromOption(self, option_id, current_fitter=None): … … 175 173 if current_fitter is None: 176 174 current_fitter = self.current_fitter_id 177 if option_id not in bumps.options.FIT_FIELDS.keys(): return None175 if option_id not in list(bumps.options.FIT_FIELDS.keys()): return None 178 176 option = option_id + '_' + current_fitter 179 177 if not hasattr(self, option): return None … … 193 191 """ 194 192 options = self.config.values[fitter_id] 195 for option in options. iterkeys():193 for option in options.keys(): 196 194 # Find the widget name of the option 197 195 # e.g. 'samples' for 'dream' is 'self.samples_dream' -
src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
r377ade1 r14ec91c5 1 1 import numpy 2 2 3 from PyQt4 import QtCore 4 from PyQt4 import QtGui 3 from PyQt5 import QtCore 4 from PyQt5 import QtGui 5 from PyQt5 import QtWidgets 5 6 6 7 from bumps import options … … 10 11 11 12 from sas.qtgui.Perspectives.Fitting.FittingWidget import FittingWidget 13 from sas.qtgui.Perspectives.Fitting.ConstraintWidget import ConstraintWidget 12 14 from sas.qtgui.Perspectives.Fitting.FittingOptions import FittingOptions 13 from sas.qtgui.Perspectives.Fitting import ModelUtilities14 15 class FittingWindow(Qt Gui.QTabWidget):15 from sas.qtgui.Perspectives.Fitting.GPUOptions import GPUOptions 16 17 class FittingWindow(QtWidgets.QTabWidget): 16 18 """ 17 19 """ 20 tabsModifiedSignal = QtCore.pyqtSignal() 21 fittingStartedSignal = QtCore.pyqtSignal(list) 22 fittingStoppedSignal = QtCore.pyqtSignal(list) 23 18 24 name = "Fitting" # For displaying in the combo box in DataExplorer 19 25 def __init__(self, parent=None, data=None): 26 20 27 super(FittingWindow, self).__init__() 21 28 … … 35 42 self.optimizer = 'Levenberg-Marquardt' 36 43 37 # Dataset inde -> Fitting tab mapping44 # Dataset index -> Fitting tab mapping 38 45 self.dataToFitTab = {} 39 46 40 47 # The tabs need to be closeable 41 48 self.setTabsClosable(True) 49 50 # The tabs need to be movabe 51 self.setMovable(True) 42 52 43 53 self.communicate = self.parent.communicator() … … 49 59 self.tabCloseRequested.connect(self.tabCloses) 50 60 self.communicate.dataDeletedSignal.connect(self.dataDeleted) 61 self.fittingStartedSignal.connect(self.onFittingStarted) 62 self.fittingStoppedSignal.connect(self.onFittingStopped) 51 63 52 64 # Perspective window not allowed to close by default … … 61 73 self.fit_options_widget.fit_option_changed.connect(self.onFittingOptionsChange) 62 74 63 self.menu_manager = ModelUtilities.ModelManager() 64 # TODO: reuse these in FittingWidget properly 65 self.model_list_box = self.menu_manager.get_model_list() 66 self.model_dictionary = self.menu_manager.get_model_dictionary() 67 68 #self.setWindowTitle('Fit panel - Active Fitting Optimizer: %s' % self.optimizer) 75 # GPU Options 76 self.gpu_options_widget = GPUOptions(self) 77 69 78 self.updateWindowTitle() 70 79 … … 79 88 def setClosable(self, value=True): 80 89 """ 81 Allow outsiders close this widget90 Allow outsiders to close this widget 82 91 """ 83 92 assert isinstance(value, bool) … … 90 99 """ 91 100 # Invoke fit page events 92 for tab in self.tabs:93 tab.close()94 101 if self._allow_close: 95 102 # reset the closability flag 96 103 self.setClosable(value=False) 104 # Tell the MdiArea to close the container 105 self.parentWidget().close() 97 106 event.accept() 98 107 else: … … 108 117 tab.is_batch_fitting = is_batch 109 118 # Add this tab to the object library so it can be retrieved by scripting/jupyter 110 tab_name = self. tabName(is_batch=is_batch)119 tab_name = self.getTabName(is_batch=is_batch) 111 120 ObjectLibrary.addObject(tab_name, tab) 112 121 self.tabs.append(tab) … … 115 124 self.maxIndex += 1 116 125 self.addTab(tab, tab_name) 126 self.tabsModifiedSignal.emit() 127 128 def addConstraintTab(self): 129 """ 130 Add a new C&S fitting tab 131 """ 132 tabs = [isinstance(tab, ConstraintWidget) for tab in self.tabs] 133 if any(tabs): 134 # We already have a C&S tab: show it 135 self.setCurrentIndex(tabs.index(True)) 136 return 137 tab = ConstraintWidget(parent=self) 138 # Add this tab to the object library so it can be retrieved by scripting/jupyter 139 tab_name = self.getCSTabName() # TODO update the tab name scheme 140 ObjectLibrary.addObject(tab_name, tab) 141 self.tabs.append(tab) 142 self.addTab(tab, tab_name) 117 143 118 144 def updateFitDict(self, item_key, tab_name): … … 120 146 Create a list if none exists and append if there's already a list 121 147 """ 122 if item_key in self.dataToFitTab.keys(): 123 self.dataToFitTab[item_key].append(tab_name) 148 item_key_str = str(item_key) 149 if item_key_str in list(self.dataToFitTab.keys()): 150 self.dataToFitTab[item_key_str].append(tab_name) 124 151 else: 125 self.dataToFitTab[item_key] = [tab_name] 126 127 #print "CURRENT dict: ", self.dataToFitTab 128 129 def tabName(self, is_batch=False): 152 self.dataToFitTab[item_key_str] = [tab_name] 153 154 def getTabName(self, is_batch=False): 130 155 """ 131 156 Get the new tab name, based on the number of fitting tabs so far … … 133 158 page_name = "BatchPage" if is_batch else "FitPage" 134 159 page_name = page_name + str(self.maxIndex) 160 return page_name 161 162 def getCSTabName(self): 163 """ 164 Get the new tab name, based on the number of fitting tabs so far 165 """ 166 page_name = "Const. & Simul. Fit" 135 167 return page_name 136 168 … … 161 193 self.removeTab(index) 162 194 del self.tabs[index] 195 self.tabsModifiedSignal.emit() 163 196 except IndexError: 164 197 # The tab might have already been deleted previously … … 169 202 Given name of the fitting tab - close it 170 203 """ 171 for tab_index in xrange(len(self.tabs)):204 for tab_index in range(len(self.tabs)): 172 205 if self.tabText(tab_index) == tab_name: 173 206 self.tabCloses(tab_index) … … 181 214 return 182 215 for index_to_delete in index_list: 183 if index_to_delete in self.dataToFitTab.keys(): 184 for tab_name in self.dataToFitTab[index_to_delete]: 216 index_to_delete_str = str(index_to_delete) 217 if index_to_delete_str in list(self.dataToFitTab.keys()): 218 for tab_name in self.dataToFitTab[index_to_delete_str]: 185 219 # delete tab #index after corresponding data got removed 186 220 self.closeTabByName(tab_name) 187 self.dataToFitTab.pop(index_to_delete) 188 189 #print "CURRENT dict: ", self.dataToFitTab 221 self.dataToFitTab.pop(index_to_delete_str) 190 222 191 223 def allowBatch(self): … … 205 237 if not isinstance(data_item, list): 206 238 msg = "Incorrect type passed to the Fitting Perspective" 207 raise AttributeError , msg239 raise AttributeError(msg) 208 240 209 241 if not isinstance(data_item[0], QtGui.QStandardItem): 210 242 msg = "Incorrect type passed to the Fitting Perspective" 211 raise AttributeError, msg 243 raise AttributeError(msg) 244 245 if is_batch: 246 # Just create a new fit tab. No empty batchFit tabs 247 self.addFit(data_item, is_batch=is_batch) 248 return 212 249 213 250 items = [data_item] if is_batch else data_item 214 215 251 for data in items: 216 252 # Find the first unassigned tab. 217 253 # If none, open a new tab. 218 available_tabs = list(map(lambda tab: tab.acceptsData(), self.tabs))254 available_tabs = [tab.acceptsData() for tab in self.tabs] 219 255 220 256 if numpy.any(available_tabs): … … 236 272 self.updateWindowTitle() 237 273 274 def onFittingStarted(self, tabs_for_fitting=None): 275 """ 276 Notify tabs listed in tabs_for_fitting 277 that the fitting thread started 278 """ 279 assert(isinstance(tabs_for_fitting, list)) 280 assert(len(tabs_for_fitting)>0) 281 282 for tab_object in self.tabs: 283 if not isinstance(tab_object, FittingWidget): 284 continue 285 page_name = "Page%s"%tab_object.tab_id 286 if any([page_name in tab for tab in tabs_for_fitting]): 287 tab_object.setFittingStarted() 288 238 289 pass 290 291 def onFittingStopped(self, tabs_for_fitting=None): 292 """ 293 Notify tabs listed in tabs_for_fitting 294 that the fitting thread stopped 295 """ 296 assert(isinstance(tabs_for_fitting, list)) 297 assert(len(tabs_for_fitting)>0) 298 299 for tab_object in self.tabs: 300 if not isinstance(tab_object, FittingWidget): 301 continue 302 page_name = "Page%s"%tab_object.tab_id 303 if any([page_name in tab for tab in tabs_for_fitting]): 304 tab_object.setFittingStopped() 305 306 pass -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
rd0dfcb2 rfde5bcd 1 from copy import deepcopy 2 3 from PyQt4 import QtGui 4 from PyQt4 import QtCore 1 import copy 2 3 from PyQt5 import QtCore 4 from PyQt5 import QtGui 5 from PyQt5 import QtWidgets 5 6 6 7 import numpy … … 44 45 Returns a list of all multi-shell parameters in 'model' 45 46 """ 46 return list( filter(lambda par: "[" in par.name, model.iq_parameters))47 return list([par for par in model.iq_parameters if "[" in par.name]) 47 48 48 49 def getMultiplicity(model): … … 156 157 """ 157 158 for i, item in enumerate(model_header_captions): 158 model.setHeaderData(i, QtCore.Qt.Horizontal, QtCore.QVariant(item))159 160 model.header_tooltips = model_header_tooltips159 model.setHeaderData(i, QtCore.Qt.Horizontal, item) 160 161 model.header_tooltips = copy.copy(model_header_tooltips) 161 162 162 163 def addErrorHeadersToModel(model): … … 164 165 Adds predefined headers to the model 165 166 """ 166 model_header_error_captions = model_header_captions167 model_header_error_captions = copy.copy(model_header_captions) 167 168 model_header_error_captions.insert(2, header_error_caption) 168 169 for i, item in enumerate(model_header_error_captions): 169 model.setHeaderData(i, QtCore.Qt.Horizontal, QtCore.QVariant(item))170 171 model_header_error_tooltips = model_header_tooltips170 model.setHeaderData(i, QtCore.Qt.Horizontal, item) 171 172 model_header_error_tooltips = copy.copy(model_header_tooltips) 172 173 model_header_error_tooltips.insert(2, error_tooltip) 173 model.header_tooltips = model_header_error_tooltips174 model.header_tooltips = copy.copy(model_header_error_tooltips) 174 175 175 176 def addPolyHeadersToModel(model): … … 178 179 """ 179 180 for i, item in enumerate(poly_header_captions): 180 model.setHeaderData(i, QtCore.Qt.Horizontal, QtCore.QVariant(item))181 182 model.header_tooltips = poly_header_tooltip