def get_values(self, count):
        """ get_values(count) -> []        
        Convert the list values into a list

        count should be an integer with the expected size of the list (given
        by the dimension 'size' in the exploration)
        
        """

        param_info = self._param_info
        module = registry.get_module_by_name(param_info.identifier,
                                             param_info.type,
                                             param_info.namespace)
        result = [module.translate_to_python(m)
                  for m in self._str_values]
        if len(result) != count:
            show_warning('Inconsistent Size',
                         'One of the <i>%s</i>\'s list '
                         'interpolated '
                         'values has a different '
                         'size from the step count. '
                         'Expected %d, got %d instead. '
                         'Parameter Exploration aborted.'
                         % (self.type, count, len(result)))
            return None
        return result
Example #2
0
 def updateCurrentTag(self, name):
     if BaseController.updateCurrentTag(self, name) == False:
         show_warning('Name Exists',
                      "There is already another version named '%s'.\n"
                      "Please enter a different one." % name)
         return False
     else:
         return True
    def compute(self):
        # if server, grab local file using checksum id
        if self.is_server:
            self.checkInputPort("checksum")
            self.checksum = self.getInputFromPort("checksum")
            # get file path
            path_url = "%s/datasets/path/%s/" % (self.base_url, self.checksum)
            try:
                dataset_path_request = urllib2.urlopen(url=path_url)
                dataset_path = dataset_path_request.read()
            except urllib2.HTTPError:
                pass

            if os.path.isfile(dataset_path):
                out_file = core.modules.basic_modules.File()
                out_file.name = dataset_path
                self.setResult("file", out_file)
        else:  # is client
            self.checkInputPort("file")
            self.in_file = self.getInputFromPort("file")
            if os.path.isfile(self.in_file.name):
                # do size check
                size = os.path.getsize(self.in_file.name)
                if size > 26214400:
                    show_warning(
                        "File is too large", ("file is larger than 25MB, " "unable to sync with web repository")
                    )
                    self.setResult("file", self.in_file)
                else:
                    # compute checksum
                    f = open(self.in_file.name, "r")
                    self.checksum = hashlib.sha1()
                    block = 1
                    while block:
                        block = f.read(128)
                        self.checksum.update(block)
                    f.close()
                    self.checksum = self.checksum.hexdigest()

                    # upload/download file
                    self.data_sync()

                    # set checksum param in module
                    if not self.hasInputFromPort("checksum"):
                        self.change_parameter("checksum", [self.checksum])

            else:
                # local file not present
                if self.hasInputFromPort("checksum"):
                    self.checksum = self.getInputFromPort("checksum")

                    # download file
                    self.data_sync()
Example #4
0
    def compute(self):
        # if server, grab local file using checksum id
        if self.is_server:
            self.checkInputPort('checksum')
            self.checksum = self.getInputFromPort("checksum")
            # get file path
            path_url = "%s/datasets/path/%s/" % (self.base_url, self.checksum)
            try:
                dataset_path_request = urllib2.urlopen(url=path_url)
                dataset_path = dataset_path_request.read()
            except urllib2.HTTPError:
                pass

            if os.path.isfile(dataset_path):
                out_file = core.modules.basic_modules.File()
                out_file.name = dataset_path
                self.setResult("file", out_file)
        else:  # is client
            self.checkInputPort('file')
            self.in_file = self.getInputFromPort("file")
            if os.path.isfile(self.in_file.name):
                # do size check
                size = os.path.getsize(self.in_file.name)
                if size > 26214400:
                    show_warning("File is too large",
                                 ("file is larger than 25MB, "
                                  "unable to sync with web repository"))
                    self.setResult("file", self.in_file)
                else:
                    # compute checksum
                    f = open(self.in_file.name, 'r')
                    self.checksum = hashlib.sha1()
                    block = 1
                    while block:
                        block = f.read(128)
                        self.checksum.update(block)
                    f.close()
                    self.checksum = self.checksum.hexdigest()

                    # upload/download file
                    self.data_sync()

                    # set checksum param in module
                    if not self.hasInputFromPort('checksum'):
                        self.change_parameter('checksum', [self.checksum])

            else:
                # local file not present
                if self.hasInputFromPort('checksum'):
                    self.checksum = self.getInputFromPort("checksum")

                    # download file
                    self.data_sync()
 def thumbs_cache_directory_changed(self):
     """ thumbs_cache_changed(v: int) -> None
     
     """
     value = str(self._thumbs_cache_directory_edt.text())
     old_folder = self._configuration.thumbs.cacheDirectory
     if os.path.exists(value):
         self._configuration.thumbs.cacheDirectory = value
         self._temp_configuration.thumbs.cacheDirectory = value
         self.emit(QtCore.SIGNAL("configuration_changed"), None, value)
         self._cache.move_cache_directory(old_folder, value)
     else:
         show_warning("VisTrails", "The directory specified does not exist.")
         self._thumbs_cache_directory_edt.setText(old_folder)
Example #6
0
 def thumbs_cache_directory_changed(self):
     """ thumbs_cache_changed(v: int) -> None
     
     """
     value = str(self._thumbs_cache_directory_edt.text())
     old_folder = self._configuration.thumbs.cacheDirectory
     if os.path.exists(value):
         self._configuration.thumbs.cacheDirectory = value
         self._temp_configuration.thumbs.cacheDirectory = value
         self.emit(QtCore.SIGNAL('configuration_changed'), None, value)
         self._cache.move_cache_directory(old_folder, value)
     else:
         show_warning('VisTrails',
                      'The directory specified does not exist.')
         self._thumbs_cache_directory_edt.setText(old_folder)
 def exportMashupGUI(self):
     if self.controller:
         dialog = QMashupExportDialog(self)
         if dialog.exec_() == QtGui.QDialog.Accepted:
             result = dialog.btnPressed
             fileName = QtGui.QFileDialog.getSaveFileName(self,
                        "Export Mashup...",
                        core.system.vistrails_file_directory(),
                        "VisTrail link files (*.vtl)",
                        None)
             if not fileName.isEmpty():
                 filename = str(fileName)
                 res = MashupsManager.exportMashup(filename, 
                                                   self.controller.originalController, 
                                                   self.controller.mshptrail,
                                                   self.controller.currentVersion,
                                                   result)
                 if not res:
                     show_warning('VisTrails - Exporting Mashup',
                 'There was an error and the mashup could not be exported.')
Example #8
0
 def exportMashupGUI(self):
     if self.controller:
         dialog = QMashupExportDialog(self)
         if dialog.exec_() == QtGui.QDialog.Accepted:
             result = dialog.btnPressed
             fileName = QtGui.QFileDialog.getSaveFileName(
                 self, "Export Mashup...",
                 core.system.vistrails_file_directory(),
                 "VisTrail link files (*.vtl)", None)
             if not fileName.isEmpty():
                 filename = str(fileName)
                 res = MashupsManager.exportMashup(
                     filename, self.controller.originalController,
                     self.controller.mshptrail,
                     self.controller.currentVersion, result)
                 if not res:
                     show_warning(
                         'VisTrails - Exporting Mashup',
                         'There was an error and the mashup could not be exported.'
                     )
Example #9
0
    def addParameter(self, paramInfo):
        """ addParameter(paramInfo: (str, [ParameterInfo]) -> None
        Add a parameter to the table. The parameter info is specified
        in QParameterTreeWidgetItem
        
        """
        # Check to see paramInfo is not a subset of some other parameter set
        params = paramInfo[1]
        for i in xrange(self.layout().count()):
            pEditor = self.layout().itemAt(i).widget()
            if pEditor and type(pEditor)==QParameterSetEditor:
                subset = True
                for p in params:
                    if not (p in pEditor.info[1]):
                        subset = False
                        break                    
                if subset:
                    show_warning('Parameter Exists',
                                 'The parameter you are trying to add is '
                                 'already in the list.')
                    return
        self.showPrompt(False)
        newEditor = QParameterSetEditor(paramInfo, self)

        # Make sure to disable all duplicated parameter
        for p in xrange(len(params)):
            for i in xrange(self.layout().count()):
                pEditor = self.layout().itemAt(i).widget()
                if pEditor and type(pEditor)==QParameterSetEditor:
                    if params[p] in pEditor.info[1]:
                        widget = newEditor.paramWidgets[p]
                        widget.setDimension(4)
                        widget.setDuplicate(True)
                        widget.setEnabled(False)
                        break
        
        self.layout().addWidget(newEditor)
        newEditor.show()
        self.setMinimumHeight(self.layout().minimumSize().height())
        self.emit(QtCore.SIGNAL('exploreChange(bool)'), self.layout().count() > 3)
        return newEditor
Example #10
0
    def nameChanged(self):
        old_alias = self.alias.name
        new_alias = str(self.name_edit.text())
        if old_alias == new_alias:
            return
        if new_alias in self.table.aliases.keys():
            show_warning("Mashup",
                         """Label name %s already exists. 
Please type a different name. """ % new_alias)
            self.name_edit.setText(old_alias)
            self.name_edit.setFocus()
        elif new_alias == '':
            show_warning("Mashup",
                         """Variables with empty name are not allowed. 
Please type a unique name. """ % new_alias)
            self.name_edit.setText(old_alias)
            self.name_edit.setFocus()
        else:
            self.table.aliases[new_alias] = self.table.aliases[old_alias]
            #self.table.alias_cache[new_alias] = self.table.alias_cache[old_alias]
            del self.table.aliases[old_alias]
            #del self.table.alias_cache[old_alias]
            self.alias.name = new_alias
            self.aliasChanged.emit(self.alias)
Example #11
0
    def data_sync(self):
        """ downloads/uploads/uses the local file depending on availability """
        self.checksum_lookup()

        # local file not on repository, so upload
        if not self.on_server and os.path.isfile(self.in_file.name):
            cookiejar = gui.repository.QRepositoryDialog.cookiejar
            if cookiejar:
                register_openers(cookiejar=cookiejar)

                params = {
                    'dataset_file': open(self.in_file.name, 'rb'),
                    'name': self.in_file.name.split('/')[-1],
                    'origin': 'vistrails',
                    'checksum': self.checksum
                }

                upload_url = "%s/datasets/upload/" % self.base_url

                datagen, headers = multipart_encode(params)
                request = urllib2.Request(upload_url, datagen, headers)
                try:
                    result = urllib2.urlopen(request)
                    if result.code != 200:
                        show_warning("Upload Failure",
                                     "Data failed to upload to repository")
                        # make temporarily uncachable
                        self.is_cacheable = self.invalidate_cache
                    else:
                        debug.warning("Push to repository was successful")
                        # make sure module caches
                        self.is_cacheable = self.validate_cache
                except Exception, e:
                    show_warning("Upload Failure",
                                 "Data failed to upload to repository")
                    # make temporarily uncachable
                    self.is_cacheable = self.invalidate_cache
                debug.warning('RepoSync uploaded %s to the repository' % \
                              self.in_file.name)
            else:
                show_warning("Please login", ("You must be logged into the web"
                                              " repository in order to upload "
                                              "data. No data was synced"))
                # make temporarily uncachable
                self.is_cacheable = self.invalidate_cache

            # use local data
            self.setResult("file", self.in_file)
    def data_sync(self):
        """ downloads/uploads/uses the local file depending on availability """
        self.checksum_lookup()

        # local file not on repository, so upload
        if not self.on_server and os.path.isfile(self.in_file.name):
            cookiejar = gui.repository.QRepositoryDialog.cookiejar
            if cookiejar:
                register_openers(cookiejar=cookiejar)

                params = {
                    "dataset_file": open(self.in_file.name, "rb"),
                    "name": self.in_file.name.split("/")[-1],
                    "origin": "vistrails",
                    "checksum": self.checksum,
                }

                upload_url = "%s/datasets/upload/" % self.base_url

                datagen, headers = multipart_encode(params)
                request = urllib2.Request(upload_url, datagen, headers)
                try:
                    result = urllib2.urlopen(request)
                    if result.code != 200:
                        show_warning("Upload Failure", "Data failed to upload to repository")
                        # make temporarily uncachable
                        self.is_cacheable = self.invalidate_cache
                    else:
                        debug.warning("Push to repository was successful")
                        # make sure module caches
                        self.is_cacheable = self.validate_cache
                except Exception, e:
                    show_warning("Upload Failure", "Data failed to upload to repository")
                    # make temporarily uncachable
                    self.is_cacheable = self.invalidate_cache
                debug.warning("RepoSync uploaded %s to the repository" % self.in_file.name)
            else:
                show_warning(
                    "Please login",
                    ("You must be logged into the web" " repository in order to upload " "data. No data was synced"),
                )
                # make temporarily uncachable
                self.is_cacheable = self.invalidate_cache

            # use local data
            self.setResult("file", self.in_file)
            def evaluate(i):
                try:
                    v = d['value'](i)
                    if v == None:
                        return module.default_value
                    return v
                except Exception, e:
                    return str(e)
            return [evaluate(i) for i in xrange(self.size)]
        result = get()
        
        if not all(result, module.validate):
            show_warning('Failed Validation',
                         'One of the <i>%s</i>\'s user defined '
                         'functions has failed validation, '
                         'which usually means it generated a '
                         'value of a type different '
                         'than that specified by the '
                         'parameter. Parameter Exploration '
                         'aborted.' % param_info.type)
            return None
        return result
        

    def getValuesString(self):
        """ getValuesString() -> str
        Return a string representation of the parameter list
        
        """
        r = self.get_values(self.size)
        if r is None:
            return '{ERROR}'
    def __init__(self, parent=None, vistrail_view=None, dumpcells=False, 
                 controller=None, version=-1):
        """ QMashupAppMainWindow()
        Initialize an app window from a mashup.

        """
        # Constructing the main widget
        QtGui.QMainWindow.__init__(self, parent)
        self.vtkCells = []
        self.setStatusBar(QtGui.QStatusBar(self))
    
        # Central widget
        centralWidget = QtGui.QWidget()
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.setMargin(0)
        self.mainLayout.setSpacing(5)
        centralWidget.setLayout(self.mainLayout)
        self.setCentralWidget(centralWidget)
        self.numberOfCells = 0
        self.is_executing = False
        #self.resize(100,100)
        self.dumpcells = dumpcells
        self.view = vistrail_view
        if controller:
            self.controller = controller
            self.mshptrail = controller.mshptrail
            if version == -1:
                self.currentMashup = self.controller.currentMashup
            else:
                self.currentMashup = self.mshptrail.getMashup(version)
            self.setWindowTitle('%s Mashup'%self.controller.getMashupName(version))
        else:
            self.setWindowTitle('Mashup')
            
        # Assign "hidden" shortcut
        self.editingModeAct = QtGui.QAction("Chang&e Layout", self, shortcut="Ctrl+E",
               statusTip="Change the layout of the widgets", triggered=self.toggleEditingMode)
        #self.editingModeShortcut = QtGui.QShortcut(QtGui.QKeySequence('Ctrl+E'), self)
        #self.connect(self.editingModeShortcut, QtCore.SIGNAL('activated()'),
        #             self.toggleEditingMode)
        self.editing = False
        # Constructing alias controls
        self.controlDocks = []
        # Show here to make sure XDisplay info is correct (for VTKCell)
        self.show()

        spreadsheetController.setEchoMode(True)        
        #will run to get Spreadsheet Cell events
        (cellEvents, errors) = self.runAndGetCellEvents(useDefaultValues=True)
        if cellEvents:
            self.numberOfCells = len(cellEvents)
            self.initCells(cellEvents)
        if len(errors) > 0:
            show_warning("VisTrails::Mashup Preview", 
                         "There was a problem executing the pipeline: %s."%errors)
        # Construct the controllers for aliases
        self.controlDocks = {}
        self.cellControls = {}
        self.aliasWidgets = {}
        self.initControls()
        
        if self.currentMashup.layout != None:
            self.restoreState(QtCore.QByteArray.fromPercentEncoding(
                                QtCore.QByteArray(self.currentMashup.layout)))
        
        if self.currentMashup.geometry != None:
            self.restoreGeometry(QtCore.QByteArray.fromPercentEncoding(
                                QtCore.QByteArray(self.currentMashup.geometry)))
        else:
            self.resize(self.sizeHint())
                    
        # Constructing buttons
        buttonDock = QCustomDockWidget('Control Buttons', self)
        buttonWidget = QtGui.QWidget(buttonDock)
        buttonWidget.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                   QtGui.QSizePolicy.Preferred)
        buttonLayout = QtGui.QGridLayout()
        buttonWidget.setLayout(buttonLayout)
        buttonLayout.setMargin(5)
        self.cb_auto_update = QtGui.QCheckBox("Turn on auto-update", self.centralWidget())
        self.cb_auto_update.setChecked(False)
        self.cb_keep_camera = QtGui.QCheckBox("Keep camera position", self.centralWidget())
        self.cb_keep_camera.setChecked(True)
        self.connect(self.cb_auto_update,
                     QtCore.SIGNAL("stateChanged(int)"),
                     self.auto_update_changed)
        self.updateButton = QtGui.QPushButton("&Update", self.centralWidget())
        if self.dumpcells:
            self.quitButton = QtGui.QPushButton("&Save", self.centralWidget())
            self.connect(self.quitButton,
                         QtCore.SIGNAL('clicked(bool)'),
                         self.saveAndExport)
        else:
            self.quitButton = QtGui.QPushButton("&Quit", self.centralWidget())
            self.connect(self.quitButton,
                         QtCore.SIGNAL('clicked(bool)'),
                         self.close)
        buttonLayout.setColumnStretch(0, 1)
        buttonLayout.addWidget(self.cb_auto_update, 0, 1, QtCore.Qt.AlignLeft)    
        buttonLayout.addWidget(self.cb_keep_camera, 0, 2, 1, 2, QtCore.Qt.AlignLeft) 
        buttonLayout.addWidget(self.updateButton, 1, 2, QtCore.Qt.AlignRight)
        buttonLayout.addWidget(self.quitButton, 1, 3, QtCore.Qt.AlignRight)
        self.connect(self.updateButton,
                     QtCore.SIGNAL('clicked(bool)'),
                     self.updateButtonClick)
        buttonDock.setWidget(buttonWidget)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, buttonDock)
        self.controlDocks["__buttons__"] = buttonDock
        
        self.saveAllAct = QtGui.QAction("S&ave Combined", self, 
                                        shortcut=QtGui.QKeySequence.SelectAll,
                                        statusTip="Save combined images to disk", 
                                        triggered=self.saveAllEvent)
        self.saveAct = QtGui.QAction("&Save Each", self, 
                                     shortcut=QtGui.QKeySequence.Save,
                                     statusTip="Save separate images to disk", 
                                     triggered=self.saveEventAction)
        self.showBuilderAct = QtGui.QAction("VisTrails Main Window", self,
                                            statusTip="Show VisTrails Main Window",
                                            triggered=self.showBuilderWindow)
        self.createMenus()
        self.lastExportPath = ''
Example #15
0
    def __init__(self,
                 parent=None,
                 vistrail_view=None,
                 dumpcells=False,
                 controller=None,
                 version=-1):
        """ QMashupAppMainWindow()
        Initialize an app window from a mashup.

        """
        # Constructing the main widget
        QtGui.QMainWindow.__init__(self, parent)
        self.vtkCells = []
        self.setStatusBar(QtGui.QStatusBar(self))

        # Central widget
        centralWidget = QtGui.QWidget()
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.setMargin(0)
        self.mainLayout.setSpacing(5)
        centralWidget.setLayout(self.mainLayout)
        self.setCentralWidget(centralWidget)
        self.numberOfCells = 0
        self.is_executing = False
        #self.resize(100,100)
        self.dumpcells = dumpcells
        self.view = vistrail_view
        if controller:
            self.controller = controller
            self.mshptrail = controller.mshptrail
            if version == -1:
                self.currentMashup = self.controller.currentMashup
            else:
                self.currentMashup = self.mshptrail.getMashup(version)
            self.setWindowTitle('%s Mashup' %
                                self.controller.getMashupName(version))
        else:
            self.setWindowTitle('Mashup')

        # Assign "hidden" shortcut
        self.editingModeAct = QtGui.QAction(
            "Chang&e Layout",
            self,
            shortcut="Ctrl+E",
            statusTip="Change the layout of the widgets",
            triggered=self.toggleEditingMode)
        #self.editingModeShortcut = QtGui.QShortcut(QtGui.QKeySequence('Ctrl+E'), self)
        #self.connect(self.editingModeShortcut, QtCore.SIGNAL('activated()'),
        #             self.toggleEditingMode)
        self.editing = False
        # Constructing alias controls
        self.controlDocks = []
        # Show here to make sure XDisplay info is correct (for VTKCell)
        self.show()

        spreadsheetController.setEchoMode(True)
        #will run to get Spreadsheet Cell events
        (cellEvents, errors) = self.runAndGetCellEvents(useDefaultValues=True)
        if cellEvents:
            self.numberOfCells = len(cellEvents)
            self.initCells(cellEvents)
        if len(errors) > 0:
            show_warning(
                "VisTrails::Mashup Preview",
                "There was a problem executing the pipeline: %s." % errors)
        # Construct the controllers for aliases
        self.controlDocks = {}
        self.cellControls = {}
        self.aliasWidgets = {}
        self.initControls()

        if self.currentMashup.layout != None:
            self.restoreState(
                QtCore.QByteArray.fromPercentEncoding(
                    QtCore.QByteArray(self.currentMashup.layout)))

        if self.currentMashup.geometry != None:
            self.restoreGeometry(
                QtCore.QByteArray.fromPercentEncoding(
                    QtCore.QByteArray(self.currentMashup.geometry)))
        else:
            self.resize(self.sizeHint())

        # Constructing buttons
        buttonDock = QCustomDockWidget('Control Buttons', self)
        buttonWidget = QtGui.QWidget(buttonDock)
        buttonWidget.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                   QtGui.QSizePolicy.Preferred)
        buttonLayout = QtGui.QGridLayout()
        buttonWidget.setLayout(buttonLayout)
        buttonLayout.setMargin(5)
        self.cb_auto_update = QtGui.QCheckBox("Turn on auto-update",
                                              self.centralWidget())
        self.cb_auto_update.setChecked(False)
        self.cb_keep_camera = QtGui.QCheckBox("Keep camera position",
                                              self.centralWidget())
        self.cb_keep_camera.setChecked(True)
        self.connect(self.cb_auto_update, QtCore.SIGNAL("stateChanged(int)"),
                     self.auto_update_changed)
        self.updateButton = QtGui.QPushButton("&Update", self.centralWidget())
        if self.dumpcells:
            self.quitButton = QtGui.QPushButton("&Save", self.centralWidget())
            self.connect(self.quitButton, QtCore.SIGNAL('clicked(bool)'),
                         self.saveAndExport)
        else:
            self.quitButton = QtGui.QPushButton("&Quit", self.centralWidget())
            self.connect(self.quitButton, QtCore.SIGNAL('clicked(bool)'),
                         self.close)
        buttonLayout.setColumnStretch(0, 1)
        buttonLayout.addWidget(self.cb_auto_update, 0, 1, QtCore.Qt.AlignLeft)
        buttonLayout.addWidget(self.cb_keep_camera, 0, 2, 1, 2,
                               QtCore.Qt.AlignLeft)
        buttonLayout.addWidget(self.updateButton, 1, 2, QtCore.Qt.AlignRight)
        buttonLayout.addWidget(self.quitButton, 1, 3, QtCore.Qt.AlignRight)
        self.connect(self.updateButton, QtCore.SIGNAL('clicked(bool)'),
                     self.updateButtonClick)
        buttonDock.setWidget(buttonWidget)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, buttonDock)
        self.controlDocks["__buttons__"] = buttonDock

        self.saveAllAct = QtGui.QAction(
            "S&ave Combined",
            self,
            shortcut=QtGui.QKeySequence.SelectAll,
            statusTip="Save combined images to disk",
            triggered=self.saveAllEvent)
        self.saveAct = QtGui.QAction("&Save Each",
                                     self,
                                     shortcut=QtGui.QKeySequence.Save,
                                     statusTip="Save separate images to disk",
                                     triggered=self.saveEventAction)
        self.showBuilderAct = QtGui.QAction(
            "VisTrails Main Window",
            self,
            statusTip="Show VisTrails Main Window",
            triggered=self.showBuilderWindow)
        self.createMenus()
        self.lastExportPath = ''
 def saveSpreadsheet(self, fileName=None):
     """ saveSpreadsheet(fileName: str) -> None        
     Save the current spreadsheet to a file if fileName is not
     None. Else, pop up a dialog to ask for a file name.
     
     """
     def serialize_locator(locator):
         wrapper = XMLWrapper()
         dom = wrapper.create_document('spreadsheet_locator')
         root = dom.documentElement
         root.setAttribute("version", "1.0")
         locator.serialize(dom,root)
         return dom.toxml()
     
     def need_save():
         from gui.vistrails_window import _app
         need_save_vt = False
         for t in self.tabWidgets:
             dim = t.getDimension()
             for r in xrange(dim[0]):
                 for c in xrange(dim[1]):
                     info = t.getCellPipelineInfo(r,c)
                     if info:
                         locator = info[0]['locator']
                         view = _app.ensureVistrail(locator)
                         if view:
                             controller = view.get_controller()
                             if controller.changed:
                                 need_save_vt = True
         return need_save_vt
     
     if need_save():
         show_warning('Save Spreadsheet', 'Please save your vistrails and try again.')
         return
     
     if fileName==None:
         fileName = self.spreadsheetFileName
     if fileName:
         indexFile = open(fileName, 'w')
         indexFile.write(str(len(self.tabWidgets))+'\n')
         for t in self.tabWidgets:
             dim = t.getDimension()
             sheet = spreadsheetRegistry.getSheetByType(type(t))
             indexFile.write('%s\n'%str((str(t.windowTitle()),
                                         sheet,
                                         dim[0], dim[1])))
             for r in xrange(dim[0]):
                 for c in xrange(dim[1]):
                     info = t.getCellPipelineInfo(r,c)
                     if info:
                         newinfo0 = copy.copy(info[0])
                         newinfo0['pipeline'] = None
                         newinfo0['actions'] = []
                         newinfo0['locator'] = \
                                       serialize_locator(newinfo0['locator'])
                         indexFile.write('%s\n'
                                         %str((r, c,
                                               newinfo0,
                                               info[1], info[2])))
             indexFile.write('---\n')
         indexFile.write(str(len(self.executedPipelines[0]))+'\n')
         for vistrail in self.executedPipelines[0]:
             indexFile.write('%s\n'%str((serialize_locator(vistrail[0]),
                                         vistrail[1])))
         self.changeSpreadsheetFileName(fileName)
         indexFile.close()
     else:
         self.saveSpreadsheetAs()
    def saveSpreadsheet(self, fileName=None):
        """ saveSpreadsheet(fileName: str) -> None        
        Save the current spreadsheet to a file if fileName is not
        None. Else, pop up a dialog to ask for a file name.
        
        """
        def serialize_locator(locator):
            wrapper = XMLWrapper()
            dom = wrapper.create_document('spreadsheet_locator')
            root = dom.documentElement
            root.setAttribute("version", "1.0")
            locator.serialize(dom, root)
            return dom.toxml()

        def need_save():
            from gui.vistrails_window import _app
            need_save_vt = False
            for t in self.tabWidgets:
                dim = t.getDimension()
                for r in xrange(dim[0]):
                    for c in xrange(dim[1]):
                        info = t.getCellPipelineInfo(r, c)
                        if info:
                            locator = info[0]['locator']
                            view = _app.ensureVistrail(locator)
                            if view:
                                controller = view.get_controller()
                                if controller.changed:
                                    need_save_vt = True
            return need_save_vt

        if need_save():
            show_warning('Save Spreadsheet',
                         'Please save your vistrails and try again.')
            return

        if fileName == None:
            fileName = self.spreadsheetFileName
        if fileName:
            indexFile = open(fileName, 'w')
            indexFile.write(str(len(self.tabWidgets)) + '\n')
            for t in self.tabWidgets:
                dim = t.getDimension()
                sheet = spreadsheetRegistry.getSheetByType(type(t))
                indexFile.write('%s\n' % str(
                    (str(t.windowTitle()), sheet, dim[0], dim[1])))
                for r in xrange(dim[0]):
                    for c in xrange(dim[1]):
                        info = t.getCellPipelineInfo(r, c)
                        if info:
                            newinfo0 = copy.copy(info[0])
                            newinfo0['pipeline'] = None
                            newinfo0['actions'] = []
                            newinfo0['locator'] = \
                                          serialize_locator(newinfo0['locator'])
                            indexFile.write('%s\n' % str(
                                (r, c, newinfo0, info[1], info[2])))
                indexFile.write('---\n')
            indexFile.write(str(len(self.executedPipelines[0])) + '\n')
            for vistrail in self.executedPipelines[0]:
                indexFile.write('%s\n' % str(
                    (serialize_locator(vistrail[0]), vistrail[1])))
            self.changeSpreadsheetFileName(fileName)
            indexFile.close()
        else:
            self.saveSpreadsheetAs()