Changeset 21e71f1 in sasview for src/sas/qtgui/MainWindow
- Timestamp:
- Nov 21, 2018 8:39:24 AM (6 years ago)
- Branches:
- ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- f2e199e
- Parents:
- 44c15fc (diff), fb39f28 (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. - Location:
- src/sas/qtgui/MainWindow
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/MainWindow/DataExplorer.py
r67346f9 re5ae812 238 238 Called when the "Open Project" menu item chosen. 239 239 """ 240 # check if any items loaded and warn about data deletion 241 if self.model.rowCount() > 0: 242 msg = "This operation will set remove all data, plots and analyses from" 243 msg += " SasView before loading the project. Do you wish to continue?" 244 msgbox = QtWidgets.QMessageBox(self) 245 msgbox.setIcon(QtWidgets.QMessageBox.Warning) 246 msgbox.setText(msg) 247 msgbox.setWindowTitle("Project Load") 248 # custom buttons 249 button_yes = QtWidgets.QPushButton("Yes") 250 msgbox.addButton(button_yes, QtWidgets.QMessageBox.YesRole) 251 button_no = QtWidgets.QPushButton("No") 252 msgbox.addButton(button_no, QtWidgets.QMessageBox.RejectRole) 253 retval = msgbox.exec_() 254 if retval == QtWidgets.QMessageBox.RejectRole: 255 # cancel fit 256 return 257 240 258 kwargs = { 241 259 'parent' : self, 242 260 'caption' : 'Open Project', 243 'filter' : 'Project (*.json);;All files (*.*)', 244 'options' : QtWidgets.QFileDialog.DontUseNativeDialog, 245 'directory' : self.default_project_location 261 'filter' : 'Project Files (*.json);;Old Project Files (*.svs);;All files (*.*)', 262 'options' : QtWidgets.QFileDialog.DontUseNativeDialog 246 263 } 247 264 filename = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0] 248 265 if filename: 249 266 self.default_project_location = os.path.dirname(filename) 250 load_thread = threads.deferToThread(self.readProject, filename) 251 load_thread.addCallback(self.readProjectComplete) 252 load_thread.addErrback(self.readProjectFailed) 253 254 def loadFailed(self, reason): 255 """ 256 """ 257 print("file load FAILED: ", reason) 258 pass 259 260 def readProjectFailed(self, reason): 261 """ 262 """ 263 print("readProjectFailed FAILED: ", reason) 264 pass 265 266 def readProject(self, filename): 267 self.communicator.statusBarUpdateSignal.emit("Loading Project... %s" % os.path.basename(filename)) 268 try: 269 manager = DataManager() 270 with open(filename, 'r') as infile: 271 manager.load_from_readable(infile) 272 273 self.communicator.statusBarUpdateSignal.emit("Loaded Project: %s" % os.path.basename(filename)) 274 return manager 275 276 except: 277 self.communicator.statusBarUpdateSignal.emit("Failed: %s" % os.path.basename(filename)) 278 raise 279 280 def readProjectComplete(self, manager): 281 self.model.clear() 282 283 self.manager.assign(manager) 284 self.model.beginResetModel() 285 for id, item in self.manager.get_all_data().items(): 286 self.updateModel(item.data, item.path) 287 288 self.model.endResetModel() 267 self.deleteAllItems() 268 self.readProject(filename) 269 270 def loadAnalysis(self): 271 """ 272 Called when the "Open Analysis" menu item chosen. 273 """ 274 kwargs = { 275 'parent' : self, 276 'caption' : 'Open Analysis', 277 'filter' : 'Project (*.fitv);;All files (*.*)', 278 'options' : QtWidgets.QFileDialog.DontUseNativeDialog 279 } 280 filename = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0] 281 if filename: 282 self.readProject(filename) 289 283 290 284 def saveProject(self): … … 301 295 name_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 302 296 filename = name_tuple[0] 303 if filename: 304 self.default_project_location = os.path.dirname(filename) 305 _, extension = os.path.splitext(filename) 306 if not extension: 307 filename = '.'.join((filename, 'json')) 308 self.communicator.statusBarUpdateSignal.emit("Saving Project... %s\n" % os.path.basename(filename)) 309 with open(filename, 'w') as outfile: 310 self.manager.save_to_writable(outfile) 297 if not filename: 298 return 299 self.default_project_location = os.path.dirname(filename) 300 _, extension = os.path.splitext(filename) 301 if not extension: 302 filename = '.'.join((filename, 'json')) 303 self.communicator.statusBarUpdateSignal.emit("Saving Project... %s\n" % os.path.basename(filename)) 304 305 return filename 306 307 def saveAsAnalysisFile(self, tab_id=1): 308 """ 309 Show the save as... dialog and return the chosen filepath 310 """ 311 default_name = "FitPage"+str(tab_id)+".fitv" 312 313 wildcard = "fitv files (*.fitv)" 314 kwargs = { 315 'caption' : 'Save As', 316 'directory' : default_name, 317 'filter' : wildcard, 318 'parent' : None, 319 } 320 # Query user for filename. 321 filename_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 322 filename = filename_tuple[0] 323 return filename 324 325 def saveAnalysis(self, data, tab_id=1): 326 """ 327 Called when the "Save Analysis" menu item chosen. 328 """ 329 filename = self.saveAsAnalysisFile(tab_id) 330 if not filename: 331 return 332 _, extension = os.path.splitext(filename) 333 if not extension: 334 filename = '.'.join((filename, 'fitv')) 335 self.communicator.statusBarUpdateSignal.emit("Saving analysis... %s\n" % os.path.basename(filename)) 336 337 with open(filename, 'w') as outfile: 338 GuiUtils.saveData(outfile, data) 339 340 self.communicator.statusBarUpdateSignal.emit('Analysis saved.') 341 342 def allDataForModel(self, model): 343 # data model 344 all_data = {} 345 for i in range(model.rowCount()): 346 properties = {} 347 item = model.item(i) 348 data = GuiUtils.dataFromItem(item) 349 if data is None: continue 350 # Now, all plots under this item 351 filename = data.filename 352 is_checked = item.checkState() 353 properties['checked'] = is_checked 354 other_datas = [] 355 # no need to save other_datas - things will be refit on read 356 #other_datas = GuiUtils.plotsFromFilename(filename, model) 357 # skip the main plot 358 #other_datas = list(other_datas.values())[1:] 359 all_data[data.id] = [data, properties, other_datas] 360 return all_data 361 362 def getDataForID(self, id): 363 # return the dataset with the given ID 364 all_data = [] 365 for model in (self.model, self.theory_model): 366 for i in range(model.rowCount()): 367 properties = {} 368 item = model.item(i) 369 data = GuiUtils.dataFromItem(item) 370 if data is None: continue 371 if data.id != id: continue 372 # We found the dataset - save it. 373 filename = data.filename 374 is_checked = item.checkState() 375 properties['checked'] = is_checked 376 other_datas = GuiUtils.plotsFromFilename(filename, model) 377 # skip the main plot 378 other_datas = list(other_datas.values())[1:] 379 all_data = [data, properties, other_datas] 380 break 381 return all_data 382 383 def getItemForID(self, id): 384 # return the model item with the given ID 385 item = None 386 for model in (self.model, self.theory_model): 387 for i in range(model.rowCount()): 388 properties = {} 389 item = model.item(i) 390 data = GuiUtils.dataFromItem(item) 391 if data is None: continue 392 if data.id != id: continue 393 # We found the item - return it 394 break 395 return item 396 397 def getAllData(self): 398 """ 399 converts all datasets into serializable dictionary 400 """ 401 data = self.allDataForModel(self.model) 402 theory = self.allDataForModel(self.theory_model) 403 404 all_data = {} 405 all_data['is_batch'] = str(self.chkBatch.isChecked()) 406 407 for key, value in data.items(): 408 all_data[key] = value 409 for key, value in theory.items(): 410 if key in all_data: 411 raise ValueError("Inconsistent data in Project file.") 412 all_data[key] = value 413 return all_data 414 415 def saveDataToFile(self, outfile): 416 """ 417 Save every dataset to a json file 418 """ 419 all_data = self.getAllData() 420 # save datas 421 GuiUtils.saveData(outfile, all_data) 422 423 def readProject(self, filename): 424 """ 425 Read out datasets and fitpages from file 426 """ 427 # Find out the filetype based on extension 428 ext = os.path.splitext(filename)[1] 429 all_data = {} 430 if 'svs' in ext.lower(): 431 # backward compatibility mode. 432 try: 433 datasets = GuiUtils.readProjectFromSVS(filename) 434 except Exception as ex: 435 # disregard malformed SVS and try to recover whatever 436 # is available 437 msg = "Error while reading the project file: "+str(ex) 438 logging.error(msg) 439 pass 440 # Convert fitpage properties and update the dict 441 try: 442 all_data = GuiUtils.convertFromSVS(datasets) 443 except Exception as ex: 444 # disregard malformed SVS and try to recover regardless 445 msg = "Error while converting the project file: "+str(ex) 446 logging.error(msg) 447 pass 448 else: 449 with open(filename, 'r') as infile: 450 try: 451 all_data = GuiUtils.readDataFromFile(infile) 452 except Exception as ex: 453 logging.error("Project load failed with " + str(ex)) 454 return 455 for key, value in all_data.items(): 456 if key=='is_batch': 457 self.chkBatch.setChecked(True if value=='True' else False) 458 continue 459 if 'cs_tab' in key: 460 continue 461 # send newly created items to the perspective 462 self.updatePerspectiveWithProperties(key, value) 463 464 # See if there are any batch pages defined and create them, if so 465 self.updateWithBatchPages(all_data) 466 467 # Only now can we create/assign C&S pages. 468 for key, value in all_data.items(): 469 if 'cs_tab' in key: 470 self.updatePerspectiveWithProperties(key, value) 471 472 def updateWithBatchPages(self, all_data): 473 """ 474 Checks all properties and see if there are any batch pages defined. 475 If so, pull out relevant indices and recreate the batch page(s) 476 """ 477 batch_pages = [] 478 for key, value in all_data.items(): 479 if 'fit_params' not in value: 480 continue 481 params = value['fit_params'] 482 for page in params: 483 if page['is_batch_fitting'][0] != 'True': 484 continue 485 batch_ids = page['data_id'][0] 486 # check for duplicates 487 batch_set = set(batch_ids) 488 if batch_set in batch_pages: 489 continue 490 # Found a unique batch page. Send it away 491 items = [self.getItemForID(i) for i in batch_set] 492 # Update the batch page list 493 batch_pages.append(batch_set) 494 # Assign parameters to the most recent (current) page. 495 self._perspective().setData(data_item=items, is_batch=True) 496 self._perspective().updateFromParameters(page) 497 pass 498 499 def updatePerspectiveWithProperties(self, key, value): 500 """ 501 """ 502 if 'fit_data' in value: 503 data_dict = {key:value['fit_data']} 504 # Create new model items in the data explorer 505 items = self.updateModelFromData(data_dict) 506 507 if 'fit_params' in value: 508 params = value['fit_params'] 509 # Make the perspective read the rest of the read data 510 if not isinstance(params, list): 511 params = [params] 512 for page in params: 513 # Check if this set of parameters is for a batch page 514 # if so, skip the update 515 if page['is_batch_fitting'][0] == 'True': 516 continue 517 # Send current model item to the perspective 518 self.sendItemToPerspective(items[0]) 519 # Assign parameters to the most recent (current) page. 520 self._perspective().updateFromParameters(page) 521 if 'cs_tab' in key and 'is_constraint' in value: 522 # Create a C&S page 523 self._perspective().addConstraintTab() 524 # Modify the tab 525 self._perspective().updateFromParameters(value) 526 527 pass # debugger 528 529 def updateModelFromData(self, data): 530 """ 531 Given data from analysis/project file, 532 create indices and populate data/theory models 533 """ 534 # model items for top level datasets 535 items = [] 536 for key, value in data.items(): 537 # key - cardinal number of dataset 538 # value - main dataset, [dependant filesets] 539 # add the main index 540 if not value: continue 541 #if key=='is_batch': 542 # self.chkBatch.setChecked(True if value=='True' else False) 543 # continue 544 new_data = value[0] 545 from sas.sascalc.dataloader.data_info import Data1D as old_data1d 546 from sas.sascalc.dataloader.data_info import Data2D as old_data2d 547 if isinstance(new_data, (old_data1d, old_data2d)): 548 new_data = self.manager.create_gui_data(value[0], new_data.filename) 549 assert isinstance(new_data, (Data1D, Data2D)) 550 properties = value[1] 551 is_checked = properties['checked'] 552 new_item = GuiUtils.createModelItemWithPlot(new_data, new_data.filename) 553 new_item.setCheckState(is_checked) 554 items.append(new_item) 555 model = self.theory_model 556 if new_data.is_data: 557 model = self.model 558 # Caption for the theories 559 new_item.setChild(2, QtGui.QStandardItem("FIT RESULTS")) 560 561 model.appendRow(new_item) 562 self.manager.add_data(data_list={new_data.id:new_data}) 563 564 # Add the underlying data 565 if not value[2]: 566 continue 567 for plot in value[2]: 568 assert isinstance(plot, (Data1D, Data2D)) 569 GuiUtils.updateModelItemWithPlot(new_item, plot, plot.name) 570 return items 311 571 312 572 def deleteFile(self, event): … … 424 684 retval = msgbox.exec_() 425 685 686 def sendItemToPerspective(self, item): 687 """ 688 Send the passed item data to the current perspective and set the relevant notifiers 689 """ 690 # Set the signal handlers 691 self.communicator.updateModelFromPerspectiveSignal.connect(self.updateModelFromPerspective) 692 selected_items = [item] 693 # Notify the GuiManager about the send request 694 try: 695 self._perspective().setData(data_item=selected_items, is_batch=False) 696 except Exception as ex: 697 msg = "%s perspective returned the following message: \n%s\n" %(self._perspective().name, str(ex)) 698 logging.error(msg) 699 msg = str(ex) 700 msgbox = QtWidgets.QMessageBox() 701 msgbox.setIcon(QtWidgets.QMessageBox.Critical) 702 msgbox.setText(msg) 703 msgbox.setStandardButtons(QtWidgets.QMessageBox.Ok) 704 retval = msgbox.exec_() 426 705 427 706 def freezeCheckedData(self): … … 1059 1338 self.actionQuick3DPlot.triggered.connect(self.quickData3DPlot) 1060 1339 self.actionEditMask.triggered.connect(self.showEditDataMask) 1061 self.actionDelete.triggered.connect(self.delete Item)1340 self.actionDelete.triggered.connect(self.deleteSelectedItem) 1062 1341 self.actionFreezeResults.triggered.connect(self.freezeSelectedItems) 1063 1342 … … 1271 1550 self.freezeItem(item_to_copy) 1272 1551 1273 def deleteItem(self): 1552 def deleteAllItems(self): 1553 """ 1554 Deletes all datasets from both model and theory_model 1555 """ 1556 deleted_items = [self.model.item(row) for row in range(self.model.rowCount()) 1557 if self.model.item(row).isCheckable()] 1558 deleted_names = [item.text() for item in deleted_items] 1559 # Let others know we deleted data 1560 self.communicator.dataDeletedSignal.emit(deleted_items) 1561 # update stored_data 1562 self.manager.update_stored_data(deleted_names) 1563 1564 # Clear the model 1565 self.model.clear() 1566 1567 def deleteSelectedItem(self): 1274 1568 """ 1275 1569 Delete the current item … … 1288 1582 return 1289 1583 1584 indices = self.current_view.selectedIndexes() 1585 self.deleteIndices(indices) 1586 1587 def deleteIndices(self, indices): 1588 """ 1589 Delete model idices from the current view 1590 """ 1591 proxy = self.current_view.model() 1592 model = proxy.sourceModel() 1593 1594 deleted_items = [] 1595 deleted_names = [] 1596 1290 1597 # Every time a row is removed, the indices change, so we'll just remove 1291 1598 # rows and keep calling selectedIndexes until it returns an empty list. 1292 indices = self.current_view.selectedIndexes()1293 1294 proxy = self.current_view.model()1295 model = proxy.sourceModel()1296 1297 deleted_items = []1298 deleted_names = []1299 1300 1599 while len(indices) > 0: 1301 1600 index = indices[0] 1302 row_index = proxy.mapToSource(index) 1303 item_to_delete = model.itemFromIndex(row_index) 1601 #row_index = proxy.mapToSource(index) 1602 #item_to_delete = model.itemFromIndex(row_index) 1603 item_to_delete = model.itemFromIndex(index) 1304 1604 if item_to_delete and item_to_delete.isCheckable(): 1305 row = row_index.row() 1605 #row = row_index.row() 1606 row = index.row() 1306 1607 1307 1608 # store the deleted item details so we can pass them on later … … 1430 1731 checkbox_item.setCheckable(True) 1431 1732 checkbox_item.setCheckState(QtCore.Qt.Checked) 1432 checkbox_item.setText(os.path.basename(p_file)) 1733 if p_file is not None: 1734 checkbox_item.setText(os.path.basename(p_file)) 1433 1735 1434 1736 # Add the actual Data1D/Data2D object -
src/sas/qtgui/MainWindow/DataManager.py
re2e5f3d r345b3b3 29 29 from sas.qtgui.Plotting.PlotterData import Data1D 30 30 from sas.qtgui.Plotting.PlotterData import Data2D 31 from sas.qtgui.Plotting.Plottables import Plottable32 31 from sas.qtgui.Plotting.Plottables import PlottableTheory1D 33 32 from sas.qtgui.Plotting.Plottables import PlottableFit1D -
src/sas/qtgui/MainWindow/GuiManager.py
r67346f9 re5ae812 255 255 if self._current_perspective: 256 256 self._current_perspective.setClosable() 257 #self._workspace.workspace.removeSubWindow(self._current_perspective)258 257 self._current_perspective.close() 259 258 self._workspace.workspace.removeSubWindow(self._current_perspective) … … 471 470 self._workspace.actionOpen_Project.triggered.connect(self.actionOpen_Project) 472 471 self._workspace.actionOpen_Analysis.triggered.connect(self.actionOpen_Analysis) 473 self._workspace.actionSave.triggered.connect(self.actionSave )472 self._workspace.actionSave.triggered.connect(self.actionSave_Project) 474 473 self._workspace.actionSave_Analysis.triggered.connect(self.actionSave_Analysis) 475 474 self._workspace.actionQuit.triggered.connect(self.actionQuit) … … 561 560 """ 562 561 """ 563 print("actionOpen_Analysis TRIGGERED")564 pass 565 566 def actionSave (self):562 self.filesWidget.loadAnalysis() 563 pass 564 565 def actionSave_Project(self): 567 566 """ 568 567 Menu Save Project 569 568 """ 570 self.filesWidget.saveProject() 569 filename = self.filesWidget.saveProject() 570 571 # datasets 572 all_data = self.filesWidget.getAllData() 573 574 # fit tabs 575 params={} 576 perspective = self.perspective() 577 if hasattr(perspective, 'isSerializable') and perspective.isSerializable(): 578 params = perspective.serializeAllFitpage() 579 580 # project dictionary structure: 581 # analysis[data.id] = [{"fit_data":[data, checkbox, child data], 582 # "fit_params":[fitpage_state]} 583 # "fit_params" not present if dataset not sent to fitting 584 analysis = {} 585 586 for id, data in all_data.items(): 587 if id=='is_batch': 588 analysis['is_batch'] = data 589 continue 590 data_content = {"fit_data":data} 591 if id in params.keys(): 592 # this dataset is represented also by the fit tab. Add to it. 593 data_content["fit_params"] = params[id] 594 analysis[id] = data_content 595 596 # standalone constraint pages 597 for keys, values in params.items(): 598 if not 'is_constraint' in values[0]: 599 continue 600 analysis[keys] = values[0] 601 602 with open(filename, 'w') as outfile: 603 GuiUtils.saveData(outfile, analysis) 571 604 572 605 def actionSave_Analysis(self): … … 574 607 Menu File/Save Analysis 575 608 """ 576 self.communicate.saveAnalysisSignal.emit() 609 per = self.perspective() 610 if not isinstance(per, FittingWindow): 611 return 612 # get fit page serialization 613 params = per.serializeCurrentFitpage() 614 # Find dataset ids for the current tab 615 # (can be multiple, if batch) 616 data_id = per.currentTabDataId() 617 tab_id = per.currentTab.tab_id 618 analysis = {} 619 for id in data_id: 620 an = {} 621 data_for_id = self.filesWidget.getDataForID(id) 622 an['fit_data'] = data_for_id 623 an['fit_params'] = [params] 624 analysis[id] = an 625 626 self.filesWidget.saveAnalysis(analysis, tab_id) 577 627 578 628 def actionQuit(self): … … 1056 1106 """ 1057 1107 self._workspace.actionReport.setEnabled(False) 1108 self._workspace.actionOpen_Analysis.setEnabled(False) 1109 self._workspace.actionSave_Analysis.setEnabled(False) 1110 if hasattr(perspective, 'isSerializable') and perspective.isSerializable(): 1111 self._workspace.actionOpen_Analysis.setEnabled(True) 1112 self._workspace.actionSave_Analysis.setEnabled(True) 1113 1058 1114 if isinstance(perspective, Perspectives.PERSPECTIVES["Fitting"]): 1059 1115 self.checkAnalysisOption(self._workspace.actionFitting) … … 1127 1183 out_f.write("#Application appearance custom configuration\n") 1128 1184 for key, item in config.__dict__.items(): 1129 if key[:2] != "__": 1130 if isinstance(item, str): 1131 item = '"' + item + '"' 1132 out_f.write("%s = %s\n" % (key, str(item))) 1185 if key[:2] == "__": 1186 continue 1187 if isinstance(item, str): 1188 item = '"' + item + '"' 1189 out_f.write("%s = %s\n" % (key, str(item))) 1133 1190 pass # debugger anchor -
src/sas/qtgui/MainWindow/UI/AcknowledgementsUI.ui
r7385fec recc5d043 10 10 <x>0</x> 11 11 <y>0</y> 12 <width> 508</width>13 <height> 283</height>12 <width>468</width> 13 <height>316</height> 14 14 </rect> 15 15 </property> … … 27 27 <widget class="QLabel" name="label"> 28 28 <property name="sizePolicy"> 29 <sizepolicy hsizetype="Preferred" vsizetype="Minimum ">29 <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> 30 30 <horstretch>0</horstretch> 31 31 <verstretch>0</verstretch> … … 35 35 <size> 36 36 <width>16777215</width> 37 <height> 41</height>37 <height>50</height> 38 38 </size> 39 39 </property> … … 46 46 <widget class="QTextBrowser" name="textBrowser"> 47 47 <property name="sizePolicy"> 48 <sizepolicy hsizetype="Expanding" vsizetype="Minimum ">48 <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding"> 49 49 <horstretch>0</horstretch> 50 50 <verstretch>0</verstretch> 51 51 </sizepolicy> 52 52 </property> 53 <property name="minimumSize"> 54 <size> 55 <width>0</width> 56 <height>85</height> 57 </size> 58 </property> 53 59 <property name="maximumSize"> 54 60 <size> 55 61 <width>16777215</width> 56 <height> 61</height>62 <height>85</height> 57 63 </size> 58 64 </property> … … 61 67 <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 62 68 p, li { white-space: pre-wrap; } 63 </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size: 8.25pt; font-weight:400; font-style:normal;">64 <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.</p></body></html></string>69 </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> 70 <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.</span></p></body></html></string> 65 71 </property> 66 72 </widget> … … 103 109 <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 104 110 p, li { white-space: pre-wrap; } 105 </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size: 8.25pt; font-weight:400; font-style:normal;">106 <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> M. Doucet et al. SasView Version 4.2, Zenodo, 10.5281/zenodo.1412041</p></body></html></string>111 </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> 112 <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">M. Doucet et al. SasView Version 4.2, Zenodo, 10.5281/zenodo.1412041</span></p></body></html></string> 107 113 </property> 108 114 </widget> … … 111 117 <widget class="QLabel" name="label_3"> 112 118 <property name="sizePolicy"> 113 <sizepolicy hsizetype="Preferred" vsizetype="Minimum ">119 <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> 114 120 <horstretch>0</horstretch> 115 121 <verstretch>0</verstretch> … … 119 125 <size> 120 126 <width>16777215</width> 121 <height> 38</height>127 <height>50</height> 122 128 </size> 123 129 </property> -
src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py
ra24eacf rb1b71ad 854 854 855 855 # Attempt at deleting 856 self.form.delete Item()856 self.form.deleteSelectedItem() 857 857 858 858 # Test the warning dialog called once … … 868 868 self.form.current_view.selectionModel().select(select_index, QtCore.QItemSelectionModel.Rows) 869 869 # delete it. now for good 870 self.form.delete Item()870 self.form.deleteSelectedItem() 871 871 872 872 # Test the warning dialog called once -
src/sas/qtgui/MainWindow/DroppableDataLoadWidget.py
r53c771e rba400d1 1 1 # global 2 import os 2 3 from PyQt5 import QtCore 3 4 from PyQt5 import QtGui … … 58 59 filenames=[] 59 60 for url in event.mimeData().urls(): 60 filenames.append(url.toLocalFile()) 61 files = url.toLocalFile() 62 if os.path.isdir(files): 63 # get content of dir into a list 64 content = [os.path.join(os.path.abspath(files), filename) 65 for filename in os.listdir(files)] 66 filenames += content 67 else: 68 filenames.append(files) 61 69 self.communicator.fileReadSignal.emit(filenames) 62 70 event.accept()
Note: See TracChangeset
for help on using the changeset viewer.