source: sasview/src/sas/qtgui/MainWindow/GuiManager.py @ f0bb711

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since f0bb711 was f0bb711, checked in by celinedurniak <celine.durniak@…>, 7 years ago

Implemented comments from review for Data Operation Panel (ESS-GUI-SasView?-245)

  • Property mode set to 100644
File size: 25.6 KB
Line 
1import sys
2import os
3import subprocess
4import logging
5import json
6import webbrowser
7
8from PyQt4 import QtCore
9from PyQt4 import QtGui
10from PyQt4 import QtWebKit
11
12from twisted.internet import reactor
13# General SAS imports
14from sas.qtgui.Utilities.ConnectionProxy import ConnectionProxy
15from sas.qtgui.Utilities.SasviewLogger import XStream
16
17import sas.qtgui.Utilities.LocalConfig as LocalConfig
18import sas.qtgui.Utilities.GuiUtils as GuiUtils
19
20import sas.qtgui.Utilities.ObjectLibrary as ObjectLibrary
21from sas.qtgui.MainWindow.UI.AcknowledgementsUI import Ui_Acknowledgements
22from sas.qtgui.MainWindow.AboutBox import AboutBox
23from sas.qtgui.MainWindow.WelcomePanel import WelcomePanel
24
25from sas.qtgui.MainWindow.DataManager import DataManager
26
27from sas.qtgui.Calculators.SldPanel import SldPanel
28from sas.qtgui.Calculators.DensityPanel import DensityPanel
29from sas.qtgui.Calculators.KiessigPanel import KiessigPanel
30from sas.qtgui.Calculators.SlitSizeCalculator import SlitSizeCalculator
31from sas.qtgui.Calculators.GenericScatteringCalculator import GenericScatteringCalculator
32from sas.qtgui.Calculators.ResolutionCalculatorPanel import ResolutionCalculatorPanel
33from sas.qtgui.Calculators.DataOperationUtilityPanel import DataOperationUtilityPanel
34
35# Perspectives
36import sas.qtgui.Perspectives as Perspectives
37from sas.qtgui.Perspectives.Fitting.FittingPerspective import FittingWindow
38from sas.qtgui.MainWindow.DataExplorer import DataExplorerWindow
39
40class Acknowledgements(QtGui.QDialog, Ui_Acknowledgements):
41    def __init__(self, parent=None):
42        QtGui.QDialog.__init__(self, parent)
43        self.setupUi(self)
44
45class GuiManager(object):
46    """
47    Main SasView window functionality
48    """
49
50    def __init__(self, parent=None):
51        """
52        Initialize the manager as a child of MainWindow.
53        """
54        self._workspace = parent
55        self._parent = parent
56
57        # Add signal callbacks
58        self.addCallbacks()
59
60        # Create the data manager
61        # TODO: pull out all required methods from DataManager and reimplement
62        self._data_manager = DataManager()
63
64        # Create action triggers
65        self.addTriggers()
66
67        # Populate menus with dynamic data
68        #
69        # Analysis/Perspectives - potentially
70        # Window/current windows
71        #
72        # Widgets
73        #
74        # Current displayed perspective
75        self._current_perspective = None
76
77        # Invoke the initial perspective
78        self.perspectiveChanged("Fitting")
79
80        self.addWidgets()
81
82        # Fork off logging messages to the Log Window
83        XStream.stdout().messageWritten.connect(self.listWidget.insertPlainText)
84        XStream.stderr().messageWritten.connect(self.listWidget.insertPlainText)
85
86        # Log the start of the session
87        logging.info(" --- SasView session started ---")
88        # Log the python version
89        logging.info("Python: %s" % sys.version)
90
91        # Set up the status bar
92        self.statusBarSetup()
93
94        # Show the Welcome panel
95        self.welcomePanel = WelcomePanel()
96        self._workspace.workspace.addWindow(self.welcomePanel)
97
98        # Current help file
99        self._helpView = QtWebKit.QWebView()
100        # Needs URL like path, so no path.join() here
101        self._helpLocation = GuiUtils.HELP_DIRECTORY_LOCATION + "/index.html"
102
103        # Current tutorial location
104        self._tutorialLocation = os.path.abspath(os.path.join(GuiUtils.HELP_DIRECTORY_LOCATION,
105                                              "_downloads",
106                                              "Tutorial.pdf"))
107    def addWidgets(self):
108        """
109        Populate the main window with widgets
110
111        TODO: overwrite close() on Log and DR widgets so they can be hidden/shown
112        on request
113        """
114        # Add FileDialog widget as docked
115        self.filesWidget = DataExplorerWindow(self._parent, self, manager=self._data_manager)
116        ObjectLibrary.addObject('DataExplorer', self.filesWidget)
117
118        self.dockedFilesWidget = QtGui.QDockWidget("Data Explorer", self._workspace)
119        self.dockedFilesWidget.setWidget(self.filesWidget)
120
121        # Disable maximize/minimize and close buttons
122        self.dockedFilesWidget.setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures)
123        self._workspace.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
124                                      self.dockedFilesWidget)
125
126        # Add the console window as another docked widget
127        self.logDockWidget = QtGui.QDockWidget("Log Explorer", self._workspace)
128        self.logDockWidget.setObjectName("LogDockWidget")
129        self.listWidget = QtGui.QTextBrowser()
130        self.logDockWidget.setWidget(self.listWidget)
131        self._workspace.addDockWidget(QtCore.Qt.BottomDockWidgetArea,
132                                      self.logDockWidget)
133
134        # Add other, minor widgets
135        self.ackWidget = Acknowledgements()
136        self.aboutWidget = AboutBox()
137
138        # Add calculators - floating for usability
139        self.SLDCalculator = SldPanel(self)
140        self.DVCalculator = DensityPanel(self)
141        self.KIESSIGCalculator = KiessigPanel(self)
142        self.SlitSizeCalculator = SlitSizeCalculator(self)
143        self.GENSASCalculator = GenericScatteringCalculator(self)
144        self.ResolutionCalculator = ResolutionCalculatorPanel(self)
145        self.DataOperation = DataOperationUtilityPanel(self)
146
147    def statusBarSetup(self):
148        """
149        Define the status bar.
150        | <message label> .... | Progress Bar |
151
152        Progress bar invisible until explicitly shown
153        """
154        self.progress = QtGui.QProgressBar()
155        self._workspace.statusbar.setSizeGripEnabled(False)
156
157        self.statusLabel = QtGui.QLabel()
158        self.statusLabel.setText("Welcome to SasView")
159        self._workspace.statusbar.addPermanentWidget(self.statusLabel, 1)
160        self._workspace.statusbar.addPermanentWidget(self.progress, stretch=0)
161        self.progress.setRange(0, 100)
162        self.progress.setValue(0)
163        self.progress.setTextVisible(True)
164        self.progress.setVisible(False)
165
166    def fileWasRead(self, data):
167        """
168        Callback for fileDataReceivedSignal
169        """
170        pass
171
172    def workspace(self):
173        """
174        Accessor for the main window workspace
175        """
176        return self._workspace.workspace
177
178    def perspectiveChanged(self, perspective_name):
179        """
180        Respond to change of the perspective signal
181        """
182        # Close the previous perspective
183        if self._current_perspective:
184            self._current_perspective.setClosable()
185            self._current_perspective.close()
186        # Default perspective
187        self._current_perspective = Perspectives.PERSPECTIVES[str(perspective_name)](parent=self)
188
189        self._workspace.workspace.addWindow(self._current_perspective)
190        # Resize to the workspace height
191        workspace_height = self._workspace.workspace.sizeHint().height()
192        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)
196        self._current_perspective.show()
197
198    def updatePerspective(self, data):
199        """
200        Update perspective with data sent.
201        """
202        assert isinstance(data, list)
203        if self._current_perspective is not None:
204            self._current_perspective.setData(data.values())
205        else:
206            msg = "No perspective is currently active."
207            logging.info(msg)
208
209    def communicator(self):
210        """ Accessor for the communicator """
211        return self.communicate
212
213    def perspective(self):
214        """ Accessor for the perspective """
215        return self._current_perspective
216
217    def updateProgressBar(self, value):
218        """
219        Update progress bar with the required value (0-100)
220        """
221        assert -1 <= value <= 100
222        if value == -1:
223            self.progress.setVisible(False)
224            return
225        if not self.progress.isVisible():
226            self.progress.setTextVisible(True)
227            self.progress.setVisible(True)
228
229        self.progress.setValue(value)
230
231    def updateStatusBar(self, text):
232        """
233        Set the status bar text
234        """
235        self.statusLabel.setText(text)
236
237    def createGuiData(self, item, p_file=None):
238        """
239        Access the Data1D -> plottable Data1D conversion
240        """
241        return self._data_manager.create_gui_data(item, p_file)
242
243    def setData(self, data):
244        """
245        Sends data to current perspective
246        """
247        if self._current_perspective is not None:
248            self._current_perspective.setData(data.values())
249        else:
250            msg = "Guiframe does not have a current perspective"
251            logging.info(msg)
252
253    def quitApplication(self):
254        """
255        Close the reactor and exit nicely.
256        """
257        # Display confirmation messagebox
258        quit_msg = "Are you sure you want to exit the application?"
259        reply = QtGui.QMessageBox.question(
260            self._parent,
261            'Information',
262            quit_msg,
263            QtGui.QMessageBox.Yes,
264            QtGui.QMessageBox.No)
265
266        # Exit if yes
267        if reply == QtGui.QMessageBox.Yes:
268            reactor.callFromThread(reactor.stop)
269            return True
270
271        return False
272
273    def checkUpdate(self):
274        """
275        Check with the deployment server whether a new version
276        of the application is available.
277        A thread is started for the connecting with the server. The thread calls
278        a call-back method when the current version number has been obtained.
279        """
280        version_info = {"version": "0.0.0"}
281        c = ConnectionProxy(LocalConfig.__update_URL__, LocalConfig.UPDATE_TIMEOUT)
282        response = c.connect()
283        if response is None:
284            return
285        try:
286            content = response.read().strip()
287            logging.info("Connected to www.sasview.org. Latest version: %s"
288                            % (content))
289            version_info = json.loads(content)
290            self.processVersion(version_info)
291        except ValueError, ex:
292            logging.info("Failed to connect to www.sasview.org:", ex)
293
294    def processVersion(self, version_info):
295        """
296        Call-back method for the process of checking for updates.
297        This methods is called by a VersionThread object once the current
298        version number has been obtained. If the check is being done in the
299        background, the user will not be notified unless there's an update.
300
301        :param version: version string
302        """
303        try:
304            version = version_info["version"]
305            if version == "0.0.0":
306                msg = "Could not connect to the application server."
307                msg += " Please try again later."
308                self.communicate.statusBarUpdateSignal.emit(msg)
309
310            elif cmp(version, LocalConfig.__version__) > 0:
311                msg = "Version %s is available! " % str(version)
312                if "download_url" in version_info:
313                    webbrowser.open(version_info["download_url"])
314                else:
315                    webbrowser.open(LocalConfig.__download_page__)
316                self.communicate.statusBarUpdateSignal.emit(msg)
317            else:
318                msg = "You have the latest version"
319                msg += " of %s" % str(LocalConfig.__appname__)
320                self.communicate.statusBarUpdateSignal.emit(msg)
321        except:
322            msg = "guiframe: could not get latest application"
323            msg += " version number\n  %s" % sys.exc_value
324            logging.error(msg)
325            msg = "Could not connect to the application server."
326            msg += " Please try again later."
327            self.communicate.statusBarUpdateSignal.emit(msg)
328
329    def addCallbacks(self):
330        """
331        Method defining all signal connections for the gui manager
332        """
333        self.communicate = GuiUtils.Communicate()
334        self.communicate.fileDataReceivedSignal.connect(self.fileWasRead)
335        self.communicate.statusBarUpdateSignal.connect(self.updateStatusBar)
336        self.communicate.updatePerspectiveWithDataSignal.connect(self.updatePerspective)
337        self.communicate.progressBarUpdateSignal.connect(self.updateProgressBar)
338        self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged)
339        self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective)
340        self.communicate.plotRequestedSignal.connect(self.showPlot)
341        self.communicate.updateModelFromDataOperationPanelSignal.connect(self.updateModelFromDataOperationPanel)
342
343    def addTriggers(self):
344        """
345        Trigger definitions for all menu/toolbar actions.
346        """
347        # File
348        self._workspace.actionLoadData.triggered.connect(self.actionLoadData)
349        self._workspace.actionLoad_Data_Folder.triggered.connect(self.actionLoad_Data_Folder)
350        self._workspace.actionOpen_Project.triggered.connect(self.actionOpen_Project)
351        self._workspace.actionOpen_Analysis.triggered.connect(self.actionOpen_Analysis)
352        self._workspace.actionSave.triggered.connect(self.actionSave)
353        self._workspace.actionSave_Analysis.triggered.connect(self.actionSave_Analysis)
354        self._workspace.actionQuit.triggered.connect(self.actionQuit)
355        # Edit
356        self._workspace.actionUndo.triggered.connect(self.actionUndo)
357        self._workspace.actionRedo.triggered.connect(self.actionRedo)
358        self._workspace.actionCopy.triggered.connect(self.actionCopy)
359        self._workspace.actionPaste.triggered.connect(self.actionPaste)
360        self._workspace.actionReport.triggered.connect(self.actionReport)
361        self._workspace.actionReset.triggered.connect(self.actionReset)
362        self._workspace.actionExcel.triggered.connect(self.actionExcel)
363        self._workspace.actionLatex.triggered.connect(self.actionLatex)
364
365        # View
366        self._workspace.actionShow_Grid_Window.triggered.connect(self.actionShow_Grid_Window)
367        self._workspace.actionHide_Toolbar.triggered.connect(self.actionHide_Toolbar)
368        self._workspace.actionStartup_Settings.triggered.connect(self.actionStartup_Settings)
369        self._workspace.actionCategry_Manager.triggered.connect(self.actionCategry_Manager)
370        # Tools
371        self._workspace.actionData_Operation.triggered.connect(self.actionData_Operation)
372        self._workspace.actionSLD_Calculator.triggered.connect(self.actionSLD_Calculator)
373        self._workspace.actionDensity_Volume_Calculator.triggered.connect(self.actionDensity_Volume_Calculator)
374        self._workspace.actionKeissig_Calculator.triggered.connect(self.actionKiessig_Calculator)
375        #self._workspace.actionKIESSING_Calculator.triggered.connect(self.actionKIESSING_Calculator)
376        self._workspace.actionSlit_Size_Calculator.triggered.connect(self.actionSlit_Size_Calculator)
377        self._workspace.actionSAS_Resolution_Estimator.triggered.connect(self.actionSAS_Resolution_Estimator)
378        self._workspace.actionGeneric_Scattering_Calculator.triggered.connect(self.actionGeneric_Scattering_Calculator)
379        self._workspace.actionPython_Shell_Editor.triggered.connect(self.actionPython_Shell_Editor)
380        self._workspace.actionImage_Viewer.triggered.connect(self.actionImage_Viewer)
381        # Fitting
382        self._workspace.actionNew_Fit_Page.triggered.connect(self.actionNew_Fit_Page)
383        self._workspace.actionConstrained_Fit.triggered.connect(self.actionConstrained_Fit)
384        self._workspace.actionCombine_Batch_Fit.triggered.connect(self.actionCombine_Batch_Fit)
385        self._workspace.actionFit_Options.triggered.connect(self.actionFit_Options)
386        self._workspace.actionFit_Results.triggered.connect(self.actionFit_Results)
387        self._workspace.actionChain_Fitting.triggered.connect(self.actionChain_Fitting)
388        self._workspace.actionEdit_Custom_Model.triggered.connect(self.actionEdit_Custom_Model)
389        # Window
390        self._workspace.actionCascade.triggered.connect(self.actionCascade)
391        self._workspace.actionTile.triggered.connect(self.actionTile)
392        self._workspace.actionArrange_Icons.triggered.connect(self.actionArrange_Icons)
393        self._workspace.actionNext.triggered.connect(self.actionNext)
394        self._workspace.actionPrevious.triggered.connect(self.actionPrevious)
395        # Analysis
396        self._workspace.actionFitting.triggered.connect(self.actionFitting)
397        self._workspace.actionInversion.triggered.connect(self.actionInversion)
398        self._workspace.actionInvariant.triggered.connect(self.actionInvariant)
399        # Help
400        self._workspace.actionDocumentation.triggered.connect(self.actionDocumentation)
401        self._workspace.actionTutorial.triggered.connect(self.actionTutorial)
402        self._workspace.actionAcknowledge.triggered.connect(self.actionAcknowledge)
403        self._workspace.actionAbout.triggered.connect(self.actionAbout)
404        self._workspace.actionCheck_for_update.triggered.connect(self.actionCheck_for_update)
405
406    #============ FILE =================
407    def actionLoadData(self):
408        """
409        Menu File/Load Data File(s)
410        """
411        self.filesWidget.loadFile()
412
413    def actionLoad_Data_Folder(self):
414        """
415        Menu File/Load Data Folder
416        """
417        self.filesWidget.loadFolder()
418
419    def actionOpen_Project(self):
420        """
421        Menu Open Project
422        """
423        self.filesWidget.loadProject()
424
425    def actionOpen_Analysis(self):
426        """
427        """
428        print("actionOpen_Analysis TRIGGERED")
429        pass
430
431    def actionSave(self):
432        """
433        Menu Save Project
434        """
435        self.filesWidget.saveProject()
436
437    def actionSave_Analysis(self):
438        """
439        """
440        print("actionSave_Analysis TRIGGERED")
441
442        pass
443
444    def actionQuit(self):
445        """
446        Close the reactor, exit the application.
447        """
448        self.quitApplication()
449
450    #============ EDIT =================
451    def actionUndo(self):
452        """
453        """
454        print("actionUndo TRIGGERED")
455        pass
456
457    def actionRedo(self):
458        """
459        """
460        print("actionRedo TRIGGERED")
461        pass
462
463    def actionCopy(self):
464        """
465        """
466        print("actionCopy TRIGGERED")
467        pass
468
469    def actionPaste(self):
470        """
471        """
472        print("actionPaste TRIGGERED")
473        pass
474
475    def actionReport(self):
476        """
477        """
478        print("actionReport TRIGGERED")
479        pass
480
481    def actionReset(self):
482        """
483        """
484        logging.warning(" *** actionOpen_Analysis logging *******")
485        print("actionReset print TRIGGERED")
486        sys.stderr.write("STDERR - TRIGGERED")
487        pass
488
489    def actionExcel(self):
490        """
491        """
492        print("actionExcel TRIGGERED")
493        pass
494
495    def actionLatex(self):
496        """
497        """
498        print("actionLatex TRIGGERED")
499        pass
500
501    #============ VIEW =================
502    def actionShow_Grid_Window(self):
503        """
504        """
505        print("actionShow_Grid_Window TRIGGERED")
506        pass
507
508    def actionHide_Toolbar(self):
509        """
510        Toggle toolbar vsibility
511        """
512        if self._workspace.toolBar.isVisible():
513            self._workspace.actionHide_Toolbar.setText("Show Toolbar")
514            self._workspace.toolBar.setVisible(False)
515        else:
516            self._workspace.actionHide_Toolbar.setText("Hide Toolbar")
517            self._workspace.toolBar.setVisible(True)
518        pass
519
520    def actionStartup_Settings(self):
521        """
522        """
523        print("actionStartup_Settings TRIGGERED")
524        pass
525
526    def actionCategry_Manager(self):
527        """
528        """
529        print("actionCategry_Manager TRIGGERED")
530        pass
531
532    #============ TOOLS =================
533    def actionData_Operation(self):
534        """
535        """
536        self.communicate.sendDataToPanelSignal.emit(self._data_manager.get_all_data())
537
538        self.DataOperation.show()
539
540    def actionSLD_Calculator(self):
541        """
542        """
543        self.SLDCalculator.show()
544
545    def actionDensity_Volume_Calculator(self):
546        """
547        """
548        self.DVCalculator.show()
549
550    def actionKiessig_Calculator(self):
551        """
552        """
553        #self.DVCalculator.show()
554        self.KIESSIGCalculator.show()
555
556    def actionSlit_Size_Calculator(self):
557        """
558        """
559        self.SlitSizeCalculator.show()
560
561    def actionSAS_Resolution_Estimator(self):
562        """
563        """
564        self.ResolutionCalculator.show()
565
566    def actionGeneric_Scattering_Calculator(self):
567        """
568        """
569        self.GENSASCalculator.show()
570
571    def actionPython_Shell_Editor(self):
572        """
573        Display the Jupyter console as a docked widget.
574        """
575        # Import moved here for startup performance reasons
576        from sas.qtgui.Utilities.IPythonWidget import IPythonWidget
577        terminal = IPythonWidget()
578
579        # Add the console window as another docked widget
580        self.ipDockWidget = QtGui.QDockWidget("IPython", self._workspace)
581        self.ipDockWidget.setObjectName("IPythonDockWidget")
582        self.ipDockWidget.setWidget(terminal)
583        self._workspace.addDockWidget(QtCore.Qt.RightDockWidgetArea,
584                                      self.ipDockWidget)
585
586    def actionImage_Viewer(self):
587        """
588        """
589        print("actionImage_Viewer TRIGGERED")
590        pass
591
592    #============ FITTING =================
593    def actionNew_Fit_Page(self):
594        """
595        Add a new, empty Fit page in the fitting perspective.
596        """
597        # Make sure the perspective is correct
598        per = self.perspective()
599        if not isinstance(per, FittingWindow):
600            return
601        per.addFit(None)
602
603    def actionConstrained_Fit(self):
604        """
605        """
606        print("actionConstrained_Fit TRIGGERED")
607        pass
608
609    def actionCombine_Batch_Fit(self):
610        """
611        """
612        print("actionCombine_Batch_Fit TRIGGERED")
613        pass
614
615    def actionFit_Options(self):
616        """
617        """
618        if getattr(self._current_perspective, "fit_options_widget"):
619            self._current_perspective.fit_options_widget.show()
620        pass
621
622    def actionFit_Results(self):
623        """
624        """
625        print("actionFit_Results TRIGGERED")
626        pass
627
628    def actionChain_Fitting(self):
629        """
630        """
631        print("actionChain_Fitting TRIGGERED")
632        pass
633
634    def actionEdit_Custom_Model(self):
635        """
636        """
637        print("actionEdit_Custom_Model TRIGGERED")
638        pass
639
640    #============ ANALYSIS =================
641    def actionFitting(self):
642        """
643        """
644        print("actionFitting TRIGGERED")
645        pass
646
647    def actionInversion(self):
648        """
649        """
650        print("actionInversion TRIGGERED")
651        pass
652
653    def actionInvariant(self):
654        """
655        """
656        print("actionInvariant TRIGGERED")
657        pass
658
659    #============ WINDOW =================
660    def actionCascade(self):
661        """
662        Arranges all the child windows in a cascade pattern.
663        """
664        self._workspace.workspace.cascade()
665
666    def actionTile(self):
667        """
668        Tile workspace windows
669        """
670        self._workspace.workspace.tile()
671
672    def actionArrange_Icons(self):
673        """
674        Arranges all iconified windows at the bottom of the workspace
675        """
676        self._workspace.workspace.arrangeIcons()
677
678    def actionNext(self):
679        """
680        Gives the input focus to the next window in the list of child windows.
681        """
682        self._workspace.workspace.activateNextWindow()
683
684    def actionPrevious(self):
685        """
686        Gives the input focus to the previous window in the list of child windows.
687        """
688        self._workspace.workspace.activatePreviousWindow()
689
690    #============ HELP =================
691    def actionDocumentation(self):
692        """
693        Display the documentation
694
695        TODO: use QNetworkAccessManager to assure _helpLocation is valid
696        """
697        self._helpView.load(QtCore.QUrl(self._helpLocation))
698        self._helpView.show()
699
700    def actionTutorial(self):
701        """
702        Open the tutorial PDF file with default PDF renderer
703        """
704        # Not terribly safe here. Shell injection warning.
705        # isfile() helps but this probably needs a better solution.
706        if os.path.isfile(self._tutorialLocation):
707            result = subprocess.Popen([self._tutorialLocation], shell=True)
708
709    def actionAcknowledge(self):
710        """
711        Open the Acknowledgements widget
712        """
713        self.ackWidget.show()
714
715    def actionAbout(self):
716        """
717        Open the About box
718        """
719        # Update the about box with current version and stuff
720
721        # TODO: proper sizing
722        self.aboutWidget.show()
723
724    def actionCheck_for_update(self):
725        """
726        Menu Help/Check for Update
727        """
728        self.checkUpdate()
729
730    def updateTheoryFromPerspective(self, index):
731        """
732        Catch the theory update signal from a perspective
733        Send the request to the DataExplorer for updating the theory model.
734        """
735        self.filesWidget.updateTheoryFromPerspective(index)
736
737    def updateModelFromDataOperationPanel(self, new_item, new_datalist_item):
738        """
739        :param new_item: item to be added to list of loaded files
740        :param new_datalist_item:
741        """
742        if not isinstance(new_item, QtGui.QStandardItem) or \
743                not isinstance(new_datalist_item, dict):
744            msg = "Wrong data type returned from calculations."
745            raise AttributeError, msg
746
747        self.filesWidget.model.appendRow(new_item)
748        self._data_manager.add_data(new_datalist_item)
749
750    def showPlot(self, plot):
751        """
752        Pass the show plot request to the data explorer
753        """
754        if hasattr(self, "filesWidget"):
755            self.filesWidget.displayData(plot)
Note: See TracBrowser for help on using the repository browser.