PLCControler.py
changeset 56 7187e1c00975
parent 53 4988262d03e3
child 57 9bf197698af0
equal deleted inserted replaced
55:e24d2f917c7e 56:7187e1c00975
   160     # Reset PLCControler internal variables
   160     # Reset PLCControler internal variables
   161     def Reset(self):
   161     def Reset(self):
   162         self.VerifyXML = False
   162         self.VerifyXML = False
   163         self.Project = None
   163         self.Project = None
   164         self.ProjectBuffer = None
   164         self.ProjectBuffer = None
       
   165         self.Buffering = False
   165         self.FilePath = ""
   166         self.FilePath = ""
   166         self.FileName = ""
   167         self.FileName = ""
   167         self.ProgramFilePath = ""
   168         self.ProgramFilePath = ""
   168         self.ElementsOpened = []
   169         self.ElementsOpened = []
   169         self.CurrentElementEditing = None
   170         self.CurrentElementEditing = None
   185     # Create a new project by replacing the current one
   186     # Create a new project by replacing the current one
   186     def CreateNewProject(self, name):
   187     def CreateNewProject(self, name):
   187         # Create the project
   188         # Create the project
   188         self.Project = plcopen.project()
   189         self.Project = plcopen.project()
   189         self.Project.setName(name)
   190         self.Project.setName(name)
       
   191         self.SetFilePath("")
   190         # Initialize the project buffer
   192         # Initialize the project buffer
   191         #self.ProjectBuffer = UndoBuffer(self.Copy(self.Project))
   193         self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), False)
   192     
   194         self.Buffering = False
   193     # Change project name
       
   194     def SetProjectName(self, name):
       
   195         self.Project.setName(name)
       
   196     
       
   197     # Return project name
       
   198     def GetProjectName(self):
       
   199         return self.Project.getName()
       
   200     
   195     
   201     # Return project pou names
   196     # Return project pou names
   202     def GetProjectPouNames(self):
   197     def GetProjectPouNames(self):
   203         return [pou.getName() for pou in self.Project.getPous()]
   198         return [pou.getName() for pou in self.Project.getPous()]
   204     
   199     
   217                         variables.append(transition.getName())
   212                         variables.append(transition.getName())
   218                     for action in pou.getActionList():
   213                     for action in pou.getActionList():
   219                         variables.append(action.getName())
   214                         variables.append(action.getName())
   220         return variables
   215         return variables
   221     
   216     
       
   217     # Return if project is saved
       
   218     def ProjectIsSaved(self):
       
   219         return self.ProjectBuffer.IsCurrentSaved()
       
   220     
   222     # Return file path if project is an open file
   221     # Return file path if project is an open file
   223     def GetFilePath(self):
   222     def GetFilePath(self):
   224         return self.FilePath
   223         return self.FilePath
   225     
   224     
   226     # Return file path if project is an open file
   225     # Return file path if project is an open file
   242             self.FileName = "Unnamed%d"%self.LastNewIndex
   241             self.FileName = "Unnamed%d"%self.LastNewIndex
   243         else:
   242         else:
   244             self.FileName = os.path.splitext(os.path.basename(filepath))[0]
   243             self.FileName = os.path.splitext(os.path.basename(filepath))[0]
   245     
   244     
   246     # Change project properties
   245     # Change project properties
   247     def SetProjectProperties(self, values):
   246     def SetProjectProperties(self, name = None, properties = None):
   248         self.Project.setFileHeader(values)
   247         if name != None:
   249     
   248             self.Project.setName(name)
       
   249         if properties != None:
       
   250             self.Project.setFileHeader(properties)
       
   251         if name != None or properties != None:
       
   252             self.BufferProject()
       
   253             
   250     # Return project properties
   254     # Return project properties
   251     def GetProjectProperties(self):
   255     def GetProjectProperties(self):
   252         return self.Project.getFileHeader()
   256         properties = self.Project.getFileHeader()
       
   257         properties["projectName"] = self.Project.getName()
       
   258         return properties
   253     
   259     
   254     # Return project informations
   260     # Return project informations
   255     def GetProjectInfos(self):
   261     def GetProjectInfos(self):
   256         if self.Project:
   262         if self.Project:
   257             infos = {"name": self.Project.getName(), "type": ITEM_PROJECT}
   263             infos = {"name": self.Project.getName(), "type": ITEM_PROJECT}
   374                 return used
   380                 return used
   375         return False
   381         return False
   376 
   382 
   377     def GenerateProgram(self, filepath):
   383     def GenerateProgram(self, filepath):
   378         if self.Project:
   384         if self.Project:
   379             #try:
   385             try:
   380             program = GenerateCurrentProgram(self.Project)
   386                 program = GenerateCurrentProgram(self.Project)
   381             programfile = open(filepath, "w")
   387                 programfile = open(filepath, "w")
   382             programfile.write(program)
   388                 programfile.write(program)
   383             programfile.close()
   389                 programfile.close()
   384             self.ProgramFilePath = filepath
   390                 self.ProgramFilePath = filepath
   385             return True
   391                 return True
   386             #except:
   392             except:
   387             #    pass
   393                 pass
   388         return False
   394         return False
   389 
   395 
   390 #-------------------------------------------------------------------------------
   396 #-------------------------------------------------------------------------------
   391 #                        Project Pous management functions
   397 #                        Project Pous management functions
   392 #-------------------------------------------------------------------------------
   398 #-------------------------------------------------------------------------------
   395     def ProjectAddPou(self, name, pou_type, body_type):
   401     def ProjectAddPou(self, name, pou_type, body_type):
   396         # Add the pou to project
   402         # Add the pou to project
   397         self.Project.appendPou(name, pou_type, body_type)
   403         self.Project.appendPou(name, pou_type, body_type)
   398         self.RefreshPouUsingTree()
   404         self.RefreshPouUsingTree()
   399         self.RefreshBlockTypes()
   405         self.RefreshBlockTypes()
       
   406         self.BufferProject()
   400     
   407     
   401     # Remove a pou from project
   408     # Remove a pou from project
   402     def ProjectRemovePou(self, name):
   409     def ProjectRemovePou(self, name):
   403         removed = None
   410         removed = None
   404         # Search if the pou removed is currently opened
   411         # Search if the pou removed is currently opened
   416                 self.CurrentElementEditing = None
   423                 self.CurrentElementEditing = None
   417         # Remove pou from project
   424         # Remove pou from project
   418         self.Project.removePou(name)
   425         self.Project.removePou(name)
   419         self.RefreshPouUsingTree()
   426         self.RefreshPouUsingTree()
   420         self.RefreshBlockTypes()
   427         self.RefreshBlockTypes()
       
   428         self.BufferProject()
   421     
   429     
   422     # Add a configuration to Project
   430     # Add a configuration to Project
   423     def ProjectAddConfiguration(self, name):
   431     def ProjectAddConfiguration(self, name):
   424         self.Project.addConfiguration(name)
   432         self.Project.addConfiguration(name)
   425         self.RefreshPouUsingTree()
   433         self.RefreshPouUsingTree()
   426         self.RefreshBlockTypes()
   434         self.RefreshBlockTypes()
       
   435         self.BufferProject()
   427     
   436     
   428     # Remove a configuration from project
   437     # Remove a configuration from project
   429     def ProjectRemoveConfiguration(self, name):
   438     def ProjectRemoveConfiguration(self, name):
   430         self.Project.removeConfiguration(name)
   439         self.Project.removeConfiguration(name)
   431         self.RefreshPouUsingTree()
   440         self.RefreshPouUsingTree()
   432         self.RefreshBlockTypes()
   441         self.RefreshBlockTypes()
       
   442         self.BufferProject()
   433     
   443     
   434     # Add a resource to a configuration of the Project
   444     # Add a resource to a configuration of the Project
   435     def ProjectAddConfigurationResource(self, config, name):
   445     def ProjectAddConfigurationResource(self, config, name):
   436         self.Project.addConfigurationResource(config, name)
   446         self.Project.addConfigurationResource(config, name)
   437         self.RefreshPouUsingTree()
   447         self.RefreshPouUsingTree()
   438         self.RefreshBlockTypes()
   448         self.RefreshBlockTypes()
       
   449         self.BufferProject()
   439     
   450     
   440     # Remove a resource from a configuration of the project
   451     # Remove a resource from a configuration of the project
   441     def ProjectRemoveConfigurationResource(self, config, name):
   452     def ProjectRemoveConfigurationResource(self, config, name):
   442         self.Project.removeConfigurationResource(config, name)
   453         self.Project.removeConfigurationResource(config, name)
   443         self.RefreshPouUsingTree()
   454         self.RefreshPouUsingTree()
   444         self.RefreshBlockTypes()
   455         self.RefreshBlockTypes()
       
   456         self.BufferProject()
   445     
   457     
   446     # Add a Transition to a Project Pou
   458     # Add a Transition to a Project Pou
   447     def ProjectAddPouTransition(self, pou_name, transition_name, transition_type):
   459     def ProjectAddPouTransition(self, pou_name, transition_name, transition_type):
   448         pou = self.Project.getPou(pou_name)
   460         pou = self.Project.getPou(pou_name)
   449         pou.addTransition(transition_name, transition_type)
   461         pou.addTransition(transition_name, transition_type)
       
   462         self.BufferProject()
   450     
   463     
   451     # Add a Transition to a Project Pou
   464     # Add a Transition to a Project Pou
   452     def ProjectAddPouAction(self, pou_name, action_name, action_type):
   465     def ProjectAddPouAction(self, pou_name, action_name, action_type):
   453         pou = self.Project.getPou(pou_name)
   466         pou = self.Project.getPou(pou_name)
   454         pou.addAction(action_name, action_type)
   467         pou.addAction(action_name, action_type)
       
   468         self.BufferProject()
   455         
   469         
   456     # Change the name of a pou
   470     # Change the name of a pou
   457     def ChangePouName(self, old_name, new_name):
   471     def ChangePouName(self, old_name, new_name):
   458         # Found the pou corresponding to old name and change its name to new name
   472         # Found the pou corresponding to old name and change its name to new name
   459         pou = self.Project.getPou(old_name)
   473         pou = self.Project.getPou(old_name)
   462         if old_name in self.ElementsOpened:
   476         if old_name in self.ElementsOpened:
   463             idx = self.ElementsOpened.index(old_name)
   477             idx = self.ElementsOpened.index(old_name)
   464             self.ElementsOpened[idx] = new_name
   478             self.ElementsOpened[idx] = new_name
   465         self.RefreshPouUsingTree()
   479         self.RefreshPouUsingTree()
   466         self.RefreshBlockTypes()
   480         self.RefreshBlockTypes()
       
   481         self.BufferProject()
   467     
   482     
   468     # Change the name of a pou transition
   483     # Change the name of a pou transition
   469     def ChangePouTransitionName(self, pou_name, old_name, new_name):
   484     def ChangePouTransitionName(self, pou_name, old_name, new_name):
   470         # Found the pou transition corresponding to old name and change its name to new name
   485         # Found the pou transition corresponding to old name and change its name to new name
   471         pou = self.Project.getPou(pou_name)
   486         pou = self.Project.getPou(pou_name)
   475         old_computedname = self.ComputePouTransitionName(pou_name, old_name)
   490         old_computedname = self.ComputePouTransitionName(pou_name, old_name)
   476         new_computedname = self.ComputePouTransitionName(pou_name, new_name)
   491         new_computedname = self.ComputePouTransitionName(pou_name, new_name)
   477         if old_computedname in self.ElementsOpened:
   492         if old_computedname in self.ElementsOpened:
   478             idx = self.ElementsOpened.index(old_computedname)
   493             idx = self.ElementsOpened.index(old_computedname)
   479             self.ElementsOpened[idx] = new_computedname
   494             self.ElementsOpened[idx] = new_computedname
       
   495         self.BufferProject()
   480     
   496     
   481     # Change the name of a pou action
   497     # Change the name of a pou action
   482     def ChangePouActionName(self, pou_name, old_name, new_name):
   498     def ChangePouActionName(self, pou_name, old_name, new_name):
   483         # Found the pou action corresponding to old name and change its name to new name
   499         # Found the pou action corresponding to old name and change its name to new name
   484         pou = self.Project.getPou(pou_name)
   500         pou = self.Project.getPou(pou_name)
   488         old_computedname = self.ComputePouActionName(pou_name, old_name)
   504         old_computedname = self.ComputePouActionName(pou_name, old_name)
   489         new_computedname = self.ComputePouActionName(pou_name, new_name)
   505         new_computedname = self.ComputePouActionName(pou_name, new_name)
   490         if old_computedname in self.ElementsOpened:
   506         if old_computedname in self.ElementsOpened:
   491             idx = self.ElementsOpened.index(old_computedname)
   507             idx = self.ElementsOpened.index(old_computedname)
   492             self.ElementsOpened[idx] = new_computedname
   508             self.ElementsOpened[idx] = new_computedname
   493 
   509         self.BufferProject()
       
   510     
   494     # Change the name of a pou action
   511     # Change the name of a pou action
   495     def ChangePouVariableName(self, pou_name, old_name, new_name):
   512     def ChangePouVariableName(self, pou_name, old_name, new_name):
   496         # Found the pou action corresponding to old name and change its name to new name
   513         # Found the pou action corresponding to old name and change its name to new name
   497         pou = self.Project.getPou(pou_name)
   514         pou = self.Project.getPou(pou_name)
   498         for type, varlist in pou.getVars():
   515         for type, varlist in pou.getVars():
   499             for var in varlist.getVariable():
   516             for var in varlist.getVariable():
   500                 if var.getName() == old_name:
   517                 if var.getName() == old_name:
   501                     var.setName(new_name)
   518                     var.setName(new_name)
   502         self.RefreshBlockTypes()
   519         self.RefreshBlockTypes()
       
   520         self.BufferProject()
   503         
   521         
   504     # Change the name of a configuration
   522     # Change the name of a configuration
   505     def ChangeConfigurationName(self, old_name, new_name):
   523     def ChangeConfigurationName(self, old_name, new_name):
   506         # Found the configuration corresponding to old name and change its name to new name
   524         # Found the configuration corresponding to old name and change its name to new name
   507         configuration = self.Project.getConfiguration(old_name)
   525         configuration = self.Project.getConfiguration(old_name)
   508         configuration.setName(new_name)
   526         configuration.setName(new_name)
   509         # If configuration is currently opened, change its name in the list of opened elements
   527         # If configuration is currently opened, change its name in the list of opened elements
   510         for idx, element in enumerate(self.ElementsOpened):
   528         for idx, element in enumerate(self.ElementsOpened):
   511             self.ElementsOpened[idx] = element.replace(old_name, new_name)
   529             self.ElementsOpened[idx] = element.replace(old_name, new_name)
   512 
   530         self.BufferProject()
       
   531     
   513     # Change the name of a configuration resource
   532     # Change the name of a configuration resource
   514     def ChangeConfigurationResourceName(self, config_name, old_name, new_name):
   533     def ChangeConfigurationResourceName(self, config_name, old_name, new_name):
   515         # Found the resource corresponding to old name and change its name to new name
   534         # Found the resource corresponding to old name and change its name to new name
   516         resource = self.Project.getConfigurationResource(config_name)
   535         resource = self.Project.getConfigurationResource(config_name)
   517         resource.setName(new_name)
   536         resource.setName(new_name)
   519         old_computedname = self.ComputeConfigurationResourceName(config_name, old_name)
   538         old_computedname = self.ComputeConfigurationResourceName(config_name, old_name)
   520         new_computedname = self.ComputeConfigurationResourceName(config_name, new_name)
   539         new_computedname = self.ComputeConfigurationResourceName(config_name, new_name)
   521         if old_computedname in self.ElementsOpened:
   540         if old_computedname in self.ElementsOpened:
   522             idx = self.ElementsOpened.index(old_computedname)
   541             idx = self.ElementsOpened.index(old_computedname)
   523             self.ElementsOpened[idx] = new_computedname
   542             self.ElementsOpened[idx] = new_computedname
       
   543         self.BufferProject()
   524     
   544     
   525     # Return the type of the pou given by its name
   545     # Return the type of the pou given by its name
   526     def GetPouType(self, name):
   546     def GetPouType(self, name):
   527         # Found the pou correponding to name and return its type
   547         # Found the pou correponding to name and return its type
   528         pou = self.Project.getPou(name)
   548         pou = self.Project.getPou(name)
   577     
   597     
   578     # Add a Transition to a Project Pou
   598     # Add a Transition to a Project Pou
   579     def ProjectRemovePouTransition(self, pou_name, transition_name):
   599     def ProjectRemovePouTransition(self, pou_name, transition_name):
   580         pou = self.Project.getPou(pou_name)
   600         pou = self.Project.getPou(pou_name)
   581         pou.removeTransition(transition_name)
   601         pou.removeTransition(transition_name)
       
   602         self.BufferProject()
   582     
   603     
   583     # Add a Transition to a Project Pou
   604     # Add a Transition to a Project Pou
   584     def ProjectRemovePouAction(self, pou_name, action_name):
   605     def ProjectRemovePouAction(self, pou_name, action_name):
   585         pou = self.Project.getPou(pou_name)
   606         pou = self.Project.getPou(pou_name)
   586         pou.removeAction(action_name)
   607         pou.removeAction(action_name)
       
   608         self.BufferProject()
   587     
   609     
   588     # Extract varlists from a list of vars
   610     # Extract varlists from a list of vars
   589     def ExtractVarLists(self, vars):
   611     def ExtractVarLists(self, vars):
   590         varlist_list = []
   612         varlist_list = []
   591         current_varlist = None
   613         current_varlist = None
   625             # Set configuration global vars
   647             # Set configuration global vars
   626             configuration.setGlobalVars([])
   648             configuration.setGlobalVars([])
   627             for vartype, varlist in self.ExtractVarLists(vars):
   649             for vartype, varlist in self.ExtractVarLists(vars):
   628                 configuration.globalVars.append(varlist)
   650                 configuration.globalVars.append(varlist)
   629         self.RefreshBlockTypes()
   651         self.RefreshBlockTypes()
   630 
   652         self.BufferProject()
       
   653     
   631     # Return the configuration globalvars
   654     # Return the configuration globalvars
   632     def GetConfigurationGlobalVars(self, name):
   655     def GetConfigurationGlobalVars(self, name):
   633         vars = []
   656         vars = []
   634         # Found the configuration corresponding to name
   657         # Found the configuration corresponding to name
   635         configuration = self.Project.getConfiguration(name)
   658         configuration = self.Project.getConfiguration(name)
   667         if resource:
   690         if resource:
   668             resource.setGlobalVars([])
   691             resource.setGlobalVars([])
   669             for vartype, varlist in self.ExtractVarLists(vars):
   692             for vartype, varlist in self.ExtractVarLists(vars):
   670                 resource.globalVars.append(varlist)
   693                 resource.globalVars.append(varlist)
   671         self.RefreshBlockTypes()
   694         self.RefreshBlockTypes()
   672 
   695         self.BufferProject()
       
   696     
   673     # Return the resource globalvars
   697     # Return the resource globalvars
   674     def GetConfigurationResourceGlobalVars(self, config_name, name):
   698     def GetConfigurationResourceGlobalVars(self, config_name, name):
   675         vars = []
   699         vars = []
   676         # Found the resource corresponding to name
   700         # Found the resource corresponding to name
   677         resource = self.Project.getConfigurationResource(config_name, name)
   701         resource = self.Project.getConfigurationResource(config_name, name)
   743         if not pou.interface:
   767         if not pou.interface:
   744             pou.interface = plcopen.pou_interface()
   768             pou.interface = plcopen.pou_interface()
   745         # Set Pou interface
   769         # Set Pou interface
   746         pou.setVars(self.ExtractVarLists(vars))
   770         pou.setVars(self.ExtractVarLists(vars))
   747         self.RefreshBlockTypes()
   771         self.RefreshBlockTypes()
   748 
   772         self.BufferProject()
       
   773     
   749     # Replace the return type of the pou given by its name (only for functions)
   774     # Replace the return type of the pou given by its name (only for functions)
   750     def SetPouInterfaceReturnType(self, name, type):
   775     def SetPouInterfaceReturnType(self, name, type):
   751         pou = self.Project.getPou(name)
   776         pou = self.Project.getPou(name)
   752         if not pou.interface:
   777         if not pou.interface:
   753             pou.interface = plcopen.pou_interface()
   778             pou.interface = plcopen.pou_interface()
   757             return_type = plcopen.dataType()
   782             return_type = plcopen.dataType()
   758             pou.interface.setReturnType(return_type)
   783             pou.interface.setReturnType(return_type)
   759         # Change return type
   784         # Change return type
   760         return_type.setValue(type)
   785         return_type.setValue(type)
   761         self.RefreshBlockTypes()
   786         self.RefreshBlockTypes()
       
   787         self.BufferProject()
   762     
   788     
   763     # Return the return type of the pou given by its name
   789     # Return the return type of the pou given by its name
   764     def GetPouInterfaceReturnTypeByName(self, name):
   790     def GetPouInterfaceReturnTypeByName(self, name):
   765         # Found the pou correponding to name and return the return type
   791         # Found the pou correponding to name and return the return type
   766         return self.GetPouInterfaceReturnType(self.Project.getPou(name))
   792         return self.GetPouInterfaceReturnType(self.Project.getPou(name))
  1949             tree = minidom.parse(xmlfile)
  1975             tree = minidom.parse(xmlfile)
  1950             xmlfile.close()
  1976             xmlfile.close()
  1951         
  1977         
  1952         self.Project = plcopen.project()
  1978         self.Project = plcopen.project()
  1953         self.Project.loadXMLTree(tree.childNodes[0])
  1979         self.Project.loadXMLTree(tree.childNodes[0])
  1954         self.UndoBuffer = UndoBuffer(self.Copy(self.Project), True)
       
  1955         self.SetFilePath(filepath)
  1980         self.SetFilePath(filepath)
       
  1981         self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), True)
       
  1982         self.Buffering = False
  1956         self.ElementsOpened = []
  1983         self.ElementsOpened = []
  1957         self.CurrentElementEditing = None
  1984         self.CurrentElementEditing = None
  1958         self.RefreshPouUsingTree()
  1985         self.RefreshPouUsingTree()
  1959         self.RefreshBlockTypes()
  1986         self.RefreshBlockTypes()
  1960 
  1987 
  1980                 xmlfile = open(filepath,"w")
  2007                 xmlfile = open(filepath,"w")
  1981             else:
  2008             else:
  1982                 xmlfile = open(self.FilePath,"w")
  2009                 xmlfile = open(self.FilePath,"w")
  1983             xmlfile.write(text)
  2010             xmlfile.write(text)
  1984             xmlfile.close()
  2011             xmlfile.close()
  1985             #self.ProjectBuffer.CurrentSaved()
  2012             self.ProjectBuffer.CurrentSaved()
  1986             if filepath:
  2013             if filepath:
  1987                 self.SetFilePath(filepath)
  2014                 self.SetFilePath(filepath)
  1988             return True
  2015             return True
  1989 
  2016 
  1990 #-------------------------------------------------------------------------------
  2017 #-------------------------------------------------------------------------------
  1996     """
  2023     """
  1997     def Copy(self, model):
  2024     def Copy(self, model):
  1998         return cPickle.loads(cPickle.dumps(model))
  2025         return cPickle.loads(cPickle.dumps(model))
  1999 
  2026 
  2000     def BufferProject(self):
  2027     def BufferProject(self):
  2001         self.ProjectBuffer.Buffering(self.Copy(self))
  2028         self.ProjectBuffer.Buffering(self.Copy(self.Project))
       
  2029 
       
  2030     def StartBuffering(self):
       
  2031         self.ProjectBuffer.Buffering(self.Project)
       
  2032         self.Buffering = True
       
  2033         
       
  2034     def EndBuffering(self):
       
  2035         if self.Buffering:
       
  2036             self.Project = self.Copy(self.Project)
       
  2037             self.Buffering = False
  2002 
  2038 
  2003     def ProjectIsSaved(self):
  2039     def ProjectIsSaved(self):
  2004         return self.ProjectBuffer.IsCurrentSaved()
  2040         return self.ProjectBuffer.IsCurrentSaved()
  2005 
  2041 
  2006     def LoadPrevious(self):
  2042     def LoadPrevious(self):
  2007         self.Project = self.Copy(self.ProjectBuffer.Previous())
  2043         self.Project = self.Copy(self.ProjectBuffer.Previous())
  2008         self.RefreshElementsOpened()
       
  2009     
  2044     
  2010     def LoadNext(self):
  2045     def LoadNext(self):
  2011         self.Project = self.Copy(self.ProjectBuffer.Next())
  2046         self.Project = self.Copy(self.ProjectBuffer.Next())
  2012         self.RefreshElementsOpened()
       
  2013     
  2047     
  2014     def GetBufferState(self):
  2048     def GetBufferState(self):
  2015         first = self.ProjectBuffer.IsFirst()
  2049         first = self.ProjectBuffer.IsFirst()
  2016         last = self.ProjectBuffer.IsLast()
  2050         last = self.ProjectBuffer.IsLast()
  2017         return not first, not last
  2051         return not first, not last