changeset 33:01b5265264b6

more work on projects.
author casties
date Wed, 24 Apr 2013 20:48:45 +0200
parents 6891732a148f
children b8ced08ebea9
files MPIWGProjects.py MPIWGRoot.py MPIWGRoot_deleted_methods.py zpt/project/edit_basic.zpt
diffstat 4 files changed, 266 insertions(+), 279 deletions(-) [+]
line wrap: on
line diff
--- a/MPIWGProjects.py	Tue Apr 23 20:54:02 2013 +0200
+++ b/MPIWGProjects.py	Wed Apr 24 20:48:45 2013 +0200
@@ -30,6 +30,7 @@
 from SrvTxtUtils import getInt, unicodify, utf8ify, refreshingImageFileIndexHtml
 from Products.MPIWGBibliography.BibliographyManager import BibliographyManager
 from bibliography import *
+from Products.ZDBInterface.ZDBInterfaceFolder import ZDBInterfaceFolder
 #import xml.dom.minidom
 #from Ft.Xml.XPath import Evaluate
 #from Ft.Xml.XPath.Context import Context
@@ -49,6 +50,29 @@
 
 import transaction
 
+
+# TODO: fix this
+fieldLabels={'WEB_title':'WEB_Title',
+         'xdata_01':'Responsible Scientists',
+         'xdata_02':'Department',
+         'xdata_03':'Historical Persons',
+         'xdata_04':'Time period',
+         'xdata_05':'Sorting number',
+         'xdata_06':'Keywords',
+         'xdata_07':'Short title',
+         'xdata_08':'Other involved scholars' ,
+         'xdata_09':'Disciplines',
+         'xdata_10':'Themes',
+         'xdata_11':'Object Digitallibrary',
+         'xdata_12':'Cooperation partners',
+         'xdata_13':'Funding institutions',
+         'WEB_project_header':'WEB_project_header',
+         'WEB_project_description':'WEB_project_description',
+         'WEB_related_pub':'WEB_related_pub'}
+
+checkFields = ['xdata_01']
+
+
 # die folgenden Klassen sind jetzt in einzelne Files ausgelagert aus Kompatibilitaetsgruenden, bleiben die Klassen hier noch drin.
 # Sonst funktionieren die alten Webseiten nicht mehr.
 
@@ -258,46 +282,25 @@
 class MPIWGProject(CatalogAware,Folder,Cacheable):
     """Class for Projects"""
     
-    def _p_resolveConflict(self, oldState, savedState, newState):
-        return newState
-
-    security=ClassSecurityInfo()
-    meta_type='MPIWGProject'
-    default_catalog='ProjectCatalog'
+    security = ClassSecurityInfo()
+    meta_type = 'MPIWGProject'
     
     manage_options = Folder.manage_options+(
         {'label':'Load New File','action':'loadNewFileForm'},
         {'label':'Edit','action':'editForm'},
         )
-
         #{'label':'Edit ProjectInfo','action':'editMPIWGProjectForm'},
         #{'label':'Edit BasisInfo','action':'editMPIWGBasisForm'},
         #{'label':'Edit Publications','action':'editMPIWGRelatedPublicationsForm'},
         #{'label':'Edit Themes & Disciplines','action':'editMPIWGDisciplinesThemesForm'},
         #{'label':'Versionmanager','action':'versionManageForm'},
 
+    # enthaelt die Lister der verantwortlichen Wissenschaftler in der Form (NAME, KEY), key ist "" falls Wissenschaftler nicht an unserem Haus
+    responsibleScientistsList=[]
 
-    # TODO: fix this
-    fieldLabels={'WEB_title':'WEB_Title',
-             'xdata_01':'Responsible Scientists',
-             'xdata_02':'Department',
-             'xdata_03':'Historical Persons',
-             'xdata_04':'Time period',
-             'xdata_05':'Sorting number',
-             'xdata_06':'Keywords',
-             'xdata_07':'Short title',
-             'xdata_08':'Other involved scholars' ,
-             'xdata_09':'Disciplines',
-             'xdata_10':'Themes',
-             'xdata_11':'Object Digitallibrary',
-             'xdata_12':'Cooperation partners',
-             'xdata_13':'Funding institutions',
-             'WEB_project_header':'WEB_project_header',
-             'WEB_project_description':'WEB_project_description',
-             'WEB_related_pub':'WEB_related_pub'}
-
-    checkFields = ['xdata_01']
-
+    #
+    # templates
+    #
     edit_css = ImageFile('css/edit.css', globals())
     # make css refreshable for development
     edit_css.index_html = refreshingImageFileIndexHtml
@@ -484,8 +487,6 @@
             
     def manageImages(self,imageName=None,op=None):
         """managage images"""
-
-
         if imageName and op:
             if op=='up':
                 images=self.getImages()
@@ -512,8 +513,6 @@
 
     def managePublications(self,pubName=None,op=None):
         """managage images"""
-
-
         if pubName and op:
             if op=='up':
                 publications=self.getPublications()
@@ -540,8 +539,6 @@
     
     def manageRelatedProjects(self,pubName=None,op=None):
         """managage relatedProjectd"""
-
-
         if pubName and op:
             if op=='up':
                 relatedProjects=self.getRelatedProjects()
@@ -640,9 +637,6 @@
 
     def addRelatedProject(self,link,RESPONSE=None):
         """add an MPIWG_Publication"""
-
-        
-        
         number=self.getLastPublicationNumber()+1
         name="RelatedProject"+str(number)
         while hasattr(self,name):
@@ -677,7 +671,6 @@
         obj.id=name
         self.ZCacheable_invalidate()
         if RESPONSE is not None:
-        
             self.redirect(RESPONSE,'manageRelatedProjects')
 
  
@@ -717,7 +710,12 @@
 
     def getNumber(self):
         """returns sorting number"""
-        return getattr(self, 'xdata_05', None)
+        n = getattr(self, 'xdata_05', None)
+        if isinstance(n, list):
+            # compat with old lists
+            return n[0]
+        else:
+            return n
     
               
     def getUrl(self, baseUrl=None):
@@ -820,10 +818,6 @@
             
             self.redirect(RESPONSE,'manageImages')
 
-    def PrincipiaSearchSource(self):
-        """Return cataloguable key for ourselves."""
-        return str(self)
-
     def versionHeader(self):
         """version Header, gibt header text entsprechend der aktuellen version aus"""
         
@@ -857,7 +851,6 @@
             else:
                 return None
 
-
         else:
             finds.sort(sortProjectsByTime)
 
@@ -887,17 +880,6 @@
         else:
             return 1
         
-    def isActualForIndex(self): #isActual kann nicht indiziert werden, da intern fom ZCAtalog verwendete Funktion
-        """gibt 1 zurueck wenn aktuell, 0 sonst"""
-        actualTime=time.localtime()
-        
-        
-        #print getattr(self,'archiveTime',actualTime)
-        if getattr(self,'archiveTime',actualTime)< actualTime:
-            return 0
-        else:
-            return 1
-        
     def copyObjectToArchive(self):
         """kopiere aktuelles objekt ins archiv"""
         logging.info("copytoarchive 1")
@@ -935,7 +917,6 @@
         self.invisible=invisible
 
         if RESPONSE is not None:
-            
             self.redirect(RESPONSE,'manage_main')
 
    
@@ -1290,19 +1271,20 @@
 
         text=u''
 
-        for x in getattr(self,field):
-            
-            try:
-                text +=x
-            except:
-                text = x
-            
-        
+        f = getattr(self,field)
+        if isinstance(f, list):
+            # compat with old lists
+            for x in f:
+                try:
+                    text +=x
+                except:
+                    text = x
+        else:
+            text = f
 
         try:
             if text[len(text)-1]==";":
                 text=text[0:len(text)-1]
-          
                 
         except:
             pass
@@ -1527,9 +1509,6 @@
 
     def isResponsibleScientist(self,key):
         """teste ob eine Person in der Liste der respl. scientists auftaucht"""
-        #logging.info("XXXXXXXXXXXXX"+repr(self.responsibleScientistsList))
-  
-        
         keys = [unicodify(x[1]) for x in getattr(self,"responsibleScientistsList",[])]
         #logging.error("RESP. SCIEN:%s"%getattr(self,"responsibleScientistsList",[]))
         #logging.error("RESP. SCIEN:%s"%unicodify(key))
@@ -1577,32 +1556,27 @@
         
         return list
         
-        ##nameList=nameList.replace(";",",") # falls ; als Trenner ersetze    
-        
-        
-        
         
     def identifyNames(self,nameList):
         """Bekommt eine Komma oder Semikolon getrennte Liste mit Name der Form Vorname MittelName(n) Nachname
-        und ordnet diese dann Mitarbeiter IDs zu falls es schone eine Liste gibt wird im Projekte gibt wird diese Upgedated.
+        und ordnet diese dann Mitarbeiter IDs zu.
+        
+        Returns a dict with full names as keys and a row of person objects from the database as values.
+        
         @param nameList
         """
-        
         if nameList.find(";")>-1: # rate Trenner ist ;
-          names=nameList.split(";")  
-          
+            names=nameList.split(";")  
         else:
             names=nameList.split(",")
             
         ##nameList=nameList.replace(";",",") # falls ; als Trenner ersetze    
         returnNamesDict={}
-
        
         for name in names:
-            name=name.lstrip().rstrip()
+            name=name.strip()
             nameSplitted = name.split(" ")
             if len(nameSplitted)>1:  #vor und nachname angegeben)
-              
                 lastname=nameSplitted[-1]
                 firstname=nameSplitted[0]
             else:
@@ -1611,28 +1585,29 @@
                
             #finde Mitarbeiter mit den entsprechenden Name
             
-            firstname=self.myCapitalize(firstname).encode('utf-8')
-            lastname=self.myCapitalize(lastname).encode('utf-8')
-            logging.info("Search: %s %s %s"%(name,repr(firstname),repr(lastname)))
+            #firstname=self.myCapitalize(firstname).encode('utf-8')
+            #lastname=self.myCapitalize(lastname).encode('utf-8')
+            logging.debug("Search: %s %s %s"%(name,repr(firstname),repr(lastname)))
             try:
-                cataloggedNames=self.MembersCatalog(firstName=firstname,lastName=lastname)
+                #cataloggedNames=self.MembersCatalog(firstName=firstname,lastName=lastname)
+                # TODO: I think this does not work without firstname
+                # try to find names in members db by searching for sub-words
+                cataloggedNames = self.executeZSQL("select * from personal_www where first_name ~* ('\m'||%s||'\M') and last_name ~* ('\m'||%s||'\M')", (firstname, lastname))
+                if len(cataloggedNames) == 0:
+                    # PostgreSQL has a bug with \m and words ending in non-ASCII :-(
+                    cataloggedNames = self.executeZSQL("select * from personal_www where %s in (select regexp_split_to_table(lower(first_name), '\s+')) and %s in (select regexp_split_to_table(lower(last_name), '\s+'))", (firstname.lower(), lastname.lower()))
             except:
                 cataloggedNames=[]
                 logging.error("ERROR: identifyNames %s %s"%sys.exc_info()[0:2])
             
-            #Teste ob die ensprechenden Namen schon der Liste zu geordnet sind
-            #if not hasattr(self,'responsibleScientistsList'):
-            #     self.responsibleScientistsList={}
-            # 
-            # if name in self.responsibleScientistsList.values()
-            
             if len(cataloggedNames)>0:
                returnNamesDict[name]=cataloggedNames
             else:
                 returnNamesDict[name]=[]
        
-        logging.error("id: %s"%repr(returnNamesDict))
+        logging.debug("id: %s"%repr(returnNamesDict))
         return returnNamesDict
+
         
     def editMPIWGProject(self,RESPONSE=None,fromEdit=None):
         """edit the project and archive the old version"""
@@ -1642,11 +1617,8 @@
 
         for x in definedFields:
             if self.REQUEST.has_key(x):
-                
-                setattr(self,x,[self.REQUEST[x].decode('utf-8')])
-
-        
-       
+                logging.debug("editMPIWGProject: key=%s val=%s"%(repr(x),repr(self.REQUEST.get(x))))
+                setattr(self,x,self.REQUEST.get(x))
 
         completedAt = self.REQUEST.get('completedAt')
         if not self.setCompletedAt(completedAt):
@@ -1656,9 +1628,6 @@
         if not self.setStartedAt(startedAt):
             RESPONSE.redirect('./editMPIWGBasisEditor?error="dateWrong')
         
-        if self.REQUEST.has_key('historicalNames'):
-            self.en.changeHistoricalNames(self.getId(),self.REQUEST['historicalNames'].split("\n"))
-        
         if self.REQUEST.has_key('active'):
             self.setActiveFlag(True)
         else:
@@ -1677,62 +1646,22 @@
                     names[nr]=self.REQUEST[key]
                 elif splitted[1]=="key":
                     keys[nr]=self.REQUEST[key]
-                
          
         for nr in names.keys():#schreibe keys und namen in die Liste, stelle ausserdem sicher, dass name unicode
              tmpList.append((unicodify(names[nr]),unicodify(keys.get(nr,""))))
              
         self.responsibleScientistsList=tmpList
         
-        self.reindex_object()
+        #self.reindex_object()
         if fromEdit and (RESPONSE is not None):
             #RESPONSE.redirect('./editMPIWGBasisEditor')
-            return self.editMPIWGBasisEditor(identifiedNames=self.identifyNames(self.decode(self.REQUEST.get('xdata_01',''))))
+            return self.editBasic(identifiedNames=self.identifyNames(self.decode(self.REQUEST.get('xdata_01',''))))
             
         else:
             if RESPONSE is not None:
                 RESPONSE.redirect('manage_main')
 
 
-
-    security.declareProtected('View managment screens','editMPIWGDisciplinesThemesEditor')
-    def editMPIWGDisciplinesThemesEditor(self):
-        """edit from edit"""
-        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGDisciplinesThemesNeu.zpt')).__of__(self)
-        return pt()
-        
-    
-    def editMPIWGDisciplinesThemesForm(self):
-        """edit the disciplines and themes Form"""
-     
-        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGDisciplinesThemes.zpt')).__of__(self)
-        return pt()
-
-    def editMPIWGDisciplinesThemes(self,disciplines=None,themes=None,RESPONSE=None,fromEdit=None):
-        """edit disciplin and form"""
-        if disciplines:
-            if type(disciplines) is StringType:
-                self.xdata_09=disciplines
-            else:
-                self.xdata_09=";".join(disciplines)
-        else:
-                self.xdata_09=""
-        if themes:
-            if type(themes) is StringType:
-                self.xdata_10=themes
-            else:
-                self.xdata_10=";".join(themes)
-        else:
-            self.xdata_10=""
-
-        if fromEdit and (RESPONSE is not None):
-            self.redirect(RESPONSE,'./editMPIWGDisciplinesThemesEditor')
-
-        else:
-            if RESPONSE is not None:
-                RESPONSE.redirect('manage_main')
-
-
     def isChecked(self,wert,list):
         """check if wert is in ; seperated list"""
 
@@ -1752,7 +1681,6 @@
 
     security.declareProtected('View management screens','editBasic')
     def editBasic(self, identifiedNames=None):
-                            
         """editform"""
         if not identifiedNames:
             identifiedNames=self.identifyNames(self.getContent('xdata_01'))
@@ -1762,6 +1690,7 @@
         pt=PageTemplateFile('zpt/project/edit_basic', globals()).__of__(self)
         return pt(identifiedNames=identifiedNames)
 
+
     security.declareProtected('View management screens','editMPIWGBasisForm')
     def editMPIWGBasisForm(self):
         """editform"""
@@ -1839,7 +1768,7 @@
         RESPONSE.redirect('manage_main')
 
 
-class MPIWGProjectFolder(Folder):
+class MPIWGProjectFolder(ZDBInterfaceFolder):
     """Folder of project objects"""
 
     meta_type="MPIWGProjectFolder"
@@ -1872,7 +1801,8 @@
     
     
     def getProjectList(self, start, active=1, archived=1):
-        """returns list of projects starting at start.
+        """returns list of projects, starting from start.
+
         active = 0 : all projects
         active = 1 : active projects
         active = 2 : inactive projects
@@ -1890,8 +1820,75 @@
         #logging.debug("getProjectList: node=(%s,%s) pl=%s"%(node.key,node.value,pl))
         # return filtered list
         return [p for p in pl if (p.checkActive(active) and p.checkArchived(archived))]     
+    
+    
+    def getProjectsOfMember(self, key, active=1, archived=1):
+        """returns a list of all projects of a member.
+    
+        @param key: member's key
+        active = 0 : all projects
+        active = 1 : active projects
+        active = 2 : inactive projects
+        archived = 0 : all projects
+        archived = 1 : current projects
+        archived = 2 : archived projects
+        """
+        projects = []
+        # search project numbers
+        res = self.executeZSQL("select * from projects_members where lower(member_key) = %s", [key.lower()])
+        tree = self.getTree()
+        # find projects in tree
+        for r in res:
+            p = tree.get(r.project_number)
+            if p is not None and p.checkActive(active) and p.checkArchived(archived):
+                projects.append(p)
+            
+        return projects        
         
         
+    security.declareProtected('View management screens','updateAllProjectMembers')
+    def updateAllProjectMembers(self, updateResponsibleScientistsList=False):
+        """re-creates responsibleScientistsLists and projects_members table from all current projects"""
+        # empty table
+        self.executeZSQL('truncate table projects_members')
+        cnt = 0
+        # go through all projects
+        for p in self.objectValues(spec='MPIWGProject'):
+            cnt += 1
+            memberlist = []
+            logging.debug("updateAllProjectMembers: updating project %s"%p)
+            if updateResponsibleScientistsList:
+                newlist = []
+                names = p.identifyNames(p.getContent('xdata_01'))
+                for name in names.keys():
+                    logging.debug("updateAllProjectMembers: name=%s"%repr(name))
+                    members = names[name]
+                    if len(members) > 0:
+                        # take the first matching name
+                        newlist.append([name, members[0].key])
+                    
+                memberlist = newlist
+            
+            else:
+                memberlist = p.responsibleScientistsList
+                
+            # add members to table
+            for m in memberlist:
+                memberKey = m[1]
+                if not memberKey or not isinstance(memberKey, basestring):
+                    logging.error("updateAllProjectMembers: not a valid member key: %s"%repr(memberKey))
+                    continue
+                
+                pNum = p.getNumber()
+                if not pNum or not isinstance(pNum, basestring):
+                    logging.error("updateAllProjectMembers: not a valid project number: %s"%repr(pNum))
+                    continue
+                
+                self.executeZSQL('insert into projects_members (project_number, member_key) values (%s, %s)', (pNum, memberKey))
+
+        return "updated %s projects!"%cnt
+
+        
 def manage_addMPIWGProjectFolderForm(self):
     """form for adding a MPIWGProjectFolder"""
     pt = PageTemplateFile('zpt/project/manage_add_MPIWGProjectFolder', globals()).__of__(self)
--- a/MPIWGRoot.py	Tue Apr 23 20:54:02 2013 +0200
+++ b/MPIWGRoot.py	Wed Apr 24 20:48:45 2013 +0200
@@ -1284,124 +1284,6 @@
         return (fieldname in checkFields)
 
     
-    def generateNameIndex(self):
-        """erzeuge einen index verwendeter personen"""
-        import psycopg
-        o = psycopg.connect('dbname=authorities user=dwinter password=3333',serialize=0) 
-        results={}
-        print self.fulltext.historicalNames.items()
-        for nameItem in self.fulltext.historicalNames.items(): #gehe durch alle namen des lexikons
-            
-            c = o.cursor() 
-            name=nameItem[0]
-            print "check",name
-            c.execute("select lastname,firstname from persons where lower(lastname) = '%s'"%quote(name))
-            tmpres=c.fetchall()
-            firstnames=[result[1] for result in tmpres] # find all firstnames
-            if tmpres:
-                lastname=tmpres[0][0]
-                
-            for found in self.fulltext({'names':name}):
-                if found.getObject().isActual():
-                    for nh in found.getObject().getGetNeighbourhood(name, length=50,tagging=False): #hole umgebung
-                        #schaue nun ob der vorname hinter oder vor dem name ist
-                        position=nh.find(lastname)
-                        # vorher
-                        #print "NH",nh
-                        bevorS=nh[0:position].split()
-                        #print "BV",bevorS
-                        if len(bevorS)>1:
-                            try:
-                                bevor=[bevorS[-1],bevorS[-2]]
-                            except:
-                                bevor=[bevorS[0]]
-                        else:
-                            bevor=[]
-                        #nachher
-                        behindS= re.split("[,|;| ]",nh[position:]) 
-                        #print "BH",behindS
-                        if len(behindS)>2:
-                            try:
-                                behind=behindS[1:3]
-                            except:
-                                behind=[bevorS[1]]
-                        else:
-                            behind=[]
-                        for firstname in firstnames:
-                            if firstname in bevor+behind: #Namen wie mit Adelspraedikaten werden so erstmal nich gefunden
-                                id="%s,%s"%(lastname,firstname)
-                                if not results.has_key(id):
-                                    results[id]=[]
-                                objId=found.getObject().getId()
-                                if not (objId in results[id]):
-                                    print "d %s for %s"%(id,objId)    
-                                    results[id].append(objId)    
-            self.nameIndex=results
-        return results
-                    
-    def editNameIndexHTML(self):
-        """edit the name index"""
-        if not hasattr(self,'nameIndexEdited'): # falls editierter index noch nicht existiert, kopiere automatisch erstellten
-            self.nameIndexEdited=copy.copy(self.nameIndex)
-            print "huh"
-        #self.nameIndexEdited=copy.copy(self.nameIndex)
-        #print self.nameIndexEdited
-        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','editHistoricalNames.zpt')).__of__(self)
-        return pt()
-    
-    def getNamesInProject(self,projectId):
-        """get all names ofnameIndexEdited which are references in projec with projectId"""
-        
-        ret=[]
-        for name in self.nameIndexEdited.keys():
-            if projectId in self.nameIndexEdited[name]:
-                ret.append(name)
-        
-        return ret
-    
-    def editNameIndex(self,RESPONSE=None,name=None,occurrances=None,submit=None):
-        """edit the index"""
-        nI=self.nameIndexEdited # mI introduced to make sure that changes to nameIndexEdited are know to ZODB
-        if submit=="delete":
-           
-
-            dh=getattr(self,'deletedHistoricalNames',{})
-            
-            if type(dh) is ListType:
-                dh={}
-            if not dh.has_key(name):
-                dh[name]=occurrances.split("\n")
-            else:
-                dh[name]+=occurrances.split("\n")
-            
-            self.deletedHistoricalNames=dh
-            
-            del self.nameIndexEdited[name]
-            
-        
-        elif (submit=="change"):
-            
-            nI[name]=occurrances.split("\n")[0:]
-            
-        elif (submit=="add"):
-            if not nI.has_key(name):
-                nI[name]=occurrances.split("\n")
-            else:
-                nI[name]+=occurrances.split("\n")
-    
-        self.nameIndexEdited=nI
-   
-      
-        if RESPONSE is not None:
-            RESPONSE.redirect('editNameIndexHTML')
-        
-    
-    
-    def restoreIndex(self):
-        """restore"""
-        self.nameIndexEdited=self.nameIndex
-        return "done"
-    
 
     def sortResults(self,results):
         """search the catalog and give results back sorted by meta_type"""
--- a/MPIWGRoot_deleted_methods.py	Tue Apr 23 20:54:02 2013 +0200
+++ b/MPIWGRoot_deleted_methods.py	Wed Apr 24 20:48:45 2013 +0200
@@ -1,4 +1,4 @@
-       def removeStopWords(self,xo):
+    def removeStopWords(self,xo):
         """remove stop words from xo"""
         if not hasattr(self,'_v_stopWords'):
             self._v_stopWords=self.stopwords_en.data.split("\n")
@@ -181,4 +181,124 @@
                 fh=file("/tmp/harvest_MPIWG/"+name,"w")
                 fh.write(txt)
                 fh.close()
-                
\ No newline at end of file
+                
+                
+                
+    def generateNameIndex(self):
+        """erzeuge einen index verwendeter personen"""
+        import psycopg
+        o = psycopg.connect('dbname=authorities user=dwinter password=3333',serialize=0) 
+        results={}
+        print self.fulltext.historicalNames.items()
+        for nameItem in self.fulltext.historicalNames.items(): #gehe durch alle namen des lexikons
+            
+            c = o.cursor() 
+            name=nameItem[0]
+            print "check",name
+            c.execute("select lastname,firstname from persons where lower(lastname) = '%s'"%quote(name))
+            tmpres=c.fetchall()
+            firstnames=[result[1] for result in tmpres] # find all firstnames
+            if tmpres:
+                lastname=tmpres[0][0]
+                
+            for found in self.fulltext({'names':name}):
+                if found.getObject().isActual():
+                    for nh in found.getObject().getGetNeighbourhood(name, length=50,tagging=False): #hole umgebung
+                        #schaue nun ob der vorname hinter oder vor dem name ist
+                        position=nh.find(lastname)
+                        # vorher
+                        #print "NH",nh
+                        bevorS=nh[0:position].split()
+                        #print "BV",bevorS
+                        if len(bevorS)>1:
+                            try:
+                                bevor=[bevorS[-1],bevorS[-2]]
+                            except:
+                                bevor=[bevorS[0]]
+                        else:
+                            bevor=[]
+                        #nachher
+                        behindS= re.split("[,|;| ]",nh[position:]) 
+                        #print "BH",behindS
+                        if len(behindS)>2:
+                            try:
+                                behind=behindS[1:3]
+                            except:
+                                behind=[bevorS[1]]
+                        else:
+                            behind=[]
+                        for firstname in firstnames:
+                            if firstname in bevor+behind: #Namen wie mit Adelspraedikaten werden so erstmal nich gefunden
+                                id="%s,%s"%(lastname,firstname)
+                                if not results.has_key(id):
+                                    results[id]=[]
+                                objId=found.getObject().getId()
+                                if not (objId in results[id]):
+                                    print "d %s for %s"%(id,objId)    
+                                    results[id].append(objId)    
+            self.nameIndex=results
+        return results
+                    
+    def editNameIndexHTML(self):
+        """edit the name index"""
+        if not hasattr(self,'nameIndexEdited'): # falls editierter index noch nicht existiert, kopiere automatisch erstellten
+            self.nameIndexEdited=copy.copy(self.nameIndex)
+            print "huh"
+        #self.nameIndexEdited=copy.copy(self.nameIndex)
+        #print self.nameIndexEdited
+        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','editHistoricalNames.zpt')).__of__(self)
+        return pt()
+    
+    def getNamesInProject(self,projectId):
+        """get all names ofnameIndexEdited which are references in projec with projectId"""
+        
+        ret=[]
+        for name in self.nameIndexEdited.keys():
+            if projectId in self.nameIndexEdited[name]:
+                ret.append(name)
+        
+        return ret
+    
+    def editNameIndex(self,RESPONSE=None,name=None,occurrances=None,submit=None):
+        """edit the index"""
+        nI=self.nameIndexEdited # mI introduced to make sure that changes to nameIndexEdited are know to ZODB
+        if submit=="delete":
+           
+
+            dh=getattr(self,'deletedHistoricalNames',{})
+            
+            if type(dh) is ListType:
+                dh={}
+            if not dh.has_key(name):
+                dh[name]=occurrances.split("\n")
+            else:
+                dh[name]+=occurrances.split("\n")
+            
+            self.deletedHistoricalNames=dh
+            
+            del self.nameIndexEdited[name]
+            
+        
+        elif (submit=="change"):
+            
+            nI[name]=occurrances.split("\n")[0:]
+            
+        elif (submit=="add"):
+            if not nI.has_key(name):
+                nI[name]=occurrances.split("\n")
+            else:
+                nI[name]+=occurrances.split("\n")
+    
+        self.nameIndexEdited=nI
+   
+      
+        if RESPONSE is not None:
+            RESPONSE.redirect('editNameIndexHTML')
+        
+    
+    
+    def restoreIndex(self):
+        """restore"""
+        self.nameIndexEdited=self.nameIndex
+        return "done"
+    
--- a/zpt/project/edit_basic.zpt	Tue Apr 23 20:54:02 2013 +0200
+++ b/zpt/project/edit_basic.zpt	Wed Apr 24 20:48:45 2013 +0200
@@ -32,16 +32,6 @@
               </tal:block></td>
           </tr>
         </tal:block>
-        <!--    <tr>
-     <td><b>Historical names (new)</b><br/>
-     Please names enter as <br>
-      LASTNAME,FIRSTNAME <br/>or LASTNAME,FIRSTNAME MIDDLE.. <br> with 
-     <em>no space</em> before FIRSTNAME
-     </td>
-     <td><textarea name="historicalNames" tal:content="python:'\n'.join(here.getNamesInProject(here.getId()))" rows="10" cols="30">NAMES</textarea>
-     </td>
-    </tr> 
-    -->
         <tr tal:define="hasChildren python:here.hasChildren()">
           <td>Project is visible</td>
           <tal:x tal:condition="python:hasChildren and here.isActiveProject()">
@@ -83,14 +73,12 @@
           <td>
             <table>
               <tr tal:repeat="member python:identifiedName[1]">
-                <tal:y define="memberObj member/getObject">
-                  <td tal:content="python:here.decode(memberObj.getKey())" />
-                  <td tal:content="python:memberObj.getId()" />
+                  <td tal:content="python:member.key" />
+                  <td tal:content="python:member.e_mail" />
                   <td><input type="checkbox"
-                    tal:attributes="name python:'responsibleScientist_key_%s'%count; value python:memberObj.getKey();
-                      checked python:here.isResponsibleScientist(memberObj.getKey())" />
+                    tal:attributes="name python:'responsibleScientist_key_%s'%count; value python:member.key;
+                      checked python:here.isResponsibleScientist(member.key)" />
                   </td>
-                </tal:y>
               </tr>
             </table>