Index: main/waeup.sirp/trunk/src/waeup/sirp/browser/pages.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/browser/pages.py	(revision 6145)
+++ main/waeup.sirp/trunk/src/waeup/sirp/browser/pages.py	(revision 6146)
@@ -21,5 +21,6 @@
     from zope.app.security.interfaces import (
         IAuthentication, IUnauthenticatedPrincipal, ILogout)
-from zope.securitypolicy.interfaces import IPrincipalRoleManager, IPrincipalRoleMap
+from zope.securitypolicy.interfaces import (
+    IPrincipalRoleManager, IPrincipalRoleMap)
 from zope.component import (
     getUtility, createObject,getAllUtilitiesRegisteredFor)
@@ -32,5 +33,5 @@
     WAeUPDisplayFormPage, NullValidator)
 from waeup.sirp.browser.interfaces import (
-    IUniversity, IFacultyContainer, IFaculty, IFacultyAdd, 
+    IUniversity, IFacultyContainer, IFaculty, IFacultyAdd,
     IDepartment, IDepartmentAdd, ICourse, ICourseAdd, ICertificate,
     ICertificateAdd, ICertificateCourse, ICertificateCourseAdd)
@@ -38,7 +39,7 @@
 from waeup.sirp.interfaces import(
     IWAeUPObject, IUserContainer, IUserAccount, IDataCenter,
-    IWAeUPXMLImporter, IWAeUPXMLExporter, IBatchProcessor)
+    IWAeUPXMLImporter, IWAeUPXMLExporter, IBatchProcessor,
+    ILocalRolesAssignable)
 from waeup.sirp.university.catalog import search
-from waeup.sirp.university.faculty import local_roles as faculty_local_roles
 from waeup.sirp.university.vocabularies import course_levels
 from waeup.sirp.widgets.restwidget import ReSTDisplayWidget
@@ -99,5 +100,5 @@
     grok.require('waeup.Public')
     grok.name('logout')
-    
+
     def update(self):
         if not IUnauthenticatedPrincipal.providedBy(self.request.principal):
@@ -119,5 +120,5 @@
     grok.context(IUniversity)
     pnav = 0
-    
+
     form_fields = grok.AutoFields(IUniversity)
     form_fields['frontpage'].custom_widget = ReSTDisplayWidget
@@ -145,5 +146,5 @@
         self.flash('Settings have been saved.')
         return
-    
+
     @grok.action('Save and return')
     def saveAndReturn(self, **data):
@@ -164,5 +165,5 @@
         self.redirect(self.url(self.context))
         return
-        
+
 #class RemoveFormPage(WAeUPPage):
 #    grok.require('waeup.manageUniversity')
@@ -237,9 +238,9 @@
     def entries(self):
         return ()
-    
+
 #
 # User container pages...
 #
-    
+
 class UserContainerPage(WAeUPPage):
     """Overview page for all local users.
@@ -249,5 +250,5 @@
     grok.name('index')
     title = 'Portal Users'
-    
+
     def update(self, userid=None, adduser=None, edit=None, delete=None):
         if edit is not None and userid is not None:
@@ -290,5 +291,5 @@
     grok.context(IUserAccount)
     grok.name('index')
-    
+
     form_fields = grok.AutoFields(IUserAccount)
     grok.require('waeup.manageUsers')
@@ -301,5 +302,5 @@
         self.flash('User settings have been saved.')
         return
-    
+
     @grok.action('Save and return')
     def saveAndReturn(self, **data):
@@ -350,5 +351,5 @@
         self.hitlist = search(query=self.query, view=self)
         return
-        
+
 #
 # Contact forms...
@@ -360,5 +361,5 @@
     grok.require('waeup.Public')
     pnav = 2
-    
+
     def title(self):
         """Return True if the calling user is authenticated.
@@ -366,9 +367,9 @@
         userid = self.request.principal.id
         if userid != 'zope.anybody':
-            tt = u'Contact' 
+            tt = u'Contact'
         else:
-            tt = u'Enquiries'         
-        return tt     
-        
+            tt = u'Enquiries'
+        return tt
+
     def update(self, *args, **kw):
         form = self.request.form
@@ -381,5 +382,5 @@
         if not (fullname and email and descr):
             self.flash('Error: All fields must be filled!')
-            return        
+            return
         if not re.match("^[a-zA-Z0-9._%-]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$",
                         email):
@@ -394,5 +395,5 @@
         msg = MIMEText(text % (fullname,regno,descr))
         msg['From'] = '%s <%s>' % (fullname,email)
-        
+
         # These parameters should be part of the portal configuration.
         msg['To'] = 'contact@waeup.org'
@@ -404,8 +405,8 @@
         server = smtplib.SMTP('localhost')
         server.sendmail(email,'contact@waeup.org',msg.as_string())
-        
+
         server.quit()
         self.flash('Your message has been sent.')
-        return 
+        return
 
 #
@@ -426,5 +427,5 @@
     title = u'Data Center Upload'
     pnav = 0
-    
+
     def update(self, uploadfile=None, CANCEL=None, SUBMIT=None):
         if CANCEL is not None:
@@ -480,5 +481,5 @@
                 continue
             yield file
-    
+
     def update(self, filename=None, select=None, cancel=None):
         if cancel is not None:
@@ -512,5 +513,5 @@
         reader = csv.reader(open(self.fullpath, 'rb'))
         return reader.next()
-    
+
     def getPreviewBody(self):
         """Get the first 5 rows of attached CSV file.
@@ -553,5 +554,5 @@
         session = ISession(self.request)['waeup.sirp']
         self.filename = session.get('import_filename', None)
-        
+
         if self.filename is None or back1 is not None:
             self.redirect(self.url(self.context, '@@import1'))
@@ -588,5 +589,5 @@
     mode = None
     importername = None
-    
+
     @property
     def nextstep(self):
@@ -598,5 +599,5 @@
         reader = csv.reader(open(self.fullpath, 'rb'))
         return reader.next()
-    
+
     def getPreviewBody(self):
         """Get the first 5 rows of attached CSV file.
@@ -636,5 +637,5 @@
             result.append(fatal)
         return result
-    
+
     @property
     def nextstep(self):
@@ -646,5 +647,5 @@
         self.mode = session.get('import_mode', None)
         self.importername = session.get('import_importer', None)
-        
+
         if None in (self.filename, self.mode, self.importername):
             self.redirect(self.url(self.context, '@@import2'))
@@ -665,5 +666,5 @@
             self.redirect(self.url(self.context, '@@import4'))
             return
-        
+
         self.importer = getUtility(IBatchProcessor, name=self.importername)
         self.reader = csv.DictReader(open(self.fullpath, 'rb'))
@@ -697,5 +698,5 @@
         self.importername = session.get('import_importer', None)
         self.headerfields = session.get('import_headerfields', None)
-        
+
         if None in (self.filename, self.mode, self.importername,
                     self.headerfields):
@@ -708,5 +709,5 @@
             self.redirect(self.url(self.context, '@@show'))
             return
-            
+
         self.fullpath = os.path.join(self.context.storage, self.filename)
         self.importer = getUtility(IBatchProcessor, name=self.importername)
@@ -804,5 +805,5 @@
     grok.name('export.xml')
     grok.require('waeup.manageUniversity')
-    
+
     def render(self):
         exporter = IWAeUPXMLExporter(self.context)
@@ -865,9 +866,9 @@
     #        try:
     #            del self.context[code]
-    #            self.flash('Faculty %s successfully removed.' % code)                
+    #            self.flash('Faculty %s successfully removed.' % code)
     #        except:
     #            self.flash('Could not delete %s.' % code)
-    
-    
+
+
 class FacultyContainerManageFormPage(WAeUPEditFormPage):
     """Manage the basic properties of a `Faculty` instance.
@@ -885,5 +886,5 @@
     def label(self):
         return 'Manage academic section'
-        
+
     def update(self):
         tabs.need()
@@ -908,17 +909,17 @@
         if len(deleted):
             self.flash('Successfully removed: %s' % ', '.join(deleted))
-        self.redirect(self.url(self.context, '@@manage')+'#tab-1')    
-        return       
+        self.redirect(self.url(self.context, '@@manage')+'#tab-1')
+        return
 
     @grok.action('Add faculty', validator=NullValidator)
     def addFaculty(self, **data):
         self.redirect(self.url(self.context, '@@add'))
-        return    
-        
+        return
+
     @grok.action('Cancel', validator=NullValidator)
     def cancel(self, **data):
         self.redirect(self.url(self.context))
         return
-    
+
 
 class FacultyAddFormPage(WAeUPAddFormPage):
@@ -948,5 +949,5 @@
             return
         self.redirect(self.url(self.context, u'@@manage')+'#tab-1')
-        
+
     @grok.action('Cancel')
     def cancel(self, **data):
@@ -954,5 +955,5 @@
 
 #class RemoveFacultyFormPage(RemoveFormPage):
-#   """ Remove Faculty Page 
+#   """ Remove Faculty Page
 #    """
 #    grok.context(IFacultyContainer)
@@ -974,5 +975,5 @@
     def title(self):
         return self.context.longtitle()
-        
+
     @property
     def label(self):
@@ -984,8 +985,8 @@
     #        try:
     #            del self.context[code]
-    #            self.flash('Department %s successfully removed.' % code)                
+    #            self.flash('Department %s successfully removed.' % code)
     #        except:
     #            self.flash('Could not delete %s.' % code)
-    
+
 class FacultyManageFormPage(WAeUPEditFormPage):
     """Manage the basic properties of a `Faculty` instance.
@@ -1006,5 +1007,5 @@
     def label(self):
         return 'Manage faculty'
-        
+
     @property
     def title(self):
@@ -1012,7 +1013,7 @@
 
     def getLocalRoles(self):
-        #import pdb; pdb.set_trace()
-        return faculty_local_roles
-        
+        roles = ILocalRolesAssignable(self.context)
+        return roles()
+
     def getUsers(self):
         """Get a list of all users.
@@ -1032,5 +1033,5 @@
         self.applyData(self.context, **data)
         return
-          
+
     # ToDo: Show warning message before deletion
     @grok.action('Remove selected')
@@ -1050,17 +1051,17 @@
         if len(deleted):
             self.flash('Successfully removed: %s' % ', '.join(deleted))
-        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')    
-        return       
+        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')
+        return
 
     @grok.action('Add department', validator=NullValidator)
     def addDepartment(self, **data):
         self.redirect(self.url(self.context, '@@add'))
-        return    
-        
+        return
+
     @grok.action('Cancel', validator=NullValidator)
     def cancel(self, **data):
         self.redirect(self.url(self.context))
         return
-        
+
     @grok.action('Add local role', validator=NullValidator)
     def addLocalRole(self, **data):
@@ -1088,5 +1089,5 @@
     def title(self):
         return self.context.longtitle()
-    
+
     @grok.action('Add department')
     def addDepartment(self, **data):
@@ -1104,5 +1105,5 @@
             return
         self.redirect(self.url(self.context, u'@@manage')+'#tab-2')
-        
+
     @grok.action('Cancel')
     def cancel(self, **data):
@@ -1112,5 +1113,5 @@
 
 #class RemoveDepartmentFormPage(RemoveFormPage):
-#    """ Remove Department Page 
+#    """ Remove Department Page
 #    """
 #    grok.context(IFaculty)
@@ -1134,11 +1135,11 @@
     def title(self):
         return self.context.longtitle()
-    
+
     def update(self):
         tabs.need()
-        datatable.need() 
+        datatable.need()
         super(DepartmentPage, self).update()
         return
-        
+
     def getCourses(self):
         """Get a list of all stored courses.
@@ -1146,5 +1147,5 @@
         for key, val in self.context.courses.items():
             url = self.url(val)
-            yield(dict(url=url, name=key, container=val)) 
+            yield(dict(url=url, name=key, container=val))
 
     def getCertificates(self):
@@ -1153,5 +1154,5 @@
         for key, val in self.context.certificates.items():
             url = self.url(val)
-            yield(dict(url=url, name=key, container=val))              
+            yield(dict(url=url, name=key, container=val))
 
 class DepartmentManageFormPage(WAeUPEditFormPage):
@@ -1170,9 +1171,9 @@
     def label(self):
         return 'Manage department'
-        
-    @property
-    def title(self):
-        return self.context.longtitle()   
-        
+
+    @property
+    def title(self):
+        return self.context.longtitle()
+
     def getCourses(self):
         """Get a list of all stored courses.
@@ -1180,5 +1181,5 @@
         for key, val in self.context.courses.items():
             url = self.url(val)
-            yield(dict(url=url, name=key, container=val)) 
+            yield(dict(url=url, name=key, container=val))
 
     def getCertificates(self):
@@ -1187,9 +1188,9 @@
         for key, val in self.context.certificates.items():
             url = self.url(val)
-            yield(dict(url=url, name=key, container=val))                     
+            yield(dict(url=url, name=key, container=val))
 
     def update(self):
         tabs.need()
-        datatable.need() 
+        datatable.need()
         super(DepartmentManageFormPage, self).update()
         return
@@ -1201,5 +1202,5 @@
         self.applyData(self.context, **data)
         return
-        
+
     # ToDo: Show warning message before deletion
     @grok.action('Remove selected courses')
@@ -1219,8 +1220,8 @@
         if len(deleted):
             self.flash('Successfully removed: %s' % ', '.join(deleted))
-        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')    
-        return       
-     
-    @grok.action('Remove selected certificates')    
+        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')
+        return
+
+    @grok.action('Remove selected certificates')
     def delCertificates(self, **data):
         form = self.request.form
@@ -1238,17 +1239,17 @@
         if len(deleted):
             self.flash('Successfully removed: %s' % ', '.join(deleted))
-        self.redirect(self.url(self.context, u'@@manage')+'#tab-3')    
-        return               
+        self.redirect(self.url(self.context, u'@@manage')+'#tab-3')
+        return
 
     @grok.action('Add course', validator=NullValidator)
     def addCourse(self, **data):
         self.redirect(self.url(self.context, 'addcourse'))
-        return   
-        
+        return
+
     @grok.action('Add certificate', validator=NullValidator)
     def addCertificate(self, **data):
         self.redirect(self.url(self.context, 'addcertificate'))
-        return                     
-    
+        return
+
     @grok.action('Cancel', validator=NullValidator)
     def cancel(self, **data):
@@ -1265,9 +1266,9 @@
     form_fields = grok.AutoFields(ICourseAdd)
     pnav = 1
-    
-    @property
-    def title(self):
-        return self.context.longtitle()       
-    
+
+    @property
+    def title(self):
+        return self.context.longtitle()
+
     @grok.action('Add course')
     def addCourse(self, **data):
@@ -1284,5 +1285,5 @@
                                   'in the database')
             return
-        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')    
+        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')
 
     @grok.action('Cancel', validator=NullValidator)
@@ -1300,14 +1301,14 @@
     form_fields = grok.AutoFields(ICertificateAdd)
     pnav = 1
-    
-    @property
-    def title(self):
-        return self.context.longtitle()       
-        
+
+    @property
+    def title(self):
+        return self.context.longtitle()
+
     @grok.action('Add certificate')
     def addCertificate(self, **data):
         certificate = createObject(u'waeup.Certificate')
         self.applyData(certificate, **data)
-        
+
         #try:
         #    self.applyData(certificate, **data)
@@ -1317,5 +1318,5 @@
         #                          'available in workflow.')
         #    return
-        
+
         try:
             self.context.certificates.addCertificate(certificate)
@@ -1328,5 +1329,5 @@
                                   'in the database')
             return
-        self.redirect(self.url(self.context, u'@@manage')+'#tab-3')    
+        self.redirect(self.url(self.context, u'@@manage')+'#tab-3')
 
     @grok.action('Cancel', validator=NullValidator)
@@ -1361,5 +1362,5 @@
 
     form_fields = grok.AutoFields(ICourse)
-    
+
     @property
     def title(self):
@@ -1370,5 +1371,5 @@
         self.applyData(self.context, **data)
         return
-    
+
     @grok.action('Save and return')
     def saveAndReturn(self, **data):
@@ -1398,9 +1399,9 @@
     def title(self):
         return "Certificate: %s (%s)" % (self.context.title, self.context.code)
-        
+
     def update(self):
         tabs.need()
         #warning.need()
-        datatable.need() 
+        datatable.need()
         return super(CertificatePage, self).update()
 
@@ -1413,7 +1414,7 @@
     pnav = 1
     label = 'Edit certificate'
-    
+
     form_fields = grok.AutoFields(ICertificate)
-    
+
     pnav = 1
     grok.template('certificatemanagepage')
@@ -1424,15 +1425,15 @@
     def label(self):
         return 'Manage certificate'
-        
-    @property
-    def title(self):
-        return "Certificate: %s (%s)" % (self.context.title, self.context.code) 
+
+    @property
+    def title(self):
+        return "Certificate: %s (%s)" % (self.context.title, self.context.code)
 
     def update(self):
         tabs.need()
         #warning.need()
-        datatable.need() 
+        datatable.need()
         return super(CertificateManageFormPage, self).update()
-        
+
     form_fields = grok.AutoFields(ICertificate)
 
@@ -1441,5 +1442,5 @@
         self.applyData(self.context, **data)
         return
-        
+
     # ToDo: Show warning message before deletion
     @grok.action('Remove selected course referrers')
@@ -1459,19 +1460,19 @@
         if len(deleted):
             self.flash('Successfully removed: %s' % ', '.join(deleted))
-        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')    
-        return       
-     
+        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')
+        return
+
 
     @grok.action('Add course referrer', validator=NullValidator)
     def addCertificateCourse(self, **data):
         self.redirect(self.url(self.context, 'addcertificatecourse'))
-        return   
-        
+        return
+
     @grok.action('Cancel', validator=NullValidator)
     def cancel(self, **data):
         self.redirect(self.url(self.context))
         return
-    
-    
+
+
 class CertificateCourseAddFormPage(WAeUPAddFormPage):
     """Add-page to add a course ref to a certificate
@@ -1483,5 +1484,5 @@
     pnav = 1
     label = 'Add course referrer'
-    
+
     @property
     def title(self):
@@ -1523,6 +1524,6 @@
     def title(self):
         return 'Course Referrer: %s' % (self.context.longtitle())
-    
-    @property    
+
+    @property
     def leveltitle(self):
         return course_levels.getTerm(self.context.level).title
@@ -1537,9 +1538,9 @@
     label = 'Edit course referrer'
     pnav = 1
-    
+
     @property
     def title(self):
         return 'Course Referrer: %s' % (self.context.__name__)
-    
+
     @grok.action('Save and return')
     def saveAndReturn(self, **data):
