Merge with 631c0edee9ea995d0f2fa3b93742f715933c3800
authorverrierj
Tue, 10 Jan 2012 16:09:28 +0100
changeset 344 76724cebff95
parent 343 1b9b509013a7 (diff)
parent 338 631c0edee9ea (current diff)
child 345 a1fd64fbb680
Merge with 631c0edee9ea995d0f2fa3b93742f715933c3800
.settings/org.eclipse.core.resources.prefs
src/ldt/ldt/api/ldt/handlers.py
src/ldt/ldt/ldt_utils/models.py
src/ldt/ldt/ldt_utils/utils.py
--- a/.settings/org.eclipse.core.resources.prefs	Mon Jan 09 15:12:15 2012 +0100
+++ b/.settings/org.eclipse.core.resources.prefs	Tue Jan 10 16:09:28 2012 +0100
@@ -1,4 +1,4 @@
-#Thu Dec 15 18:08:14 CET 2011
+#Tue Jan 10 14:25:22 CET 2012
 eclipse.preferences.version=1
 encoding//src/ldt/ldt/core/migrations/0001_initial.py=utf-8
 encoding//src/ldt/ldt/core/migrations/0002_auto__del_owner.py=utf-8
@@ -7,6 +7,10 @@
 encoding//src/ldt/ldt/ldt_utils/migrations/0003_auto__chg_field_project_owner.py=utf-8
 encoding//src/ldt/ldt/ldt_utils/migrations/0004_auto__add_field_project_description.py=utf-8
 encoding//src/ldt/ldt/ldt_utils/migrations/0005_add_permissions.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0007_auto__add_field_content_image__del_field_media_image.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0009_auto__chg_field_content_image__chg_field_project_image.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0010_auto__add_annotationstat.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0011_gen_stat_annotation.py=utf-8
 encoding//src/ldt/ldt/text/migrations/0001_initial.py=utf-8
 encoding//src/ldt/ldt/user/migrations/0001_initial.py=utf-8
 encoding//src/ldt/ldt/user/migrations/0002_auto__del_irigroup.py=utf-8
--- a/src/ldt/ldt/api/ldt/handlers.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/api/ldt/handlers.py	Tue Jan 10 16:09:28 2012 +0100
@@ -1,9 +1,10 @@
-from ldt.ldt_utils.models import Project
+from ldt.ldt_utils.models import Project, Content
 from piston.handler import BaseHandler
 from piston.utils import rc, require_extended
 from ldt.ldt_utils.utils import LdtAnnotation
+from ldt.ldt_utils.stat import add_annotation_to_stat
+from ldt.security.utils import protect_instance, unprotect_instance
 import logging #@UnresolvedImport
-import lxml.etree
 
 
 class ProjectHandler(BaseHandler):
@@ -144,7 +145,7 @@
         }
         
         """
-        
+        #return rc.ALL_OK
         #assert False, " TIBO str(request.data) = " + str(request.data)
         if request.content_type.lower().find("application/json") > -1 :
             try:
@@ -152,8 +153,9 @@
             except Project.DoesNotExist:
                 return rc.NOT_HERE
         
-            adder = LdtAnnotation(project, force_save=True)
+            adder = LdtAnnotation(project)
             logging.debug("request json " + repr(request.data))
+            unprotect_instance(project) # allows anonymous user to save project
 
             meta = request.data['meta']
             author = meta['creator']
@@ -165,12 +167,23 @@
                 begin = str(a['begin'])
                 new_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['data'], '', a['tags'], begin, dur, author, date)
                 if not new_id:
+                    protect_instance(project)
                     return rc.BAD_REQUEST
+                
+                                
+                content = project.contents.get(iri_id=a['media'])
+                unprotect_instance(content)
+                add_annotation_to_stat(content, project, a['begin'], a['end'])
+                protect_instance(content)
+                    
                 a['id'] = new_id
+            
             # We save if there were added annotation
             if len(new_annotations)>0 :
                 adder.save()
             
+            protect_instance(project)
+            
             return request.data
             
         else:
@@ -187,6 +200,23 @@
             
             project.ldt = ldt_str
             
+            unprotect_instance(project)
             project.save()
+            protect_instance(project)
         
             return rc.ALL_OK
+        
+        
+class ContentHandler(BaseHandler):
+    allowed_methods = ('GET', )
+    model = Content
+    exclude = (
+               ("media_obj"),
+               )   
+
+    def read(self, request, iri_id):
+        """
+        returns a single content
+        """
+        return Content.objects.get(iri_id=iri_id)
+    
--- a/src/ldt/ldt/api/ldt/urls.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/api/ldt/urls.py	Tue Jan 10 16:09:28 2012 +0100
@@ -1,9 +1,12 @@
 from django.conf.urls.defaults import patterns, url
 from piston.resource import Resource
-from ldt.api.ldt.handlers import ProjectHandler
+from ldt.api.ldt.handlers import ProjectHandler, ContentHandler
 
 project_handler = Resource(ProjectHandler, None)
+content_handler = Resource(ContentHandler, None)
 
 urlpatterns = patterns('',
     url(r'projects/(?P<project_id>[^/.]+)\.?(?P<emitter_format>.*)$', project_handler, name='project_api'),
+    url(r'contents/(?P<iri_id>[^/.]+)\.?(?P<emitter_format>.*)$', content_handler, name='content_api'),
 )
+
--- a/src/ldt/ldt/ldt_utils/admin.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/admin.py	Tue Jan 10 16:09:28 2012 +0100
@@ -4,8 +4,9 @@
 from django.template import RequestContext
 from ldt.ldt_utils.contentindexer import ContentIndexer, ProjectIndexer
 from ldt.ldt_utils.fileimport import FileImport, FileImportError
-from ldt.ldt_utils.forms import LdtImportForm, ReindexForm
+from ldt.ldt_utils.forms import LdtImportForm, ReindexForm, StatAnnotationForm
 from ldt.ldt_utils.models import Content, Project, Media, Author
+#from ldt.ldt_utils.stat import compute_stats_for 
 import ldt.indexation
 from guardian.admin import GuardedModelAdmin
 
@@ -79,13 +80,38 @@
     
         return render_to_response('admin/ldt_utils/content/reindex_form.html', {'form': form, 'message':message, 'current_app': self.admin_site.name, 'current_action' : 'reindex' }, context_instance=RequestContext(request))
 
+    def stats_annotations(self, request):
+        
+        message = None
+        if request.method == "POST":
+            form = StatAnnotationForm(request.POST)
+            
+            if form.is_valid():
+                
+                if form.cleaned_data['choose_all']:
+                    projects = Content.objects.all()
+                else:
+                    projects = form.cleaned_data['projects']
+                
+#                for content in contents:
+#                    compute_stats_for(content)
+                message = "Stats computed for :" + repr(projects)
+        else:
+            form = StatAnnotationForm()
+            
+        return render_to_response('admin/ldt_utils/content/stats_form.html', {'form': form, 'message':message, 'current_app': self.admin_site.name, 'current_action' : 'stats' }, context_instance=RequestContext(request))
+            
+
     def get_urls(self):
         urls = super(ContentAdmin, self).get_urls()
         content_urls = patterns('',
             url(r'^reindex/$', self.admin_site.admin_view(self.reindex), name="ldt_content_reindex"),
     # (r'^admin/ldt/content/import/upload/$', 'ldt.ldt_utils.views.uploadFile'),                                
-            url(r'^import/$', self.admin_site.admin_view(self.import_file), name="ldt_content_import_file")
+            url(r'^import/$', self.admin_site.admin_view(self.import_file), name="ldt_content_import_file"),
+            url(r'^stats/$', self.admin_site.admin_view(self.stats_annotations), name="ldt_project_compute_stats")
+
         )
+        
         return content_urls + urls
 
 
--- a/src/ldt/ldt/ldt_utils/forms.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/forms.py	Tue Jan 10 16:09:28 2012 +0100
@@ -23,6 +23,10 @@
 class ReindexForm(forms.Form):
     contents = forms.ModelMultipleChoiceField(Content.objects.all())
     index_projects = forms.BooleanField(required=False, initial=False)
+    
+class StatAnnotationForm(forms.Form):
+    projects = forms.ModelMultipleChoiceField(Project.objects.all())
+    choose_all = forms.BooleanField(required=False, initial=False)
 
 class SearchForm(forms.Form):
     search = forms.CharField(label=_("Search"))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/migrations/0009_auto__chg_field_content_image__chg_field_project_image.py	Tue Jan 10 16:09:28 2012 +0100
@@ -0,0 +1,144 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Changing field 'Content.image'
+        db.alter_column('ldt_utils_content', 'image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=200))
+
+        # Changing field 'Project.image'
+        db.alter_column('ldt_utils_project', 'image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=200))
+
+
+    def backwards(self, orm):
+        
+        # Changing field 'Content.image'
+        db.alter_column('ldt_utils_content', 'image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=100))
+
+        # Changing field 'Project.image'
+        db.alter_column('ldt_utils_project', 'image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=100))
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'ldt_utils.author': {
+            'Meta': {'object_name': 'Author'},
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+            'firstname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '512', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lastname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.content': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Content'},
+            'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Author']", 'symmetrical': 'False', 'blank': 'True'}),
+            'content_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/contents/content_default_icon.png'", 'max_length': '200'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'default': "u'2794e921-3aa9-11e1-844e-001485352c9a'", 'unique': 'True', 'max_length': '1024'}),
+            'iriurl': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'media_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Media']", 'null': 'True', 'blank': 'True'}),
+            'nb_annotation': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'stat_annotation': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.media': {
+            'Meta': {'object_name': 'Media'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'external_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_permalink': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_publication_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_src_url': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'media_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'mimetype_field': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'src': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'videopath': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.project': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Project'},
+            'changed_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'contents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Content']", 'symmetrical': 'False'}),
+            'created_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/projects/project_default_icon.png'", 'max_length': '200'}),
+            'ldt': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'ldt_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}),
+            'modification_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'state': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
+        },
+        'ldt_utils.segment': {
+            'Meta': {'unique_together': "(('project_id', 'iri_id', 'ensemble_id', 'cutting_id', 'element_id'),)", 'object_name': 'Segment'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Content']"}),
+            'cutting_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'date': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'element_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'ensemble_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'project_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'project_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True'}),
+            'start_ts': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['ldt_utils']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/migrations/0010_auto__add_annotationstat.py	Tue Jan 10 16:09:28 2012 +0100
@@ -0,0 +1,166 @@
+#@PydevCodeAnalysisIgnore
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+   
+        # Adding field 'Content.stat_annotation'
+        db.add_column('ldt_utils_content', 'stat_annotation', self.gf('django.db.models.fields.CommaSeparatedIntegerField')(max_length=1024, null=True, blank=True), keep_default=False)
+
+        # Adding field 'Content.nb_annotation'
+        db.add_column('ldt_utils_content', 'nb_annotation', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False)
+
+        db.rename_table('ldt_utils_project_contents', 'ldt_utils_annotationstat')
+                
+        db.add_column('ldt_utils_annotationstat', 'stat', self.gf('django.db.models.fields.CommaSeparatedIntegerField')(max_length=1024, null=True, blank=True), keep_default=False)
+        db.add_column('ldt_utils_annotationstat', 'nb_annotation', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
+       
+
+    def backwards(self, orm):
+        
+        db.rename_table('ldt_utils_annotationstat', 'ldt_utils_project_contents')
+
+        db.delete_column('ldt_utils_project_contents', 'stat')
+        db.delete_column('ldt_utils_project_contents', 'nb_annotation')
+
+        # Deleting field 'Content.nb_annotation'
+        db.delete_column('ldt_utils_content', 'nb_annotation')
+                
+        # Deleting field 'Content.stat_annotation'
+        db.delete_column('ldt_utils_content', 'stat_annotation')
+
+
+
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'ldt_utils.annotationstat': {
+            'Meta': {'object_name': 'AnnotationStat'},
+            'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Content']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nb_annotation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']"}),
+            'stat': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.author': {
+            'Meta': {'object_name': 'Author'},
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+            'firstname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '512', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lastname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.content': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Content'},
+            'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Author']", 'symmetrical': 'False', 'blank': 'True'}),
+            'content_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/contents/content_default_icon.png'", 'max_length': '200'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'default': "u'f17c154f-3b7c-11e1-a7a8-001485352c9a'", 'unique': 'True', 'max_length': '1024'}),
+            'iriurl': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'media_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Media']", 'null': 'True', 'blank': 'True'}),
+            'nb_annotation': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'stat_annotation': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.media': {
+            'Meta': {'object_name': 'Media'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'external_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_permalink': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_publication_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_src_url': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'media_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'mimetype_field': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'src': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'videopath': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.project': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Project'},
+            'changed_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'contents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Content']", 'through': "orm['ldt_utils.AnnotationStat']", 'symmetrical': 'False'}),
+            'created_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/projects/project_default_icon.png'", 'max_length': '200'}),
+            'ldt': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'ldt_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}),
+            'modification_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'state': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
+        },
+        'ldt_utils.segment': {
+            'Meta': {'unique_together': "(('project_id', 'iri_id', 'ensemble_id', 'cutting_id', 'element_id'),)", 'object_name': 'Segment'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Content']"}),
+            'cutting_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'date': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'element_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'ensemble_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'project_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'project_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True'}),
+            'start_ts': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['ldt_utils']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/migrations/0011_gen_stat_annotation.py	Tue Jan 10 16:09:28 2012 +0100
@@ -0,0 +1,148 @@
+#@PydevCodeAnalysisIgnore
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+from ldt.ldt_utils.stat import update_stat_project
+
+
+class Migration(DataMigration):
+
+    def forwards(self, orm):
+        "Write your forwards methods here."
+        
+        for proj in orm.Project.objects.all():
+            update_stat_project(proj)
+
+
+    def backwards(self, orm):
+        "Write your backwards methods here."
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'ldt_utils.annotationstat': {
+            'Meta': {'object_name': 'AnnotationStat'},
+            'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Content']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nb_annotation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']"}),
+            'stat': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.author': {
+            'Meta': {'object_name': 'Author'},
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+            'firstname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '512', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lastname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.content': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Content'},
+            'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Author']", 'symmetrical': 'False', 'blank': 'True'}),
+            'content_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/contents/content_default_icon.png'", 'max_length': '200'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'default': "u'0b304030-3b8b-11e1-accd-001485352c9a'", 'unique': 'True', 'max_length': '1024'}),
+            'iriurl': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'media_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Media']", 'null': 'True', 'blank': 'True'}),
+            'nb_annotation': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'stat_annotation': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.media': {
+            'Meta': {'object_name': 'Media'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'external_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_permalink': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_publication_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_src_url': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'media_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'mimetype_field': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'src': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'videopath': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.project': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Project'},
+            'changed_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'contents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Content']", 'through': "orm['ldt_utils.AnnotationStat']", 'symmetrical': 'False'}),
+            'created_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/projects/project_default_icon.png'", 'max_length': '200'}),
+            'ldt': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'ldt_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}),
+            'modification_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'state': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
+        },
+        'ldt_utils.segment': {
+            'Meta': {'unique_together': "(('project_id', 'iri_id', 'ensemble_id', 'cutting_id', 'element_id'),)", 'object_name': 'Segment'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Content']"}),
+            'cutting_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'date': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'element_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'ensemble_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'project_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'project_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True'}),
+            'start_ts': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['ldt_utils']
--- a/src/ldt/ldt/ldt_utils/models.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py	Tue Jan 10 16:09:28 2012 +0100
@@ -127,9 +127,10 @@
     content_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('content.content_creation_date'))
     tags = tagging.fields.TagField(max_length=2048, null=True, blank=True)
     media_obj = models.ForeignKey('Media', blank=True, null=True)
-    
-    image = ImageField(upload_to=settings.MEDIA_ROOT+"thumbnails/contents/", default=settings.DEFAULT_CONTENT_ICON)
-    
+    image = ImageField(upload_to=settings.MEDIA_ROOT+"thumbnails/contents/", default=settings.DEFAULT_CONTENT_ICON, max_length=200)
+    stat_annotation = models.CommaSeparatedIntegerField(max_length=1024, null=True, blank=True, verbose_name=_("content.stat_annotation")) 
+    nb_annotation = models.IntegerField(null=True, blank=True, verbose_name=_('content.nb_annotation'))
+        
     class Meta:
         ordering = ["title"]
         permissions = (
@@ -155,8 +156,8 @@
             else:
                 self.duration = 0
             self.save()
-        return self.duration
-
+        return self.duration    
+    
     def duration_str(self):
         if self.duration is None:
             return "?"
@@ -171,7 +172,6 @@
         else:
             min_str = str(min)
         return str(hours) + "h" + min_str
-            
     
     def mimetype(): #@NoSelf
         def fget(self):
@@ -344,12 +344,12 @@
                     assign('view_media', everyone, self.media_obj)               
                 else:
                     remove_perm('view_content', everyone, self)
-                    remove_perm('vew_media', everyone, self.media_obj)
+                    remove_perm('view_media', everyone, self.media_obj)
         
         return locals()
     
     is_public = property(**is_public())
-                
+
 
     
 class Project(Document, SafeModel):  
@@ -363,15 +363,14 @@
     ldt_id = models.CharField(max_length=1024, unique=True)
     ldt = models.TextField(null=True)
     title = models.CharField(max_length=1024)
-    contents = models.ManyToManyField(Content)
+    contents = models.ManyToManyField(Content, through='AnnotationStat')
     creation_date = models.DateTimeField(auto_now_add=True)
     modification_date = models.DateTimeField(auto_now=True)
     created_by = models.CharField(_("created by"), max_length=70)
     changed_by = models.CharField(_("changed by"), max_length=70)
     state = models.IntegerField(choices=STATE_CHOICES, default=1)
-    description = models.TextField(null=True, blank=True)
-    
-    image = ImageField(upload_to=settings.MEDIA_ROOT+"thumbnails/projects/", default=settings.DEFAULT_PROJECT_ICON)
+    description = models.TextField(null=True, blank=True)    
+    image = ImageField(upload_to=settings.MEDIA_ROOT+"thumbnails/projects/", default=settings.DEFAULT_PROJECT_ICON, max_length=200)
     
     class Meta:
         ordering = ["title"]
@@ -433,7 +432,7 @@
         assign('change_project', user, project)           
                         
         for content in contents:
-            project.contents.add(content)
+            project.add_contents([content])
         
         if set_icon:
             project.set_icon()
@@ -449,7 +448,7 @@
         if group:
             assign('view_project', group, project)
         for content in self.contents.all():
-            project.contents.add(content)
+            project.add_contents([content])
         return project
     
     def publish(self):
@@ -483,8 +482,18 @@
         if (user and user.is_staff) or self.state == 2: 
             return True
         else:
-            return False        
+            return False
         
+    def add_contents(self, contents):
+        for content in contents:
+            contribution = AnnotationStat.objects.create(project=self, content=content)
+            contribution.save()  
+        
+class AnnotationStat(SafeModel):
+    project = models.ForeignKey(Project)
+    content = models.ForeignKey(Content)
+    stat = models.CommaSeparatedIntegerField(max_length=1024, null=True, blank=True, verbose_name=_("content.stat_annotation"))
+    nb_annotation = models.IntegerField(default=0, verbose_name=_("content.nb_annotation"))
 
 class Segment(SafeModel):
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/stat.py	Tue Jan 10 16:09:28 2012 +0100
@@ -0,0 +1,141 @@
+from django.conf import settings
+from ldt.ldt_utils.models import AnnotationStat, Project
+from django.db.models.signals import pre_delete
+import lxml.etree
+
+
+def update_stat_project(project, contents=None, doc=None, update_contents=[]):
+    if not contents:
+        contents = project.contents.all()
+     
+    if not doc:
+        doc = lxml.etree.fromstring(project.ldt)
+
+    number_division = settings.DIVISIONS_FOR_STAT_ANNOTATION
+    contributions = AnnotationStat.objects.filter(project=project)    
+        
+    for content_node in doc.xpath('/iri/annotations/content'):
+        content_name = content_node.get('id')
+        content = contents.get(iri_id=content_name)
+        contribution_to_content = contributions.get(content=content)
+        
+        size_division = content.duration / number_division
+        limits = [x * size_division for x in range(number_division+1)]
+        buckets = [0] * number_division
+        nb_annotation = 0
+        
+        for ann in content_node.xpath('ensemble/decoupage/elements/element'):
+ 
+            begin = int(ann.get('begin'))
+            end = int(ann.get('dur')) + begin
+                    
+            buckets = find_buckets(buckets, limits, begin, end)
+            nb_annotation += 1        
+       
+        buckets = get_string_from_buckets(buckets)
+         
+        if contribution_to_content.stat != buckets or contribution_to_content.nb_annotation != nb_annotation:
+            contribution_to_content.stat = buckets
+            contribution_to_content.nb_annotation = nb_annotation
+            contribution_to_content.save()
+            update_stat_content(content)
+    
+    for content in update_contents:
+        update_stat_content(content)
+        
+        
+def get_string_from_buckets(buckets):
+    s = "%s" % buckets
+    s = s[1:-1].replace(' ', '')
+    return s
+
+def get_buckets_from_string(string):
+    return [int(x) for x in string.split(',')]
+
+
+def find_buckets(buckets, limits, begin, end):
+    
+    if len(buckets)+1 != len(limits):
+        raise ValueError("There should be as many buckets as those defined by limits.")
+    
+    has_started = False  
+        
+    for i in range(len(limits)-1):
+        if not has_started:
+            if limits[i] <= begin and begin <= limits[i+1]:
+                buckets[i] += 1
+                has_started = True
+                #print "Starts after timecode %s" % limits[i]
+        elif limits[i] > end:
+            #print "Ends before timecode %s" % limits[i]
+            break
+        else:
+            buckets[i] += 1
+            
+    return buckets
+        
+        
+def delete_stat_project(sender, instance, **kwargs):
+    
+    contents = instance.contents.all()
+    contributions = AnnotationStat.objects.filter(project=instance)
+    
+    for c in contributions:
+        content = contents.get(id=c.content.id)        
+        content.nb_annotation -= c.nb_annotation
+        
+        if c.stat:
+            content_stat = get_buckets_from_string(content.stat_annotation)
+            proj_stat = get_buckets_from_string(c.stat)
+            content.stat_annotation = get_string_from_buckets([pair[0] - pair[1] for pair in zip(content_stat, proj_stat)])
+        
+        content.save()        
+
+pre_delete.connect(delete_stat_project, sender=Project)    
+        
+            
+def update_stat_content(content):
+    all_contributions = AnnotationStat.objects.filter(content=content)
+    content_stat = [0] * settings.DIVISIONS_FOR_STAT_ANNOTATION
+    nb_annotation = 0
+    
+    for project in all_contributions:
+        if project.stat and project.stat != '':
+            project_stat = get_buckets_from_string(project.stat)
+            content_stat = [sum(pair) for pair in zip(content_stat, project_stat)]
+        nb_annotation += project.nb_annotation  
+    
+    content.nb_annotation = nb_annotation
+    content.stat_annotation = get_string_from_buckets(content_stat)
+    content.save()    
+
+
+def add_annotation_to_stat(content, project, begin, end):
+    contribution_project = AnnotationStat.objects.get(project=project, content=content)
+    
+    if not contribution_project.nb_annotation:
+        contribution_project.nb_annotation = 1
+    else:
+        contribution_project.nb_annotation += 1
+    content.nb_annotation += 1
+    
+    if contribution_project.stat:
+        
+        number_division = settings.DIVISIONS_FOR_STAT_ANNOTATION
+        size_division = content.duration / number_division
+        
+        limits = [x * size_division for x in range(number_division+1)]
+        buckets = [0] * number_division        
+        buckets = find_buckets(buckets, limits, begin, end)
+        
+        content_stat = get_buckets_from_string(content.stat_annotation)
+        content.stat_annotation = get_string_from_buckets([pair[0] + pair[1] for pair in zip(content_stat, buckets)])
+        contribution_project.stat = get_string_from_buckets(buckets)  
+
+   
+    content.save()
+    contribution_project.save()
+
+    
+
+    
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/templates/admin/ldt_utils/app_index.html	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/admin/ldt_utils/app_index.html	Tue Jan 10 16:09:28 2012 +0100
@@ -25,6 +25,11 @@
 				</th>
 				<td>&nbsp;</td>
 			</tr>
+			<tr>
+				<th><a href="{{WEB_URL}}{% url admin:ldt_project_compute_stats %}">Compute stats</a>
+				</th>
+				<td>&nbsp;</td>
+			</tr>
 	</table>
 	</div>
 </div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/templates/admin/ldt_utils/content/stats_form.html	Tue Jan 10 16:09:28 2012 +0100
@@ -0,0 +1,23 @@
+{% extends "admin/ldt_utils/app_action.html" %}
+{% load i18n %}
+{# reindex contents #}
+{% block content %}
+{% if message %}
+<div>
+<p>{{ message }}</p>
+</div>
+{% endif %} {% if form. %}
+<div></div>
+{% endif %}
+<div>
+<form method="post"
+	action="{{WEB_URL}}{% url admin:ldt_project_compute_stats %}">{% csrf_token %}
+<table>
+	{{ form.as_table }}
+</table>
+<input type="submit" /></form>
+</div>
+
+<a href="{{WEB_URL}}{% url admin:app_list 'ldt_utils' %}">Back to administration page</a>
+
+{% endblock %}
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html	Tue Jan 10 16:09:28 2012 +0100
@@ -30,10 +30,8 @@
 	<script type="text/javascript">
 	window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";
 	
-	function public_checkbox (checkbox) {		
-		if (checkbox.is(":checked")) {
-			$("#removeall").trigger("click");
-			$("#sharelist option").css('color', '');
+	function public_checkbox (checkbox) {
+		if (checkbox.is(":checked") && ($("input[name=share]").val() == 'True')) {
 			$("#shareproject").trigger("click");
 		} 
 	}
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/permissions.html	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/permissions.html	Tue Jan 10 16:09:28 2012 +0100
@@ -44,6 +44,7 @@
 		$("#shareproject").click(function () {
 			if (state == 1) {
 				$("#sharecontainer").show();
+				$("#public input").attr('checked', false);
 				$("input[id=id_share]").val('True');
 				var new_img = '<img class="shareicon" src=' + do_not_share_img + '>';
 				$(this).html(new_img + do_not_share);
--- a/src/ldt/ldt/ldt_utils/utils.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/utils.py	Tue Jan 10 16:09:28 2012 +0100
@@ -169,7 +169,7 @@
         self.parser = lxml.etree.XMLParser(remove_blank_text=True)
         self.ldtdoc = lxml.etree.parse(StringIO(project.ldt.encode("utf-8")), self.parser)
         self.to_add = True
-        self.force_save = force_save
+        
     #   add( a['media'], a['type'],  a['type_title, a[data], '', a['tags'], begin, dur, author, date)
     def add(self, media, cutting_id, cutting_title, title, text, tags_list, begin, dur, author, date, view_id=None, color="16776960"):
         """
@@ -270,11 +270,7 @@
         if self.to_add:
             self.project.ldt = lxml.etree.tostring(self.ldtdoc, pretty_print=True)
             #assert False, " TIBO SAVE " + self.project.ldt
-            if self.force_save:
-                self.project.save_base()
-            else:
-                self.project.save()
-        return True
+            self.project.save()
     
     def __del__(self):
        self.save()       
--- a/src/ldt/ldt/ldt_utils/views/lignesdetemps.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/lignesdetemps.py	Tue Jan 10 16:09:28 2012 +0100
@@ -4,9 +4,10 @@
 from django.http import HttpResponse, HttpResponseRedirect
 from django.shortcuts import render_to_response, get_object_or_404
 from django.template import RequestContext
-from ldt.ldt_utils.models import Content, Project
+from ldt.ldt_utils.models import Content, Project, AnnotationStat
 from ldt.ldt_utils.utils import LdtUtils, LdtSearch, clean_description
 from ldt.security.utils import set_forbidden_stream
+from ldt.ldt_utils.stat import update_stat_project
 import base64
 import django.core.urlresolvers
 import lxml.etree
@@ -265,7 +266,7 @@
     if request.method == "POST":
         ldt = request.POST['ldt']
         id = request.POST['id']
-        ldtproject = Project.safe_objects.get(ldt_id=id) #@UndefinedVariable
+        ldtproject = Project.safe_objects.select_related().get(ldt_id=id) #@UndefinedVariable
 
         #save xml ldt
         ldtproject.ldt = ldt
@@ -284,18 +285,29 @@
             new_contents.append(id)
     
         check_icon_project = False
-        #set new content list
+        contents_remove = []
+        
+        #find contents to remove
         for c in ldtproject.contents.all():
             if not c.iri_id in new_contents:
-                ldtproject.contents.remove(c)
+                contents_remove.append(c)
                 if ldtproject.image == c.image:
                     check_icon_project = True
+        
+        #remove contents
+        AnnotationStat.objects.filter(content__in=contents_remove, project=ldtproject).delete()
                 
-        contents_id = [c.id for c in ldtproject.contents.all()]
+        #add new contents
+        contents_id = [c.iri_id for c in ldtproject.contents.all()]
+        
         for c in new_contents:
             if c not in contents_id:
                 content = Content.objects.get(iri_id=c)
-                ldtproject.contents.add(content)
+                rel = AnnotationStat(project=ldtproject, content=content, stat='')
+                rel.save()
+         
+        #update stats for all contents in this project and contents removed     
+        update_stat_project(ldtproject, ldtproject.contents.all(), update_contents=contents_remove)
         
         #remove html tags added by flash
         description = ldtproject.get_description(doc)
--- a/src/ldt/ldt/ldt_utils/views/workspace.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/workspace.py	Tue Jan 10 16:09:28 2012 +0100
@@ -60,7 +60,7 @@
     group_list = sorted(group_list.all(), key=lambda group: group.name.lower())    
     group_list = add_change_attr(request.user, group_list)
 
-    can_add_group = True if request.user.user_permissions.filter(codename='add_group') else False
+    can_add_group = request.user.has_perm('auth.add_group')
     is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
     # render list
     return render_to_response("ldt/ldt_utils/groups.html",
--- a/src/ldt/ldt/ldt_utils/views_old.py	Mon Jan 09 15:12:15 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1383 +0,0 @@
-from django.conf import settings
-from django.contrib.auth.decorators import login_required
-from django.contrib.auth.models import User, Group
-from django.core.cache import cache
-from django.core.urlresolvers import reverse
-from django.core.paginator import Paginator, InvalidPage, EmptyPage
-from django.db.models import Q
-from django.forms.models import model_to_dict
-from django.forms.util import ErrorList
-from django.http import (HttpResponse, HttpResponseRedirect,
-    HttpResponseForbidden, HttpResponseServerError)
-from ldt.indexation import get_results_with_context, highlight_documents
-from django.shortcuts import (render_to_response, get_object_or_404,
-    get_list_or_404)
-from django.template import RequestContext
-from django.template.loader import render_to_string
-from django.utils import simplejson
-from django.utils.html import escape
-from django.utils.translation import ugettext as _, ungettext
-from forms import (LdtAddForm, SearchForm, AddProjectForm, CopyProjectForm,
-    ContentForm, MediaForm, GroupAddForm)
-from guardian.shortcuts import remove_perm, get_objects_for_group, get_objects_for_user
-from ldt.ldt_utils.models import Content
-from ldt.ldt_utils.utils import boolean_convert, LdtUtils, LdtSearch
-from ldt.security.utils import (assign_perm_to_obj, set_forbidden_stream, 
-    add_change_attr, get_userlist, get_userlist_model, get_userlist_group)
-from ldt.security.cache import get_cached_checker, cached_assign
-from lxml.html import fragment_fromstring
-from models import Media, Project
-from projectserializer import ProjectSerializer
-from urllib2 import urlparse
-from operator import itemgetter
-from itertools import groupby
-import base64
-import django.core.urlresolvers
-import ldt.auth as ldt_auth
-import ldt.utils.path as ldt_utils_path
-import logging
-import lxml.etree
-import mimetypes
-import os
-import urllib2
-import subprocess
-import re
-import datetime
-
-
-@login_required
-def workspace(request):
-    
-    # list of contents
-    content_list = add_change_attr(request.user, Content.safe_objects.all()) #@UndefinedVariable
-    
-    # get list of projects owned by the current user
-    project_list = add_change_attr(request.user, Project.safe_objects.filter(owner=request.user)) #@UndefinedVariable
-
-    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-    
-    # render list
-    return render_to_response("ldt/ldt_utils/workspace.html",
-                              {'contents': content_list, 'projects': project_list,
-                               'is_gecko': is_gecko},
-                              context_instance=RequestContext(request))
-
-@login_required
-def groups(request): 
-
-    # get list of all published projects
-    group_list = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME)
-    
-    group_list = sorted(group_list.all(), key=lambda group: group.name.lower())    
-    group_list = add_change_attr(request.user, group_list)
-
-    can_add_group = True if request.user.user_permissions.filter(codename='add_group') else False
-    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-    # render list
-    return render_to_response("ldt/ldt_utils/groups.html",
-                              {'groups': group_list,
-                               'is_gecko': is_gecko,
-                               'can_add_group': can_add_group},
-                              context_instance=RequestContext(request))
-
-
-@login_required
-def published_project(request): 
-
-    # get list of all published projects
-    project_list = Project.safe_objects.filter(state=2) #@UndefinedVariable
-    # Search form
-    form = SearchForm()
-
-    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-    
-    # render list
-    return render_to_response("ldt/ldt_utils/published_projects.html",
-                              {'projects': project_list, 'form': form,
-                               'is_gecko': is_gecko},
-                              context_instance=RequestContext(request))
-
-
-def popup_embed(request):
-
-    json_url = request.GET.get("json_url")
-    player_id = request.GET.get("player_id")
-    ldt_id = request.GET.get("ldt_id")
-
-    project = Project.safe_objects.get(ldt_id=ldt_id); #@UndefinedVariable
-
-    stream_mode = project.stream_mode
-    if stream_mode != "video":
-        stream_mode = 'radio'
-
-    player_width = 650
-    player_height = 480
-    
-    if stream_mode == 'radio':
-        player_height = 1
-        
-    if not ldt_auth.check_access(request.user, project):
-        return HttpResponseForbidden(_("You can not access this project"))
-
-    ps = ProjectSerializer(project, from_contents=False, from_display=True)
-    annotations = ps.get_annotations(first_cutting=True)
-    
-    rend_dict = {'json_url':json_url, 'player_id':player_id, 'annotations':annotations, 'ldt_id': ldt_id, 'stream_mode': stream_mode, 'player_width': player_width, 'player_height': player_height}
-
-    embed_rendered = dict((typestr,
-                           (lambda s:escape(lxml.etree.tostring(fragment_fromstring(render_to_string("ldt/ldt_utils/partial/embed_%s.html" % (s), rend_dict, context_instance=RequestContext(request))), pretty_print=True)))(typestr))
-                           for typestr in ('player', 'seo_body', 'seo_meta', 'links'))
-
-    rend_dict['embed_rendered'] = embed_rendered
-
-    return render_to_response("ldt/ldt_utils/embed_popup.html",
-                              rend_dict,
-                              context_instance=RequestContext(request))
-
-
-@login_required
-def projects_filter(request, filter, is_owner=False, status=0, id_group=0):
-    is_owner = boolean_convert(is_owner)
-    status = int(status)
-    id_group = int(id_group)
-    query = Q()
-
-    if is_owner:
-        owner = None
-        try:
-            owner = request.user
-        except:
-            return HttpResponseServerError("<h1>User not found</h1>")
-        query &= Q(owner=owner)
-
-    if status > 0:
-        query &= Q(state=status)
-
-    if filter:
-        if len(filter) > 0 and filter[0] == '_':
-            filter = filter[1:]
-        query &= Q(title__icontains=filter)
-    
-    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-    show_username = True
-    
-    if id_group > 0:    # Search inside a group
-        grp = Group.objects.get(id=id_group)
-        project_list = get_objects_for_group(grp, 'ldt_utils.view_project').filter(query)
-    elif id_group == -1:# Search inside projects shared with a specific user
-        project_list = get_objects_for_user(request.user, 'ldt_utils.view_project', use_groups=False).exclude(owner=request.user)
-    else:
-        project_list = Project.safe_objects.filter(query)
-        show_username = False
-
-    project_list = add_change_attr(request.user, project_list)
-    
-    if status == 2:
-        url_templ = "ldt/ldt_utils/partial/publishedprojectslist.html"
-    else:
-        url_templ = "ldt/ldt_utils/partial/projectslist.html"
-        
-    return render_to_response(url_templ,
-                              {'projects': project_list, 'show_username':show_username,
-                               'is_gecko': is_gecko, 'group_id':id_group},
-                              context_instance=RequestContext(request))
-
-def share_filter(request, filter, use_groups=False):
-    use_groups = boolean_convert(use_groups)
-    if not filter or len(filter) == 0:
-        raise AttributeError("filter should be a string")
-    
-    filter = filter[1:]    
-    resp = get_userlist(request.user, filter=filter)
-            
-    if use_groups:
-        groups = Group.objects.filter(name__icontains=filter).exclude(name=settings.PUBLIC_GROUP_NAME)[0:20]
-
-        for g in groups:
-            resp.append({'name': g.name, 'id': g.id, 'type': 'group'})
-    
-    resp = sorted(resp, key=lambda elem: elem['name'].lower())
-    
-    return render_to_response("ldt/ldt_utils/partial/sharewith.html", {'elem_list' : resp}, context_instance=RequestContext(request))
-    
-@login_required
-def contents_filter(request, filter): 
-    if filter and len(filter) > 0 and filter[0] == '_':
-        filter = filter[1:]
-
-    if filter:
-        content_list = Content.safe_objects.filter(title__icontains=filter) #@UndefinedVariable
-    else:
-        content_list = Content.safe_objects.all() #@UndefinedVariable
-        
-    content_list = add_change_attr(request.user, content_list)
-    
-    return render_to_response("ldt/ldt_utils/partial/contentslist.html",
-                              {'contents': content_list},
-                              context_instance=RequestContext(request))
-
-@login_required
-def groups_filter(request, filter):
-    if filter and len(filter) > 0 and filter[0] == '_':
-        filter = filter[1:]
-
-    if filter:
-        group_list = request.user.groups.filter(name__icontains=filter)
-        search_active = True 
-    else:
-        group_list = request.user.groups.all()
-        search_active = False
-        
-    group_list = group_list.exclude(name=settings.PUBLIC_GROUP_NAME)
-    group_list = sorted(group_list.all(), key=lambda group: group.name.lower())
-    group_list = add_change_attr(request.user, group_list)
-    
-    
-    return render_to_response("ldt/ldt_utils/partial/groupslist.html",
-                              {'groups': group_list, 'search_active': search_active},
-                              context_instance=RequestContext(request))
-    
-
-def search_form(request): 
-    form = SearchForm()
-    return render_to_response('ldt/ldt_utils/search_form.html', {'form': form} , context_instance=RequestContext(request))
-
-
-@login_required
-def search_index(request):
-        
-    sform = SearchForm(request.POST)
-    if sform.is_valid():
-        search = sform.cleaned_data["search"]
-        queryStr = base64.urlsafe_b64encode(search.encode('utf8'))
-        field = request.POST["field"]
-        language_code = request.LANGUAGE_CODE[:2]
-        
-        if request.POST.has_key("ldt_pres"):
-            url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.search_init", args=[field, queryStr])
-            return render_to_response('ldt/ldt_utils/init_ldt_full.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': url}, context_instance=RequestContext(request))
-        else:
-            results = get_results_with_context(field, search)     
-            complete_results = []
-            proj_list = Project.safe_objects.all()
-            results.sort(key=lambda k: k['iri_id'])
-            for iri_id, item in groupby(results, itemgetter('iri_id')):                
-                try: 
-                    content = Content.objects.get(iri_id=iri_id)
-                except Content.DoesNotExist:
-                    continue
-                segments = list(item)
-                to_delete = []
-                for s in segments:
-                    if not s['project_id']:
-                        s['project_id'] = '_'
-                    else:
-                        project = proj_list.filter(ldt_id=s['project_id'])
-                        if len(project) == 0:
-                            to_delete.append(s)
-                            
-                for e in to_delete:
-                    segments.remove(e)
-                    
-                if not segments:
-                    continue 
-                
-                score = sum([seg['score'] for seg in segments])
-                desc = content.description if content.description else ''
-                complete_results.append({'list' : segments, 'score' : score, 'content_title' : content.title, 'content_id' : content.iri_id, 'content_description' : desc })
-            
-            complete_results.sort(key=lambda k: k['score'])
-                                
-            cache.set('complete_results_%s' % request.user.username, complete_results)
-            cache.set('search_%s' % request.user.username, search)
-            cache.set('field_%s' % request.user.username, field)
-
-            paginator = Paginator (complete_results, settings.LDT_RESULTS_PER_PAGE)
-            page = 1
-            
-            try:
-                results = paginator.page(page)
-            except (EmptyPage, InvalidPage):
-                results = paginator.page(paginator.num_pages)
-                
-            results.object_list = highlight_documents(results.object_list, search, field)
-            
-            return render_to_response('ldt/ldt_utils/search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request))   
-        
-    else:
-        return HttpResponseRedirect(reverse('ldt.ldt_utils.views.published_project'))
-        
-
-def search_listing(request):
-    if not cache.get('complete_results_%s' % request.user.username):
-        return HttpResponseRedirect(reverse('ldt.ldt_utils.views.published_project'))
-     
-    complete_results = cache.get('complete_results_%s' % request.user.username)
-    search = cache.get('search_%s' % request.user.username)
-    field = cache.get('field_%s' % request.user.username)
-    paginator = Paginator(complete_results, settings.LDT_RESULTS_PER_PAGE)
-    language_code = request.LANGUAGE_CODE[:2]
-
-    try:
-        page = int(request.GET.get('page', '1'))
-    except ValueError:
-        page = 1
-
-    try:
-        results = paginator.page(page)
-    except (EmptyPage, InvalidPage):
-        results = paginator.page(paginator.num_pages)
-    
-    results.object_list = highlight_documents(results.object_list, search, field)
-
-    return render_to_response('ldt/ldt_utils/search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request))   
-  
-def search_index_get(request, field, query):
-    
-    language_code = request.LANGUAGE_CODE[:2]
-    
-    url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.search_init", args=[field, query])
-    return render_to_response('ldt/ldt_utils/init_ldt.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': url}, context_instance=RequestContext(request))
-
-def search_init(request, field, query):
-    
-    ldtgen = LdtUtils()
-    
-    doc = ldtgen.generate_init([field, query], 'ldt.ldt_utils.views.search_ldt', 'ldt.ldt_utils.views.search_segments')
-    
-    resp = HttpResponse(mimetype="text/xml;charset=utf-8")
-    resp.write(lxml.etree.tostring(doc, pretty_print=True, encoding="utf-8")) 
-    return resp
-
-def search_ldt(request, field, query, edition=None): 
-    
-    contentList = []
-    resp = HttpResponse(mimetype="text/xml")
-    queryStr = ""
-
-    if query and len(query) > 0:        
-        queryStr = base64.urlsafe_b64decode(query.encode("ascii")).decode("utf8")
-        searcher = LdtSearch()
-        ids = {}
-        projIds = {}
-        
-        for result in searcher.query(field, queryStr):
-            ids[result["iri_id"]] = ""
-            projIds[result["project_id"]] = ""
-
-        id_list = ids.keys()
-        projId_list = projIds.keys()
-        
-        #if edition is not None:
-        #    ids_editions = map(lambda t:t[0], filter(lambda id: id[0] is not None, Speak.objects.filter(session__day__edition=edition).order_by("session__start_ts", "order").values_list("content__iri_id")))            
-        #    id_list = filter(lambda id: id in id_list, ids_editions)
-            
-        contentList = Content.objects.filter(iri_id__in=id_list)        #@UndefinedVariable
-        projectList = Project.safe_objects.filter(ldt_id__in=projId_list)    
-          
-    ldtgen = LdtUtils()
-    #            generate_ldt(contentList, title=u"", author=u"IRI Web", web_url=u"", startSegment=None, projects=None):
-    doc = ldtgen.generate_ldt(contentList, title=u"Recherche : " + queryStr, projects=projectList)
-    doc = set_forbidden_stream(doc, request.user)   
-    doc.write(resp, pretty_print=True)
-    
-    return resp
-
-
-def search_segments(request, field, query, edition=None):
-    
-    if query and len(query) > 0:
-        searcher = LdtSearch()
-        
-        queryStr = base64.urlsafe_b64decode(query.encode("ascii")).decode("utf8")
-        res = searcher.query(field, queryStr)            
-    else:
-        res = []
-        
-    iri_ids = None
-    
-    #if edition is not None:
-    #    iri_ids = map(lambda t:t[0], filter(lambda id: id[0] is not None, Speak.objects.filter(session__day__edition=edition).order_by("session__start_ts", "order").values_list("content__iri_id")))
-
-    iri = lxml.etree.Element('iri')
-    doc = lxml.etree.ElementTree(iri)
-
-    for resultMap in res:
-        if iri_ids is None or resultMap['iri_id'] in iri_ids:
-            seg = lxml.etree.SubElement(iri, 'seg')
-            seg.set('idctt', resultMap['iri_id'])
-            seg.set('idens', resultMap['ensemble_id'])
-            seg.set('iddec', resultMap['decoupage_id'])
-            seg.set('idseg', resultMap['element_id'])
-            seg.set('idvue', "")
-            seg.set('crit', "")
-    
-    #return doc  
-    
-    return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8") 
-
-
-@login_required         
-def list_ldt(request):
-    contents = Content.safe_objects.all() #@UndefinedVariable
-    try:
-        owner = request.user #@UndefinedVariable
-    except:
-        return HttpResponseRedirect(settings.LOGIN_URL)
-    ldtProjects = Project.safe_objects.filter(owner=owner) #@UndefinedVariable
-    context = {
-    'contents': contents,
-    'projects': ldtProjects.reverse(),
-    }
-    return render_to_response('ldt/ldt_utils/ldt_list.html', context, context_instance=RequestContext(request))
-
-@login_required         
-def list_content(request):
-    contents = Content.safe_objects.all() #@UndefinedVariable
-    context = {
-        'contents': contents,
-    }
-    return render_to_response('ldt/ldt_utils/content_list.html', context, context_instance=RequestContext(request))
-
-@login_required
-def create_ldt_view(request):
-    groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME)
-    redirect_to = ''
-    if request.method == "POST" :
-        form = LdtAddForm(request.POST)
-        form_status = "none"
-        contents = Content.safe_objects.all()
-           
-        if form.is_valid():              
-                     
-            user = request.user            
-            project = Project.create_project(title=form.cleaned_data['title'], user=user, 
-                                             contents=form.cleaned_data['contents'],
-                                             description=form.cleaned_data['description'])
-  
-            if form.cleaned_data["share"]:
-                assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], user)
-            form_status = "saved"
-            is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-            if is_gecko :
-                redirect_to = reverse('index_project_full', args=[project.ldt_id])
-            else:
-                return HttpResponseRedirect(reverse('index_project', args=[project.ldt_id]))   
-     
-    else:
-        form = LdtAddForm()
-        contents = Content.safe_objects.all()             
-        form_status = "none"    
-    
-    return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'form': form, 'form_status':form_status,
-                                                                'redirect_to': redirect_to, 'create_project_action':reverse(create_ldt_view), 'language_code' : settings.LANGUAGE_CODE[2:],
-                                                                'elem_list': get_userlist(request.user)}, context_instance=RequestContext(request))
-     
-def created_ldt(request):
-    return render_to_response('ldt/ldt_utils/save_done.html', context_instance=RequestContext(request))
-
-
-def index_segment(request, project_id, content_id, cutting_id, ensemble_id, segment_id):
-    url_str = settings.WEB_URL + reverse("ldt.ldt_utils.views.init_segment", args=[project_id, content_id, ensemble_id, cutting_id, segment_id])
-    post_url = ""
-    language_code = request.LANGUAGE_CODE[:2]
-    readonly = 'true'
-    template_path = 'ldt/ldt_utils/init_ldt.html'
-    
-    return render_to_response(template_path, {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': url_str, 'posturl': post_url, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request))
-    
-def init_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id):
-
-    if project_id != u"_":
-        get_object_or_404(Project.safe_objects, ldt_id=project_id)
-    
-    ldtgen = LdtUtils()
-    doc = ldtgen.generate_init([project_id, content_id, ensemble_id, cutting_id, segment_id], 'ldt.ldt_utils.views.ldt_segment', 'ldt.ldt_utils.views.highlight_segment')
-    
-    return HttpResponse(lxml.etree.tostring(lxml.etree.ElementTree(doc), pretty_print=True), mimetype="text/xml;charset=utf-8")
-
-def highlight_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id):
-    if project_id != u"_":
-        get_object_or_404(Project.safe_objects, ldt_id=project_id)
-    
-    iri = lxml.etree.Element('iri')
-    doc = lxml.etree.ElementTree(iri)    
-
-    seg = lxml.etree.SubElement(iri, 'seg')
-    seg.set('idctt', content_id)
-    seg.set('idens', ensemble_id)
-    seg.set('iddec', cutting_id)
-    seg.set('idseg', segment_id)
-    seg.set('idvue', "")
-    seg.set('crit', "")
-  
-    return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8") 
-
-
-def ldt_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id): 
-
-    resp = HttpResponse(mimetype="text/xml")
-    resp['Cache-Control'] = 'no-cache, must-revalidate'
-    resp['Pragma'] = 'no-cache'
-    
-    if project_id and project_id != "_" :
-        project = Project.safe_objects.get(ldt_id=project_id) #@UndefinedVariable
-        ldtdoc = lxml.etree.fromstring(project.ldt.encode("utf-8"))
-        ldtdoc = set_forbidden_stream(ldtdoc, request.user)
-        displays_node = ldtdoc.find("displays")
-        if not displays_node:
-            displays_node = lxml.etree.SubElement(ldtdoc, u"displays")        
-        res = displays_node.xpath("display")
-        if len(res) > 0:
-            display_node = res[0]
-        else:
-            display_node = lxml.etree.SubElement(displays_node, u"display", attrib={u'id':u'0', u'title': u'generated', u'idsel':unicode(content_id), u'tc':u'0'})
-        
-        res = display_node.xpath("content[@id='%s']/decoupage[(@id='%s') and (@idens='%s')]" % (content_id, cutting_id, ensemble_id))
-        if len(res) == 0:
-            #create node
-            res = display_node.xpath("content[@id='%s']" % (content_id))
-            if len(res) == 0:
-                content_node = lxml.etree.SubElement(display_node, u"content")
-            else:
-                content_node = res[0]
-            lxml.etree.SubElement(content_node, u"decoupage", attrib={u'id':unicode(cutting_id), u'idens':unicode(ensemble_id)})
-        active_segment_node = displays_node.find(u"activeSegment")
-        if not active_segment_node:
-            active_segment_node = lxml.etree.SubElement(displays_node, u"activeSegment")
-        id_node = active_segment_node.find(u"id")
-        if id_node:
-            active_segment_node.remove(id_node)
-        lxml.etree.SubElement(active_segment_node, u"id", attrib={u"idctt":unicode(content_id), u"idens": unicode(ensemble_id), "idcut":unicode(cutting_id), u"idseg":unicode(segment_id)})
-                                    
-        resp.write(lxml.etree.tostring(ldtdoc, xml_declaration=True, encoding='utf-8', pretty_print=True))
-    else:
-        # generate ldt from 
-        ldtgen = LdtUtils()
-        content_list = Content.safe_objects.filter(iri_id=content_id)
-        if request.user and request.user.username:
-            username = request.user.username
-        else:
-            username = "webuser"
-        
-        start_segment = {
-            'idcontent': content_id,
-            'idgroup' : ensemble_id,
-            'idcutting' : cutting_id,
-            'idsegment' : segment_id
-        }        
-        
-        doc = ldtgen.generate_ldt(content_list, "segment : ", author=username, startSegment=start_segment)
-        doc = set_forbidden_stream(doc, request.user)
-        doc.write(resp, pretty_print=('DEBUG' in dir(settings) and settings.DEBUG))
-        
-    return resp
-        
-   
-@login_required    
-def index_project(request, id, full=False): 
-
-    urlStr = settings.WEB_URL + reverse("space_ldt_init", args=['ldt_project', id])
-    posturl = settings.WEB_URL + reverse("ldt.ldt_utils.views.save_ldt_project")
-    language_code = request.LANGUAGE_CODE[:2]
-    
-    try:
-        ldt = Project.safe_objects.get(ldt_id=id)
-    except Project.DoesNotExist:
-        return HttpResponseRedirect(reverse("ldt.ldt_utils.views.workspace"))
-    
-    if ldt.state == 2 or not request.user.has_perm('change_project', ldt): #published
-        readonly = 'true'
-    else:
-        readonly = 'false'
-       
-    if full:
-        template_path = 'ldt/ldt_utils/init_ldt_full.html'
-    else:
-        template_path = 'ldt/ldt_utils/init_ldt.html'
-  
-    return render_to_response(template_path, {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': urlStr, 'posturl': posturl, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request))
-    
-    
-def init(request, method, url):
-    ldtgen = LdtUtils()
-
-    doc = ldtgen.generate_init([url], 'ldt.ldt_utils.views.' + method, None)    
-
-    library = doc.xpath('/iri/files/library')[0]
-    for c in Content.safe_objects.all():
-        elem = lxml.etree.SubElement(library, 'file')
-        elem.set('src', c.iri_url())
-        elem.set('video', c.videopath)
-        elem.set('title', c.title)
-        elem.set('author', '')
-        elem.set('category', '')
-        elem.set('pict', '')
-        elem.set('img', '')
-
-    resp = HttpResponse(mimetype="text/xml")
-    resp['Cache-Control'] = 'no-cache, must-revalidate'
-    resp['Pragma'] = 'no-cache'
-
-    resp.write(lxml.etree.tostring(doc, pretty_print=True, xml_declaration=True, encoding="utf-8")) 
-    return resp
-       
-def ldt_project(request, id): 
-    resp = HttpResponse(mimetype="text/xml")
-    resp['Cache-Control'] = 'no-cache, must-revalidate'
-    resp['Pragma'] = 'no-cache'
-    
-    project = Project.safe_objects.get(ldt_id=id) #@UndefinedVariable
-    
-    doc = lxml.etree.fromstring(project.ldt)
-    doc = set_forbidden_stream(doc, request.user)
-    resp.write(lxml.etree.tostring(doc, pretty_print=True, xml_declaration=True, encoding="utf-8")) 
-
-    return resp
-
-
-def project_json_id(request, id): 
-    
-    project = get_object_or_404(Project.safe_objects, ldt_id=id)
-
-    return project_json(request, project, False)
-
-
-def project_json_externalid(request, id): 
-        
-    res_proj = get_list_or_404(Project.safe_objects.order_by('-modification_date'), contents__external_id=id) #@UndefinedVariable
-    
-    return project_json(request, res_proj[0], False)
-
-
-
-def project_json(request, project, serialize_contents=True): # Not checked
-    
-    if not ldt_auth.check_access(request.user, project):
-        return HttpResponseForbidden(_("You can not access this project"))
-        
-    mimetype = request.REQUEST.get("mimetype")
-    if mimetype is None:
-        mimetype = "application/json; charset=utf-8"
-    else:
-        mimetype = mimetype.encode("utf-8")
-    if "charset" not in mimetype:
-        mimetype += "; charset=utf-8" 
-    resp = HttpResponse(mimetype=mimetype)
-    resp['Cache-Control'] = 'no-cache, must-revalidate'
-    resp['Pragma'] = 'no-cache'
-    
-    indent = request.REQUEST.get("indent")
-    if indent is None:
-        indent = settings.LDT_JSON_DEFAULT_INDENT
-    else:
-        indent = int(indent)
-    
-    callback = request.REQUEST.get("callback")
-    escape_str = request.REQUEST.get("escape")
-    escape_bool = False
-    if escape_str:
-        escape_bool = {'true': True, 'false': False, "0": False, "1": True}.get(escape_str.lower())
-        
-        
-    ps = ProjectSerializer(project, serialize_contents)
-    project_dict = ps.serialize_to_cinelab()
-    
-    json_str = simplejson.dumps(project_dict, ensure_ascii=False, indent=indent)
-    
-    if callback is not None:
-        json_str = "%s(%s)" % (callback, json_str)
-    
-    if escape_bool:
-        json_str = escape(json_str)
-    
-    resp.write(json_str)
-
-    return resp
-
-def project_annotations_rdf(request, ldt_id):
-
-    project = Project.safe_objects.get(ldt_id=ldt_id); #@UndefinedVariable
-    
-    if not ldt_auth.check_access(request.user, project):
-        return HttpResponseForbidden(_("You can not access this project"))
-
-    mimetype = request.REQUEST.get("mimetype")
-    if mimetype is None:
-        mimetype = "application/rdf+xml; charset=utf-8"
-    else:
-        mimetype = mimetype.encode("utf-8")
-    if "charset" not in mimetype:
-        mimetype += "; charset=utf-8" 
-    resp = HttpResponse(mimetype=mimetype)
-    resp['Cache-Control'] = 'no-cache, must-revalidate'
-    resp['Pragma'] = 'no-cache'
-
-    ps = ProjectSerializer(project, from_contents=False, from_display=True) 
-    annotations = ps.get_annotations(first_cutting=True)
-    
-    rdf_ns = u"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-    dc_ns = u"http://purl.org/dc/elements/1.1/"
-    rdf = u"{%s}" % rdf_ns
-    dc = u"{%s}" % dc_ns
-    nsmap = {u'rdf' : rdf_ns, u'dc':dc_ns}
-    
-    rdf_root = lxml.etree.Element(rdf + u"RDF", nsmap=nsmap)
-    
-    logging.debug("RDF annotations : " + repr(annotations)) #@UndefinedVariable
-    
-    for annotation in annotations:
-        uri = u""
-        if 'uri' in annotation and annotation['uri']:
-            uri = unicode(annotation['uri'])
-        annot_desc = lxml.etree.SubElement(rdf_root, rdf + u"Description")
-        annot_desc.set(rdf + u'about', uri)
-        if annotation['title']:
-            lxml.etree.SubElement(annot_desc, dc + 'title').text = lxml.etree.CDATA(unicode(annotation['title']))
-        if annotation['desc']:
-            lxml.etree.SubElement(annot_desc, dc + 'description').text = lxml.etree.CDATA(unicode(annotation['desc']))
-        if annotation['tags']:
-            for tag in annotation['tags']:
-                lxml.etree.SubElement(annot_desc, dc + 'subject').text = lxml.etree.CDATA(unicode(tag))
-        lxml.etree.SubElement(annot_desc, dc + 'coverage').text = u"start=%s, duration=%s" % (annotation['begin'], annotation['duration'])
-        
-    resp.write(u"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
-    resp.write(u"<!DOCTYPE rdf:RDF PUBLIC \"-//DUBLIN CORE//DCMES DTD 2002/07/31//EN\" \"http://dublincore.org/documents/2002/07/31/dcmes-xml/dcmes-xml-dtd.dtd\">\n")
-    
-    resp.write(lxml.etree.tostring(rdf_root, xml_declaration=False, encoding="utf-8", pretty_print=True))
-
-    return resp
-
-def save_ldt_project(request):
-    if request.method == "POST":
-        ldt = request.POST['ldt']
-        id = request.POST['id']
-        ldtproject = Project.safe_objects.get(ldt_id=id) #@UndefinedVariable
-
-        #save xml ldt
-        ldtproject.ldt = ldt
-
-        doc = lxml.etree.fromstring(ldtproject.ldt.encode("utf-8"))
-        result = doc.xpath("/iri/project")
-        
-        #set new title
-        ldtproject.title = result[0].get("title")
-        
-        #get new content list
-        new_contents = []
-        result = doc.xpath("/iri/medias/media")
-        for medianode in result:
-            id = medianode.get("id")
-            new_contents.append(id)
-    
-        #set new content list
-        for c in ldtproject.contents.all():
-            if not c.iri_id in new_contents:
-                ldtproject.contents.remove(c)
-    
-        ldtproject.save()
-    else:
-        ldt = ''
-        new_contents = []
-    
-    return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':id, 'title':ldtproject.title, 'contents': new_contents}, context_instance=RequestContext(request))
-
-@login_required
-def publish(request, id, redirect=True):
-    ldt = get_object_or_404(Project.safe_objects, ldt_id=id)
-    ldt.publish()
-    ldt.save()
-    redirect = boolean_convert(redirect)
-    if redirect:
-        return HttpResponseRedirect(reverse("ldt.ldt_utils.views.list_ldt"))
-    else:
-        return HttpResponse(simplejson.dumps({'res':True, 'ldt': {'id': ldt.id, 'state':ldt.state, 'ldt_id': ldt.ldt_id}}, ensure_ascii=False), mimetype='application/json')
-
-@login_required
-def unpublish(request, id, redirect=True):
-    ldt = get_object_or_404(Project.safe_objects, ldt_id=id)
-    ldt.unpublish()
-    ldt.save()
-    redirect = boolean_convert(redirect)
-    if redirect:
-        return HttpResponseRedirect(reverse("ldt.ldt_utils.views.list_ldt"))
-    else:
-        return HttpResponse(simplejson.dumps({'res':True, 'ldt': {'id': ldt.id, 'state':ldt.state, 'ldt_id': ldt.ldt_id}}, ensure_ascii=False), mimetype='application/json')
-    
-
-def index(request, url):
-    
-    urlStr = settings.WEB_URL + reverse("ldt_init", args=['ldt', url])
-    language_code = request.LANGUAGE_CODE[:2]
-    
-    return render_to_response('ldt/ldt_utils/init_ldt.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': urlStr, 'weburl':settings.WEB_URL + settings.BASE_URL}, context_instance=RequestContext(request))
-
-
-def ldt(request, url, startSegment=None): 
-    
-    resp = HttpResponse(mimetype="text/xml; charset=utf-8")
-    resp['Cache-Control'] = 'no-cache'
-
-    contentList = Content.safe_objects.filter(iri_id=url) #@UndefinedVariable
-
-    ldtgen = LdtUtils()
-    doc = ldtgen.generate_ldt(contentList, title=contentList[0].title, startSegment=startSegment)
-    doc = set_forbidden_stream(doc, request.user)
-    doc.write(resp, pretty_print=True)
-
-    return resp
-
-
-def loading(request): 
-    return render_to_response('ldt/ldt_utils/loading.html', context_instance=RequestContext(request))
-
-
-@login_required
-def create_project(request, iri_id): 
-    content = get_object_or_404(Content.safe_objects, iri_id=iri_id)
-    contents = [ content, ]
-    groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME)
-    redirect_to = ''
-    form_status = "none"
-    
-    if request.method == "POST" :        
-        form = AddProjectForm(request.POST)
-        
-        if form.is_valid():
-            user = request.user
-            project = Project.create_project(title=form.cleaned_data['title'], user=user, contents=contents, description=form.cleaned_data['description'])
-            form_status = "saved" 
-
-            if form.cleaned_data["share"]:
-                assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], user)
-
-            # Modal window is not used with firefox
-            is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-            if is_gecko :
-                redirect_to = reverse('index_project_full', args=[project.ldt_id])
-            else:
-                return HttpResponseRedirect(reverse('index_project', args=[project.ldt_id]))
-    else:
-        form = AddProjectForm()
-           
-    return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status': form_status, 'contents':contents,'groups' : groups,
-                                                                'redirect_to': redirect_to, 'elem_list': get_userlist(request.user), 'create_project_action':reverse("ldt.ldt_utils.views.create_project", args=[iri_id])}, context_instance=RequestContext(request))
-
-@login_required
-def update_project(request, ldt_id):
-    project = get_object_or_404(Project.safe_objects, ldt_id=ldt_id)
-    contents = project.contents.all()
-    groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME)
-    member_list, admin_list = get_userlist_model(project, request.user)
-    
-    if request.method == "POST" :
-        submit_action = request.REQUEST.get("submit_button", False)
-        if submit_action == "prepare_delete":
-            errors = []
-            if project.state == 2:
-                errors.append(_("the project %(title)s is published. please unpublish before deleting.") % {'title':project.title})
-                message = _("can not delete the project. Please correct the following error")
-                title = _('title error deleting project')
-            else:
-                message = _("please confirm deleting project %(title)s") % {'title':project.title}
-                title = _("confirm deletion")
-            return render_to_response('ldt/ldt_utils/error_confirm.html', {'errors':errors, 'message':message, 'title': title}, context_instance=RequestContext(request))
-        elif submit_action == "delete":
-            if project.state != 2:
-                project.delete()
-            form_status = 'deleted'
-            form = AddProjectForm()
-        else:
-            form_status = 'none' 
-            form = AddProjectForm(request.POST)
-            
-            if form.is_valid():          
-                if project.title != form.cleaned_data['title'] or project.description != form.cleaned_data['description']:
-                    project.title = form.cleaned_data['title']
-                    project.description = form.cleaned_data['description']
-                    ldt = lxml.etree.fromstring(project.ldt.encode("utf-8"))
-                    res = ldt.xpath("/iri/project")
-                    res[0].set("title", project.title)
-                    res[0].set("abstract", project.description)
-                    project.ldt = lxml.etree.tostring(ldt, pretty_print=True)
-                    project.save()                    
-                    
-                if form.cleaned_data["share"]:
-                    assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], request.user)
-                form_status = "saved"
-    else:
-        form = AddProjectForm({'title':unicode(project.title), 'description':unicode(project.get_description())})
-        
-        form_status = 'none'
-       
-    return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status':form_status, 'groups': groups, 'elem_list': get_userlist(request.user), 
-                                                                'ldt_id': ldt_id, 'contents':contents, 'member_list': member_list, 'admin_list': admin_list,
-                                                                'create_project_action':reverse("ldt.ldt_utils.views.update_project", args=[ldt_id])}, context_instance=RequestContext(request))
-
-@login_required
-def copy_project(request, ldt_id, group_id=0): 
-    
-    project = get_object_or_404(Project.safe_objects, ldt_id=ldt_id)
-    if request.method == "POST" :
-        form = CopyProjectForm(request.POST)
-        
-        if form.is_valid():
-            user = request.user
-            group_id = form.cleaned_data['group']
-            group = Group.objects.get(id=group_id) if group_id and group_id > 0 else None
-            project = project.copy_project(title=form.cleaned_data['title'], user=user, group=group)
-            is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-            if is_gecko:
-                return HttpResponseRedirect(reverse('index_project_full', args=[project.ldt_id]))
-            else:
-                return HttpResponseRedirect(reverse('index_project', args=[project.ldt_id]))
-    else:
-        form = CopyProjectForm()
-    # Modal window is not used with firefox, so we ask to submit the form in _parent in firefox case.
-    target_parent = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-    return render_to_response('ldt/ldt_utils/copy_ldt.html', {'form':form, 'project':project, 'group_id':group_id, 'target_parent':target_parent}, context_instance=RequestContext(request))
-
-
-def write_content_base(request, iri_id=None): 
-
-    if iri_id:        
-        instance_content = Content.safe_objects.get(iri_id=iri_id) #@UndefinedVariable
-        instance_media = instance_content.media_obj
-        logging.debug("write_content_base : valid form: for instance : media -> " + repr(instance_media) + " content : for instance : " + repr(instance_content)) #@UndefinedVariable
-    else:
-        logging.debug("No iri_id") #@UndefinedVariable
-        instance_content = None
-        instance_media = None
-    
-    form_status = 'none'        
-    if request.method == "POST":
-        
-        if instance_content is not None:
-            content_instance_val = model_to_dict(instance_content, exclude=ContentForm.Meta.exclude)
-        else:
-            content_instance_val = {}
-        
-        if instance_media is not None:
-            media_instance_val = model_to_dict(instance_media, exclude=MediaForm.Meta.exclude)
-        else:
-            media_instance_val = {}
-        #add prefix
-        
-        def add_prefix(dict, prefix):
-            for key, value in dict.items():
-                dict['%s-%s' % (prefix, key)] = value
-                del(dict[key])
-        
-        add_prefix(content_instance_val, "content")
-        add_prefix(media_instance_val, "media")     
-        
-        for k in request.POST.keys():
-            value = request.POST.get(k)
-            content_instance_val[k] = value
-            media_instance_val[k] = value
-            
-        content_instance_val['read_list'] = request.POST.getlist('read_list')
-        content_instance_val['write_list'] = request.POST.getlist('write_list')
-        content_instance_val['share'] = request.POST.get('share', False)
-
-        content_form = ContentForm(content_instance_val, prefix="content", instance=instance_content)
-        media_form = MediaForm(media_instance_val, request.FILES, prefix="media", instance=instance_media)
-                
-        media_valid = media_form.is_valid()
-        content_valid = content_form.is_valid()
-        logging.debug("write_content_base : valid form: for instance : " + repr(instance_media) + " -> media " + str(media_valid) + " content : for instance : " + repr(instance_content) + " : " + str(content_valid)) #@UndefinedVariable
-        
-        if media_valid and content_valid:
-
-            # see if media must be created
-            cleaned_data = {}
-            cleaned_data.update(media_form.cleaned_data)
-            
-            media_input_type = content_form.cleaned_data["media_input_type"]
-            
-            if media_input_type == "none":
-                media = None
-            elif media_input_type == "link":
-                media = content_form.cleaned_data["media_obj"]
-                created = False
-            elif media_input_type == "create":
-                del cleaned_data["media_file"]
-                if not cleaned_data['videopath']:
-                    cleaned_data['videopath'] = settings.STREAM_URL
-                # if the source is already http:// or rtmp:// we don't have to add STREAM_URL
-                if cleaned_data['src'].startswith("rtmp://") or cleaned_data['src'].startswith("http://"):
-                    cleaned_data['videopath'] = ''
-                media, created = Media.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
-            elif media_input_type == "url" or media_input_type == "upload" :
-                # copy file
-                #complet src
-                destination_file = None
-                source_file = None
-                try:
-                    if media_input_type == "url":
-                        url = cleaned_data["external_src_url"]
-                        source_file = urllib2.urlopen(url)
-                        source_filename = source_file.info().get('Content-Disposition', None)
-                        if not source_filename:
-                            source_filename = urlparse.urlparse(url).path.rstrip("/").split('/')[-1]
-                    elif media_input_type == "upload":
-                        #source_file = request.FILES['media-media_file']
-                        # At this point the file has already be uploaded thanks to the upload view, and original file name is sent through a post var
-                        source_filename = request.POST["media-local_file_name"]
-                    
-                    source_filename = ldt_utils_path.sanitize_filename(source_filename)
-                    destination_filepath = os.path.join(settings.STREAM_PATH, source_filename)
-                    base_source_filename = source_filename
-                    extension = base_source_filename.split(".")[-1]
-                    if extension == base_source_filename:
-                        extension = ""
-                        base_basename_filename = base_source_filename
-                    else:
-                        base_basename_filename = base_source_filename[:-1 * (len(extension) + 1)]
-                    i = 0
-                    
-                    while os.path.exists(destination_filepath):
-                        base_source_filename = "%s.%d.%s" % (base_basename_filename, i, extension)
-                        destination_filepath = os.path.join(settings.STREAM_PATH, base_source_filename)
-                        i += 1
-                    
-                    if media_input_type == "url":
-                        # we upload the file if we are in url case
-                        destination_file = open(destination_filepath, "wb")
-                        chunck = source_file.read(2048)
-                        while chunck:
-                            destination_file.write(chunck)
-                            chunck = source_file.read(2048)
-                        
-                    elif media_input_type == "upload":
-                        # The media file has been uploaded in the session temp folder 
-                        # so we just have to move to the regular folder and rename it.
-                        if os.path.exists(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename)):
-                            os.rename(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename), os.path.join(settings.STREAM_PATH, base_source_filename))
-                    
-                    
-                    src_prefix = settings.STREAM_SRC_PREFIX.rstrip("/")
-                    if len(src_prefix) > 0:
-                        cleaned_data["src"] = src_prefix + "/" + base_source_filename
-                    else:
-                        cleaned_data["src"] = base_source_filename
-                    
-                    
-                except Exception as inst:
-                    logging.debug("write_content_base : POST error when processing file:" + str(inst)) #@UndefinedVariable
-                    form_status = "error"
-                    #set error for form
-                    if media_input_type == "url":
-                        errors = media_form._errors.setdefault("external_src_url", ErrorList())
-                        errors.append(_("Problem when downloading file from url : ") + url)
-                    elif media_input_type == "upload":
-                        errors = media_form._errors.setdefault("media_file", ErrorList())
-                        errors.append(_("Problem when uploading file : ") + str(inst))
-                finally:
-                    if media_input_type == "url":
-                        if destination_file:
-                            destination_file.close()
-                        if source_file:
-                            source_file.close()
-                
-                
-                if form_status != "error":
-                    #try:
-                    del cleaned_data["media_file"]
-                    if not cleaned_data['videopath']:
-                        cleaned_data['videopath'] = settings.STREAM_URL
-                    mimetype = cleaned_data.get('mimetype_field', None)
-                    if not mimetype:
-                        mimetype = mimetypes.guess_type(cleaned_data['src'])
-                    cleaned_data['mimetype_field'] = mimetype
-                    media, created = Media.safe_objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
-                    cached_assign('view_media', request.user, media)
-                else:
-                    media = None
-                    
-
-            if media and not created:
-                for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title'):
-                    setattr(media, attribute, cleaned_data.get(attribute))
-                mimetype = cleaned_data.get('mimetype_field', None)
-                if not mimetype:
-                    mimetype = mimetypes.guess_type(media.src)
-                media.mimetype_field = mimetype
-                cached_assign('view_media', request.user, media)
-                cached_assign('change_media', request.user, media)
-                media.save()
-            
-            if form_status != "error": 
-                content_defaults = {}
-                content_defaults.update(content_form.cleaned_data)
-                content_defaults['media_obj'] = media
-                               
-                for key in ["media_input_type", "groups", "is_public", "read_list", "write_list", "share" ]:
-                    del content_defaults[key]
-                     
-                content, created = Content.safe_objects.get_or_create(iri_id=content_form.cleaned_data['iri_id'], defaults=content_defaults) #@UndefinedVariable
-                if not created:
-                    content.save() # Check if user is allowed to change object before assigning permissions.
-                cached_assign('change_content', request.user, content)
-                cached_assign('view_content', request.user, content)
-                everyone = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
-                if content_form.cleaned_data['is_public']:
-                    cached_assign('view_content', everyone, content)
-                    if media:
-                        cached_assign('view_media', everyone, media)
-                elif content_form.cleaned_data["share"]:
-                    remove_perm('view_content', everyone, content)
-                    assign_perm_to_obj(content, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user)
-                    if media:
-                        assign_perm_to_obj(media, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user)
-                if not created:
-                    for attribute in ('iriurl', 'title', 'description', 'duration', 'content_creation_date', 'tags', 'media_obj'):
-                        setattr(content, attribute, content_defaults[attribute])
-                content.save()
-                form_status = 'saved'
-                media_form = MediaForm(instance=media, prefix="media")
-                content_form = ContentForm(instance=content, prefix="content")
-        else:
-            form_status = 'error'
-    else:
-        form_status = 'empty'
-        initial = { 'media_input_type':"link"}
-        if instance_content:
-            initial['is_public'] = instance_content.is_public
-        
-        content_form = ContentForm(prefix="content", instance=instance_content, initial=initial)
-        media_form = MediaForm(prefix="media", instance=instance_media)  
-                
-        if instance_content is not None:
-            content_form.media_input_type = "link"
-    
-    return content_form, media_form, form_status
-
-@login_required
-def write_content(request, iri_id=None):    
-    submit_action = request.REQUEST.get("submit_button", False) 
-    groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME)
-    member_list = admin_list = []
-    
-    if submit_action == "prepare_delete": 
-        errors, titles = prepare_delete_content(request, iri_id)
-        if errors and len(errors) > 0:
-            message = ungettext("There is %(count)d error when deleting content", "There are %(count)d errors when deleting content", len(errors)) % { 'count': len(errors)}
-            title_msg = _('title error deleting content')
-        else:
-            message = _("Confirm delete content %(titles)s") % { 'titles' : ",".join(titles) }
-            title_msg = _("confirm delete content")
-        return render_to_response('ldt/ldt_utils/error_confirm.html', {'errors':errors, 'message':message, 'title': title_msg}, context_instance=RequestContext(request))  
-    elif submit_action == "delete":
-        delete_content(request, iri_id)
-        form_status = "deleted"
-        content_form = ContentForm()
-        media_form = MediaForm()
-    else:
-        content_form, media_form, form_status = write_content_base(request, iri_id)
-        if iri_id:
-            member_list, admin_list = get_userlist_model(Content.objects.get(iri_id=iri_id), request.user)
-        
-    if iri_id:
-        create_content_action = reverse('ldt.ldt_utils.views.write_content', kwargs={'iri_id':iri_id})
-    else:        
-        create_content_action = reverse('ldt.ldt_utils.views.write_content')
-    
-    session_key = request.COOKIES[settings.SESSION_COOKIE_NAME]
-    cookie_name = settings.SESSION_COOKIE_NAME    
-    content_form.fields["media_obj"].queryset = Media.safe_objects.all()
-    
-    return render_to_response('ldt/ldt_utils/create_content.html', {'content_form': content_form, 'media_form': media_form, 'form_status': form_status, 'create_content_action': create_content_action,
-                                                                    'elem_list': get_userlist(request.user), 'member_list': member_list, 'admin_list': admin_list,  'iri_id': iri_id, 'session_key':session_key, 'cookie_name':cookie_name}, context_instance=RequestContext(request))
-
-@login_required
-def prepare_delete_content(request, iri_id=None): 
-    errors = []
-    titles = []
-    if not iri_id:
-        iri_id = request.REQUEST.get("iri_id", None)
-        
-    if iri_id:
-        for content in Content.safe_objects.filter(iri_id=iri_id): 
-            titles.append(unicode(content.title))
-            projects = content.project_set.all()
-            projects_nb = len(projects)
-            if projects_nb > 0:
-                project_titles = map(lambda p: unicode(p.title), projects)
-                errors.append(ungettext("Content '%(title)s' is referenced by this project : %(project_titles)s. Please delete it beforehand.", "Content '%(title)s' is referenced by %(count)d projects: %(project_titles)s. Please delete them beforehand.", projects_nb) % {'title':unicode(content.title), 'count':projects_nb, 'project_titles': ",".join(project_titles)})
- 
-    return errors, titles
-
-
-@login_required
-def delete_content(request, iri_id=None):
-    if not iri_id:
-        iri_id = request.REQUEST.get("iri_id", None)
-        
-    if iri_id:
-        Content.safe_objects.get(iri_id=iri_id).delete()
-
-
-def upload(request):
-    if request.method == 'POST':
-        for field_name in request.FILES:
-            # We get the file name
-            source_file = request.FILES[field_name]
-            source_filename = source_file.name
-            # We sanitize the file name : no space, only lower case.
-            source_filename = ldt_utils_path.sanitize_filename(source_filename)
-            # We create the session temp folder if necessary
-            if not os.path.exists(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME])):
-                os.makedirs(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME]))
-            destination_filepath = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename)
-            # We delete the existing file if necessary
-            if os.path.exists(destination_filepath):
-                os.remove(destination_filepath)
-            
-            destination_file = open(destination_filepath, "wb")
-            
-            for chunk in source_file.chunks():
-                destination_file.write(chunk)
-            destination_file.close()
-            
-        # indicate that everything is OK for SWFUpload
-        return HttpResponse("ok", mimetype="text/plain")
-    else:
-        return HttpResponse("notok", mimetype="text/plain")
-
-def remove_temp_file(request):
-    # The filename arrives with a GET var.
-    file_path = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", ldt_utils_path.sanitize_filename(request.GET["filename"]))
-    if os.path.exists(file_path):
-        os.remove(file_path)
-    return HttpResponse("remove ok", mimetype="text/plain")
-
-def get_duration(request):
-    try:
-        # The filename arrives with a GET var.
-        file_path = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", ldt_utils_path.sanitize_filename(request.GET["filename"]))
-        if hasattr(settings, 'FFMPEG_PATH') and os.path.exists(file_path):
-            output = str(subprocess.Popen([settings.FFMPEG_PATH, "-i", file_path], stderr=subprocess.PIPE).communicate()[1])
-            m = re.search("Duration:\s*?([\d.:]+)", output, re.M)
-            dur_arr = m.group(1).split(":")
-            td = datetime.timedelta(hours=int(dur_arr[0]), minutes=int(dur_arr[1]), seconds=float(dur_arr[2]))
-            str_duration = str((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / 10 ** 3)
-            return HttpResponse(str_duration, mimetype="text/plain")
-        else:
-            return HttpResponse("", mimetype="text/plain")
-    except Exception as inst:
-        return HttpResponse(str(inst), mimetype="text/plain")
-
-
-@login_required
-def get_group_projects(request):
-
-    # Get group, user and project_list
-    grp_id = request.POST["id_group"]
-    if grp_id == "-1":
-        project_list = get_objects_for_user(request.user, 'ldt_utils.view_project', use_groups=False).exclude(owner=request.user)
-    else:
-        grp = Group.objects.get(id=grp_id)
-        everyone = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
-        project_list = get_objects_for_group(grp, 'ldt_utils.view_project') | get_objects_for_group(everyone, 'ldt_utils.view_project').filter(owner__in=[grp])
-    
-    project_list = add_change_attr(request.user, project_list)
-    
-    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-
-    return render_to_response("ldt/ldt_utils/partial/projectslist.html",
-                              {'projects': project_list, 'show_username':True,
-                               'is_gecko': is_gecko, 'group_id': grp_id},
-                              context_instance=RequestContext(request))
-
-@login_required
-def create_group(request):
-    if not request.user.user_permissions.filter(codename='add_group'):
-        return HttpResponseServerError('<h1>User %s can not create a group.</h1>' % request.user.username)
-
-    form_status = ''
-    
-    if request.method == 'POST':
-        form = GroupAddForm(request.POST)
-        
-        if form.is_valid():         
-            name = form.cleaned_data['name']
-            members_list = form.cleaned_data['read_list']
-            admin_list = form.cleaned_data['write_list']          
-            
-            group = Group.objects.create(name=name)
-            group.save()
-            cached_assign('is_owner_group', request.user, group)
-            cached_assign('change_group', request.user, group)
-            request.user.groups.add(group)             
-
-            for elem in members_list:
-                if hasattr(elem, 'username'):
-                    elem.groups.add(group)
-                    if elem in admin_list:
-                        cached_assign('change_group', elem, group)
-                        
-            form_status = 'saved'
-            
-    else:
-        form = GroupAddForm()
-        
-    return render_to_response("ldt/ldt_utils/create_group.html", {'group_edition': True, 'form' : form, 'form_status' : form_status, 'elem_list' : get_userlist(request.user)}, context_instance=RequestContext(request))
-
-@login_required
-def update_group(request, group_id):
-    group = get_object_or_404(Group, id=group_id)
-    checker = get_cached_checker(request.user)
-    
-    if not checker.has_perm('change_group', group):
-        form_status = 'none'
-        return render_to_response("ldt/ldt_utils/create_group.html", {'form_status' : form_status}, context_instance=RequestContext(request))
-
-    form_status = ''
-    is_owner_group = checker.has_perm('is_owner_group', group)     
-            
-    if request.method == "POST":
-        form = GroupAddForm(request.POST, instance=group)
-        submit_action = request.REQUEST.get("submit_button", False)
-        
-        if submit_action == 'delete':
-            if is_owner_group:
-                group.delete()
-                form_status = 'deleted'
-        else:   
-            if form.is_valid():
-                name = form.cleaned_data['name']
-                new_member_list = form.cleaned_data['read_list']
-                old_member_list = group.user_set.exclude(id=request.user.id)
-                admin_list = form.cleaned_data['write_list']
-                group.name = name
-
-                for user in new_member_list:
-                    if not hasattr(user, 'username'):
-                        raise AttributeError('new_member_list should only contain users')
-                    if user != request.user:                      
-                        group.user_set.add(user)
-                        if is_owner_group:
-                            if user in admin_list:
-                                cached_assign('change_group', user, group)
-                            else:
-                                remove_perm('change_group', user, group)
-                                
-                for user in old_member_list:
-                    if user not in new_member_list:
-                        group.user_set.remove(user)
-                        remove_perm('change_group', user, group)
-                                        
-                group.save()
-                form_status = 'saved'                   
-    else:
-        form = GroupAddForm(initial={'name':unicode(group.name)})    
-
-    if form_status != 'deleted':
-        member_list, admin_list = get_userlist_group(group, request.user)
-    else:    
-        member_list = admin_list = []
-        
-    return render_to_response("ldt/ldt_utils/create_group.html", {'group_id' : group_id, 'form' : form, 'form_status' : form_status, 'group_edition': True,
-                                                                  'elem_list' : get_userlist(request.user), 'member_list': member_list, 'admin_list': admin_list,
-                                                                  'is_owner_group': is_owner_group}, context_instance=RequestContext(request))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/management/commands/statannotation.py	Tue Jan 10 16:09:28 2012 +0100
@@ -0,0 +1,37 @@
+from django.core.management.base import BaseCommand
+from ldt.ldt_utils.models import Content
+from ldt.ldt_utils.stat import update_stat_content
+from optparse import make_option
+
+class Command(BaseCommand):
+    help = 'Computes annotation volume for a given content'
+    
+    option_list = BaseCommand.option_list + (
+        make_option("-c", "--content",
+                  dest="content",
+                  action="store",
+                  help="The id of the content we want to compute annotation volume on"),
+        )
+    
+    def handle(self, *args, **options):
+        parser = self.create_parser("statannotation", "")
+        options, args = parser.parse_args()
+                
+        verbose = (options.verbosity == "2")
+       
+        id_content = options.content
+        if id_content:
+            contents = Content.objects.filter(iri_id=id_content)
+            if not len(contents):
+                print "No content found with iri_id %s" % id_content
+                return None
+        else:
+            contents = Content.objects.all()
+            print "analysing all contents"
+        
+        
+        for content in contents:     
+            update_stat_content(content)
+                  
+        return None
+    
\ No newline at end of file
--- a/src/ldt/ldt/security/utils.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/security/utils.py	Tue Jan 10 16:09:28 2012 +0100
@@ -2,6 +2,7 @@
 from django.contrib.contenttypes.models import ContentType
 from guardian.shortcuts import assign, remove_perm, get_users_with_perms, get_groups_with_perms, get_objects_for_user
 from cache import get_cached_userlist
+import types
 
 try:
     from threading import local
@@ -60,9 +61,25 @@
         del cls.old_delete
         cls.safe_objects.user = None 
         
+def unprotect_instance(instance):
+    if hasattr(instance, 'old_save'):
+        instance.save = instance.old_save
+        instance.delete = instance.old_delete
+        
+def protect_instance(instance):
+    class_name = instance.__class__.__name__.lower()
+    cls = ContentType.objects.get(model=class_name)
+    cls = cls.model_class()
+    
+    save = types.MethodType(change_security('project')(cls.save), instance, cls)
+    instance.save = save
+    
+    delete = types.MethodType(change_security('project')(cls.delete), instance, cls)
+    instance.delete = delete
+        
 def change_security(cls_name):
     def wrapper(func):
-        def wrapped(self, *args, **kwargs):                      
+        def wrapped(self, *args, **kwargs):  
                         
             if self.pk and not get_current_user().has_perm('change_%s' % cls_name, self):
                 raise AttributeError('User %s is not allowed to change object %s' % (get_current_user(), self))
--- a/src/ldt/ldt/user/forms.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/user/forms.py	Tue Jan 10 16:09:28 2012 +0100
@@ -140,14 +140,14 @@
             return None
         
         class_name = self.model.__class__.__name__
-        if class_name == 'User':
-            instance_name = self.model.username
+        if class_name == 'User' or class_name == 'Group':
+            instance_name = self.model.id
             img_container = self.model.get_profile()
-        elif class_name == 'Group':
-            instance_name = self.model.name
-            img_container = self.model.profile
-        elif class_name == 'Content' or class_name == 'Project':
-            instance_name = self.model.title
+        elif class_name == 'Content':
+            instance_name = self.model.iri_id
+            img_container = self.model
+        elif class_name == 'Project':
+            instance_name = self.model.ldt_id
             img_container = self.model
             
         # We change the file name and keep the extension.
--- a/src/ldt/ldt/user/migrations/0006_auto__add_field_userprofile_image.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/user/migrations/0006_auto__add_field_userprofile_image.py	Tue Jan 10 16:09:28 2012 +0100
@@ -1,3 +1,4 @@
+#@PydevCodeAnalysisIgnore
 # encoding: utf-8
 import datetime
 from south.db import db
--- a/src/ldt/ldt/user/migrations/0007_auto__add_groupprofile.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/user/migrations/0007_auto__add_groupprofile.py	Tue Jan 10 16:09:28 2012 +0100
@@ -1,3 +1,4 @@
+#@PydevCodeAnalysisIgnore
 # encoding: utf-8
 import datetime
 from south.db import db
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/user/migrations/0008_auto__chg_field_groupprofile_image__chg_field_groupprofile_group__chg_.py	Tue Jan 10 16:09:28 2012 +0100
@@ -0,0 +1,85 @@
+#@PydevCodeAnalysisIgnore
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Changing field 'GroupProfile.image'
+        db.alter_column('user_groupprofile', 'image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=200))
+
+        # Changing field 'UserProfile.image'
+        db.alter_column('user_userprofile', 'image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=200))
+
+
+    def backwards(self, orm):
+        
+        # Changing field 'GroupProfile.image'
+        db.alter_column('user_groupprofile', 'image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=100))
+
+        # Changing field 'UserProfile.image'
+        db.alter_column('user_userprofile', 'image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=100))
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'user.groupprofile': {
+            'Meta': {'object_name': 'GroupProfile'},
+            'description': ('django.db.models.fields.TextField', [], {}),
+            'group': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/groups/group_default_icon.png'", 'max_length': '200'})
+        },
+        'user.ldt': {
+            'Meta': {'object_name': 'Ldt', '_ormbases': ['auth.User']},
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'user.userprofile': {
+            'Meta': {'object_name': 'UserProfile'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/users/user_default_icon.png'", 'max_length': '200'}),
+            'language': ('django.db.models.fields.CharField', [], {'default': "'fr'", 'max_length': '2'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
+        }
+    }
+
+    complete_apps = ['user']
--- a/src/ldt/ldt/user/models.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/src/ldt/ldt/user/models.py	Tue Jan 10 16:09:28 2012 +0100
@@ -34,9 +34,8 @@
     
 class UserProfile (models.Model): 
     user = models.OneToOneField(User)
-    language = models.CharField(max_length=2, default=settings.LANGUAGE_CODE[:2])
-    
-    image = ImageField(upload_to=settings.MEDIA_ROOT+"thumbnails/users/", default=settings.DEFAULT_USER_ICON)
+    language = models.CharField(max_length=2, default=settings.LANGUAGE_CODE[:2])    
+    image = ImageField(upload_to=settings.MEDIA_ROOT+"thumbnails/users/", default=settings.DEFAULT_USER_ICON, max_length=200)
 
     @staticmethod
     def create_user_profile(sender, instance, created, **kwargs):
@@ -46,7 +45,7 @@
 class GroupProfile(models.Model):
     group = models.OneToOneField(Group, primary_key=False, related_name='profile')
     description = models.TextField()
-    image = ImageField(upload_to=settings.MEDIA_ROOT+"thumbnails/groups/", default=settings.DEFAULT_GROUP_ICON)
+    image = ImageField(upload_to=settings.MEDIA_ROOT+"thumbnails/groups/", default=settings.DEFAULT_GROUP_ICON, max_length=200)
     
     @staticmethod
     def create_group_profile(sender, instance, created, **kwargs):
@@ -54,6 +53,13 @@
             profile = GroupProfile()
             profile.group_id = instance.id
             profile.save()
+            
+            
+# To keep consistency with User.get_profile() method
+def get_profile(self):
+    return self.profile
+
+Group.add_to_class("get_profile", get_profile)
 
 post_save.connect(GroupProfile.create_group_profile, sender=Group)
 post_save.connect(UserProfile.create_user_profile, sender=User)
--- a/web/ldtplatform/settings.py	Mon Jan 09 15:12:15 2012 +0100
+++ b/web/ldtplatform/settings.py	Tue Jan 10 16:09:28 2012 +0100
@@ -213,6 +213,8 @@
 
 WEB_VERSION = ldtplatform.get_version()
 
+DIVISIONS_FOR_STAT_ANNOTATION = 64
+
 from config import *
 
 if not "LOGIN_URL" in locals():