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

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 a6cd8d1 was a6cd8d1, checked in by krzywon, 7 years ago

GUI hooks added, but not all working.

  • Property mode set to 100644
File size: 25.9 KB
RevLine 
[f721030]1import sys
[0cd8612]2import os
[9e426c1]3import subprocess
4import logging
5import json
6import webbrowser
[f721030]7
8from PyQt4 import QtCore
9from PyQt4 import QtGui
[1042dba]10from PyQt4 import QtWebKit
11
12from twisted.internet import reactor
[dc5ef15]13# General SAS imports
14from sas.qtgui.Utilities.ConnectionProxy import ConnectionProxy
[83eb5208]15from sas.qtgui.Utilities.SasviewLogger import XStream
[fef38e8]16
[83eb5208]17import sas.qtgui.Utilities.LocalConfig as LocalConfig
18import sas.qtgui.Utilities.GuiUtils as GuiUtils
19
[fef38e8]20import sas.qtgui.Utilities.ObjectLibrary as ObjectLibrary
[83eb5208]21from sas.qtgui.MainWindow.UI.AcknowledgementsUI import Ui_Acknowledgements
22from sas.qtgui.MainWindow.AboutBox import AboutBox
23from sas.qtgui.MainWindow.WelcomePanel import WelcomePanel
[fef38e8]24
[dc5ef15]25from sas.qtgui.MainWindow.DataManager import DataManager
[83eb5208]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
[28a09b0]31from sas.qtgui.Calculators.GenericScatteringCalculator import GenericScatteringCalculator
[01cda57]32from sas.qtgui.Calculators.ResolutionCalculatorPanel import ResolutionCalculatorPanel
[d5c5d3d]33from sas.qtgui.Calculators.DataOperationUtilityPanel import DataOperationUtilityPanel
[f721030]34
35# Perspectives
[83eb5208]36import sas.qtgui.Perspectives as Perspectives
[6c8fb2c]37from sas.qtgui.Perspectives.Fitting.FittingPerspective import FittingWindow
[83eb5208]38from sas.qtgui.MainWindow.DataExplorer import DataExplorerWindow
[f51ed67]39
40class Acknowledgements(QtGui.QDialog, Ui_Acknowledgements):
41    def __init__(self, parent=None):
42        QtGui.QDialog.__init__(self, parent)
43        self.setupUi(self)
[f721030]44
45class GuiManager(object):
46    """
47    Main SasView window functionality
48    """
[d5c5d3d]49
[6fd4e36]50    def __init__(self, parent=None):
[f721030]51        """
[257bd57]52        Initialize the manager as a child of MainWindow.
[f721030]53        """
[6fd4e36]54        self._workspace = parent
[f721030]55        self._parent = parent
56
57        # Add signal callbacks
58        self.addCallbacks()
59
60        # Create the data manager
[1042dba]61        # TODO: pull out all required methods from DataManager and reimplement
62        self._data_manager = DataManager()
[f721030]63
64        # Create action triggers
65        self.addTriggers()
66
67        # Populate menus with dynamic data
[481ff26]68        #
[f721030]69        # Analysis/Perspectives - potentially
70        # Window/current windows
71        #
72        # Widgets
73        #
[5236449]74        # Current displayed perspective
75        self._current_perspective = None
76
77        # Invoke the initial perspective
78        self.perspectiveChanged("Fitting")
79
[0cd8612]80        self.addWidgets()
[f721030]81
[0cd8612]82        # Fork off logging messages to the Log Window
[8cb6cd6]83        XStream.stdout().messageWritten.connect(self.listWidget.insertPlainText)
84        XStream.stderr().messageWritten.connect(self.listWidget.insertPlainText)
85
[0cd8612]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)
[9e426c1]90
[e540cd2]91        # Set up the status bar
92        self.statusBarSetup()
[9e426c1]93
[f721030]94        # Show the Welcome panel
95        self.welcomePanel = WelcomePanel()
96        self._workspace.workspace.addWindow(self.welcomePanel)
97
[1042dba]98        # Current help file
99        self._helpView = QtWebKit.QWebView()
[9e426c1]100        # Needs URL like path, so no path.join() here
[b0c5e8c]101        self._helpLocation = GuiUtils.HELP_DIRECTORY_LOCATION + "/index.html"
[9e426c1]102
103        # Current tutorial location
[b0c5e8c]104        self._tutorialLocation = os.path.abspath(os.path.join(GuiUtils.HELP_DIRECTORY_LOCATION,
[9e426c1]105                                              "_downloads",
[31c5b58]106                                              "Tutorial.pdf"))
[0cd8612]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
[630155bd]115        self.filesWidget = DataExplorerWindow(self._parent, self, manager=self._data_manager)
[2a432e7]116        ObjectLibrary.addObject('DataExplorer', self.filesWidget)
[0cd8612]117
118        self.dockedFilesWidget = QtGui.QDockWidget("Data Explorer", self._workspace)
119        self.dockedFilesWidget.setWidget(self.filesWidget)
[83d6249]120
[0cd8612]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
[1d85b5e]138        # Add calculators - floating for usability
139        self.SLDCalculator = SldPanel(self)
140        self.DVCalculator = DensityPanel(self)
[a8ec5b1]141        self.KIESSIGCalculator = KiessigPanel(self)
[abc5e70]142        self.SlitSizeCalculator = SlitSizeCalculator(self)
[28a09b0]143        self.GENSASCalculator = GenericScatteringCalculator(self)
[01cda57]144        self.ResolutionCalculator = ResolutionCalculatorPanel(self)
[d5c5d3d]145        self.DataOperation = DataOperationUtilityPanel(self)
[83d6249]146
[e540cd2]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")
[8cb6cd6]159        self._workspace.statusbar.addPermanentWidget(self.statusLabel, 1)
[e540cd2]160        self._workspace.statusbar.addPermanentWidget(self.progress, stretch=0)
[8cb6cd6]161        self.progress.setRange(0, 100)
[e540cd2]162        self.progress.setValue(0)
163        self.progress.setTextVisible(True)
164        self.progress.setVisible(False)
165
[9d266d2]166    def fileWasRead(self, data):
[f721030]167        """
[f82ab8c]168        Callback for fileDataReceivedSignal
[f721030]169        """
170        pass
[481ff26]171
[8cb6cd6]172    def workspace(self):
173        """
174        Accessor for the main window workspace
175        """
176        return self._workspace.workspace
177
[83d6249]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:
[b1e36a3]184            self._current_perspective.setClosable()
[83d6249]185            self._current_perspective.close()
186        # Default perspective
[811bec1]187        self._current_perspective = Perspectives.PERSPECTIVES[str(perspective_name)](parent=self)
[9c391946]188
[83d6249]189        self._workspace.workspace.addWindow(self._current_perspective)
[9c391946]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)
[83d6249]196        self._current_perspective.show()
197
[f721030]198    def updatePerspective(self, data):
199        """
[71361f0]200        Update perspective with data sent.
[f721030]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)
[481ff26]208
[f721030]209    def communicator(self):
[257bd57]210        """ Accessor for the communicator """
[f721030]211        return self.communicate
212
213    def perspective(self):
[257bd57]214        """ Accessor for the perspective """
[f721030]215        return self._current_perspective
216
[e540cd2]217    def updateProgressBar(self, value):
218        """
219        Update progress bar with the required value (0-100)
220        """
[8cb6cd6]221        assert -1 <= value <= 100
[e540cd2]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
[f721030]231    def updateStatusBar(self, text):
232        """
[71361f0]233        Set the status bar text
[f721030]234        """
[e540cd2]235        self.statusLabel.setText(text)
[f721030]236
[1042dba]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)
[f721030]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
[9e426c1]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(
[481ff26]260            self._parent,
[7451b88]261            'Information',
[481ff26]262            quit_msg,
263            QtGui.QMessageBox.Yes,
264            QtGui.QMessageBox.No)
[9e426c1]265
266        # Exit if yes
[7451b88]267        if reply == QtGui.QMessageBox.Yes:
268            reactor.callFromThread(reactor.stop)
269            return True
270
271        return False
[9e426c1]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"}
[dc5ef15]281        c = ConnectionProxy(LocalConfig.__update_URL__, LocalConfig.UPDATE_TIMEOUT)
[9e426c1]282        response = c.connect()
[71361f0]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)
[481ff26]293
[f82ab8c]294    def processVersion(self, version_info):
[9e426c1]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)
[f82ab8c]312                if "download_url" in version_info:
313                    webbrowser.open(version_info["download_url"])
[9e426c1]314                else:
[f82ab8c]315                    webbrowser.open(LocalConfig.__download_page__)
[9e426c1]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)
[f82ab8c]325            msg = "Could not connect to the application server."
326            msg += " Please try again later."
327            self.communicate.statusBarUpdateSignal.emit(msg)
[9e426c1]328
[f721030]329    def addCallbacks(self):
330        """
[9e426c1]331        Method defining all signal connections for the gui manager
[f721030]332        """
[0cd8612]333        self.communicate = GuiUtils.Communicate()
[9d266d2]334        self.communicate.fileDataReceivedSignal.connect(self.fileWasRead)
[f721030]335        self.communicate.statusBarUpdateSignal.connect(self.updateStatusBar)
336        self.communicate.updatePerspectiveWithDataSignal.connect(self.updatePerspective)
[e540cd2]337        self.communicate.progressBarUpdateSignal.connect(self.updateProgressBar)
[83d6249]338        self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged)
[cbcdd2c]339        self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective)
[d48cc19]340        self.communicate.plotRequestedSignal.connect(self.showPlot)
[d5c5d3d]341        self.communicate.updateModelFromDataOperationPanelSignal.connect(self.updateModelFromDataOperationPanel)
[f721030]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)
[363fbfa]374        self._workspace.actionKeissig_Calculator.triggered.connect(self.actionKiessig_Calculator)
375        #self._workspace.actionKIESSING_Calculator.triggered.connect(self.actionKIESSING_Calculator)
[f721030]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)
[06ce180]386        self._workspace.actionGPU_Options.triggered.connect(self.actionGPU_Options)
[f721030]387        self._workspace.actionFit_Results.triggered.connect(self.actionFit_Results)
388        self._workspace.actionChain_Fitting.triggered.connect(self.actionChain_Fitting)
389        self._workspace.actionEdit_Custom_Model.triggered.connect(self.actionEdit_Custom_Model)
390        # Window
391        self._workspace.actionCascade.triggered.connect(self.actionCascade)
[e540cd2]392        self._workspace.actionTile.triggered.connect(self.actionTile)
[f721030]393        self._workspace.actionArrange_Icons.triggered.connect(self.actionArrange_Icons)
394        self._workspace.actionNext.triggered.connect(self.actionNext)
395        self._workspace.actionPrevious.triggered.connect(self.actionPrevious)
396        # Analysis
397        self._workspace.actionFitting.triggered.connect(self.actionFitting)
398        self._workspace.actionInversion.triggered.connect(self.actionInversion)
399        self._workspace.actionInvariant.triggered.connect(self.actionInvariant)
400        # Help
401        self._workspace.actionDocumentation.triggered.connect(self.actionDocumentation)
402        self._workspace.actionTutorial.triggered.connect(self.actionTutorial)
403        self._workspace.actionAcknowledge.triggered.connect(self.actionAcknowledge)
404        self._workspace.actionAbout.triggered.connect(self.actionAbout)
405        self._workspace.actionCheck_for_update.triggered.connect(self.actionCheck_for_update)
406
407    #============ FILE =================
408    def actionLoadData(self):
409        """
[9e426c1]410        Menu File/Load Data File(s)
[f721030]411        """
[5032ea68]412        self.filesWidget.loadFile()
[f721030]413
414    def actionLoad_Data_Folder(self):
415        """
[9e426c1]416        Menu File/Load Data Folder
[f721030]417        """
[5032ea68]418        self.filesWidget.loadFolder()
[f721030]419
420    def actionOpen_Project(self):
421        """
[630155bd]422        Menu Open Project
[f721030]423        """
[630155bd]424        self.filesWidget.loadProject()
[f721030]425
426    def actionOpen_Analysis(self):
427        """
428        """
429        print("actionOpen_Analysis TRIGGERED")
430        pass
431
432    def actionSave(self):
433        """
[630155bd]434        Menu Save Project
[f721030]435        """
[630155bd]436        self.filesWidget.saveProject()
[f721030]437
438    def actionSave_Analysis(self):
439        """
440        """
441        print("actionSave_Analysis TRIGGERED")
[481ff26]442
[f721030]443        pass
444
445    def actionQuit(self):
446        """
[1042dba]447        Close the reactor, exit the application.
[f721030]448        """
[9e426c1]449        self.quitApplication()
[f721030]450
451    #============ EDIT =================
452    def actionUndo(self):
453        """
454        """
455        print("actionUndo TRIGGERED")
456        pass
457
458    def actionRedo(self):
459        """
460        """
461        print("actionRedo TRIGGERED")
462        pass
463
464    def actionCopy(self):
465        """
466        """
467        print("actionCopy TRIGGERED")
468        pass
469
470    def actionPaste(self):
471        """
472        """
473        print("actionPaste TRIGGERED")
474        pass
475
476    def actionReport(self):
477        """
478        """
479        print("actionReport TRIGGERED")
480        pass
481
482    def actionReset(self):
483        """
484        """
[0cd8612]485        logging.warning(" *** actionOpen_Analysis logging *******")
486        print("actionReset print TRIGGERED")
487        sys.stderr.write("STDERR - TRIGGERED")
[f721030]488        pass
489
490    def actionExcel(self):
491        """
492        """
493        print("actionExcel TRIGGERED")
494        pass
495
496    def actionLatex(self):
497        """
498        """
499        print("actionLatex TRIGGERED")
500        pass
501
502    #============ VIEW =================
503    def actionShow_Grid_Window(self):
504        """
505        """
506        print("actionShow_Grid_Window TRIGGERED")
507        pass
508
509    def actionHide_Toolbar(self):
510        """
[e540cd2]511        Toggle toolbar vsibility
[f721030]512        """
[e540cd2]513        if self._workspace.toolBar.isVisible():
514            self._workspace.actionHide_Toolbar.setText("Show Toolbar")
515            self._workspace.toolBar.setVisible(False)
516        else:
517            self._workspace.actionHide_Toolbar.setText("Hide Toolbar")
518            self._workspace.toolBar.setVisible(True)
[f721030]519        pass
520
521    def actionStartup_Settings(self):
522        """
523        """
524        print("actionStartup_Settings TRIGGERED")
525        pass
526
527    def actionCategry_Manager(self):
528        """
529        """
530        print("actionCategry_Manager TRIGGERED")
531        pass
532
533    #============ TOOLS =================
534    def actionData_Operation(self):
535        """
536        """
[f0bb711]537        self.communicate.sendDataToPanelSignal.emit(self._data_manager.get_all_data())
[d5c5d3d]538
539        self.DataOperation.show()
[f721030]540
541    def actionSLD_Calculator(self):
542        """
543        """
[1d85b5e]544        self.SLDCalculator.show()
[f721030]545
546    def actionDensity_Volume_Calculator(self):
547        """
548        """
[1d85b5e]549        self.DVCalculator.show()
[f721030]550
[363fbfa]551    def actionKiessig_Calculator(self):
552        """
553        """
554        #self.DVCalculator.show()
555        self.KIESSIGCalculator.show()
556
[f721030]557    def actionSlit_Size_Calculator(self):
558        """
559        """
[a8ec5b1]560        self.SlitSizeCalculator.show()
[f721030]561
562    def actionSAS_Resolution_Estimator(self):
563        """
564        """
[01cda57]565        self.ResolutionCalculator.show()
[f721030]566
567    def actionGeneric_Scattering_Calculator(self):
568        """
569        """
[28a09b0]570        self.GENSASCalculator.show()
[f721030]571
572    def actionPython_Shell_Editor(self):
573        """
[1af348e]574        Display the Jupyter console as a docked widget.
[f721030]575        """
[fef38e8]576        # Import moved here for startup performance reasons
577        from sas.qtgui.Utilities.IPythonWidget import IPythonWidget
[1af348e]578        terminal = IPythonWidget()
579
580        # Add the console window as another docked widget
581        self.ipDockWidget = QtGui.QDockWidget("IPython", self._workspace)
582        self.ipDockWidget.setObjectName("IPythonDockWidget")
583        self.ipDockWidget.setWidget(terminal)
584        self._workspace.addDockWidget(QtCore.Qt.RightDockWidgetArea,
585                                      self.ipDockWidget)
[f721030]586
587    def actionImage_Viewer(self):
588        """
589        """
590        print("actionImage_Viewer TRIGGERED")
591        pass
592
593    #============ FITTING =================
594    def actionNew_Fit_Page(self):
595        """
[60af928]596        Add a new, empty Fit page in the fitting perspective.
[f721030]597        """
[60af928]598        # Make sure the perspective is correct
599        per = self.perspective()
600        if not isinstance(per, FittingWindow):
601            return
602        per.addFit(None)
[f721030]603
604    def actionConstrained_Fit(self):
605        """
606        """
607        print("actionConstrained_Fit TRIGGERED")
608        pass
609
610    def actionCombine_Batch_Fit(self):
611        """
612        """
613        print("actionCombine_Batch_Fit TRIGGERED")
614        pass
615
616    def actionFit_Options(self):
617        """
618        """
[2d0e0c1]619        if getattr(self._current_perspective, "fit_options_widget"):
620            self._current_perspective.fit_options_widget.show()
[f721030]621        pass
622
[06ce180]623    def actionGPU_Options(self):
624        """
625        """
626        if getattr(self._current_perspective, "gpu_options_widget"):
627            self._current_perspective.gpu_options_widget.show()
628        pass
629
[f721030]630    def actionFit_Results(self):
631        """
632        """
633        print("actionFit_Results TRIGGERED")
634        pass
635
636    def actionChain_Fitting(self):
637        """
638        """
639        print("actionChain_Fitting TRIGGERED")
640        pass
641
642    def actionEdit_Custom_Model(self):
643        """
644        """
645        print("actionEdit_Custom_Model TRIGGERED")
646        pass
647
648    #============ ANALYSIS =================
649    def actionFitting(self):
650        """
651        """
652        print("actionFitting TRIGGERED")
653        pass
654
655    def actionInversion(self):
656        """
657        """
658        print("actionInversion TRIGGERED")
659        pass
660
661    def actionInvariant(self):
662        """
663        """
664        print("actionInvariant TRIGGERED")
665        pass
666
667    #============ WINDOW =================
668    def actionCascade(self):
669        """
[e540cd2]670        Arranges all the child windows in a cascade pattern.
[f721030]671        """
[e540cd2]672        self._workspace.workspace.cascade()
[f721030]673
[e540cd2]674    def actionTile(self):
[f721030]675        """
[e540cd2]676        Tile workspace windows
[f721030]677        """
[e540cd2]678        self._workspace.workspace.tile()
[f721030]679
680    def actionArrange_Icons(self):
681        """
[e540cd2]682        Arranges all iconified windows at the bottom of the workspace
[f721030]683        """
[e540cd2]684        self._workspace.workspace.arrangeIcons()
[f721030]685
686    def actionNext(self):
687        """
[e540cd2]688        Gives the input focus to the next window in the list of child windows.
[f721030]689        """
[e540cd2]690        self._workspace.workspace.activateNextWindow()
[f721030]691
692    def actionPrevious(self):
693        """
[e540cd2]694        Gives the input focus to the previous window in the list of child windows.
[f721030]695        """
[e540cd2]696        self._workspace.workspace.activatePreviousWindow()
[f721030]697
698    #============ HELP =================
699    def actionDocumentation(self):
700        """
[9e426c1]701        Display the documentation
702
703        TODO: use QNetworkAccessManager to assure _helpLocation is valid
[f721030]704        """
[1042dba]705        self._helpView.load(QtCore.QUrl(self._helpLocation))
706        self._helpView.show()
[f721030]707
708    def actionTutorial(self):
709        """
[9e426c1]710        Open the tutorial PDF file with default PDF renderer
[f721030]711        """
[9e426c1]712        # Not terribly safe here. Shell injection warning.
713        # isfile() helps but this probably needs a better solution.
714        if os.path.isfile(self._tutorialLocation):
715            result = subprocess.Popen([self._tutorialLocation], shell=True)
[f721030]716
717    def actionAcknowledge(self):
718        """
[9e426c1]719        Open the Acknowledgements widget
[f721030]720        """
[9e426c1]721        self.ackWidget.show()
[f721030]722
723    def actionAbout(self):
724        """
[9e426c1]725        Open the About box
[f721030]726        """
[f82ab8c]727        # Update the about box with current version and stuff
728
729        # TODO: proper sizing
730        self.aboutWidget.show()
[f721030]731
732    def actionCheck_for_update(self):
733        """
[9e426c1]734        Menu Help/Check for Update
[f721030]735        """
[9e426c1]736        self.checkUpdate()
737
[cbcdd2c]738    def updateTheoryFromPerspective(self, index):
739        """
740        Catch the theory update signal from a perspective
741        Send the request to the DataExplorer for updating the theory model.
742        """
743        self.filesWidget.updateTheoryFromPerspective(index)
744
[d5c5d3d]745    def updateModelFromDataOperationPanel(self, new_item, new_datalist_item):
746        """
747        :param new_item: item to be added to list of loaded files
748        :param new_datalist_item:
749        """
750        if not isinstance(new_item, QtGui.QStandardItem) or \
751                not isinstance(new_datalist_item, dict):
752            msg = "Wrong data type returned from calculations."
753            raise AttributeError, msg
754
755        self.filesWidget.model.appendRow(new_item)
756        self._data_manager.add_data(new_datalist_item)
757
[d48cc19]758    def showPlot(self, plot):
759        """
760        Pass the show plot request to the data explorer
761        """
762        if hasattr(self, "filesWidget"):
763            self.filesWidget.displayData(plot)
Note: See TracBrowser for help on using the repository browser.