Merge with upstream
authorhamidouk
Mon, 16 Jan 2012 09:57:38 +0100
changeset 396 134fe0c9e811
parent 395 557cefc119e9 (current diff)
parent 391 b5c0d6a45f28 (diff)
child 397 bfea870f9eb9
Merge with upstream
--- a/.project	Mon Jan 16 09:56:08 2012 +0100
+++ b/.project	Mon Jan 16 09:57:38 2012 +0100
@@ -1,17 +1,23 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>platform_group</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>com.aptana.ide.core.unifiedBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>com.aptana.projects.webnature</nature>
-	</natures>
-</projectDescription>
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>platform_group</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.aptana.ide.core.unifiedBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.aptana.projects.webnature</nature>
+		<nature>org.python.pydev.pythonNature</nature>
+	</natures>
+</projectDescription>
--- a/src/ldt/ldt/api/ldt/handlers.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/api/ldt/handlers.py	Mon Jan 16 09:57:38 2012 +0100
@@ -165,7 +165,7 @@
             for a in new_annotations:
                 dur = str(a['end'] - a['begin'])
                 begin = str(a['begin'])
-                new_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['data'], '', a['tags'], begin, dur, author, date)
+                type_id, 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
@@ -175,7 +175,9 @@
                 unprotect_instance(content)
                 add_annotation_to_stat(content, project, a['begin'], a['end'])
                 protect_instance(content)
-                    
+                
+                # We update the ids
+                a['type'] = type_id
                 a['id'] = new_id
             
             # We save if there were added annotation
--- a/src/ldt/ldt/ldt_utils/forms.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/forms.py	Mon Jan 16 09:57:38 2012 +0100
@@ -50,7 +50,8 @@
     content_creation_date = forms.SplitDateTimeField(widget=ldt_widgets.LdtSplitDateTime, required=False, label=_("content.content_creation_date"))
     media_input_type = forms.ChoiceField(required=False, label=_("content.media_input_type"), choices=(("upload", _("file_upload")), ("url", _("url")), ("link", _("existing_media")), ("create", _("create_media")), ("none", _("none_media"))))
     groups = forms.ModelMultipleChoiceField(Group.objects.all(), required=False)
-    is_public = forms.BooleanField(required=False)  
+    is_public = forms.BooleanField(required=False)
+    front_project = forms.ModelChoiceField(queryset=Project.objects.all(), required=False, label=_("content.front_project")) 
         
     def clean_iri_id(self):
         data = self.cleaned_data.get('iri_id')
--- a/src/ldt/ldt/ldt_utils/migrations/0012_auto__add_field_content_last_annotated.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/migrations/0012_auto__add_field_content_last_annotated.py	Mon Jan 16 09:57:38 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/ldt_utils/migrations/0013_auto__add_field_content_front_project__chg_field_content_last_annotate.py	Mon Jan 16 09:57:38 2012 +0100
@@ -0,0 +1,162 @@
+#@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.front_project'
+        db.add_column('ldt_utils_content', 'front_project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ldt_utils.Project'], null=True, blank=True), keep_default=False)
+
+        # Changing field 'Content.last_annotated'
+        db.alter_column('ldt_utils_content', 'last_annotated', self.gf('django.db.models.fields.DateTimeField')())
+
+        # Changing field 'Content.last_annotated'
+        db.alter_column('ldt_utils_content', 'last_annotated', self.gf('django.db.models.fields.DateTimeField')(null=True))
+
+
+    def backwards(self, orm):
+        
+        # Deleting field 'Content.front_project'
+        db.delete_column('ldt_utils_content', 'front_project_id')
+
+        # Changing field 'Content.last_annotated'
+        db.alter_column('ldt_utils_content', 'last_annotated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True))
+
+        # Changing field 'Content.last_annotated'
+        db.alter_column('ldt_utils_content', 'last_annotated', self.gf('django.db.models.fields.DateTimeField')())
+
+
+
+    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'}),
+            'front_project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", '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'd9a1c770-3dc7-11e1-ac36-001485352c9a'", 'unique': 'True', 'max_length': '1024'}),
+            'iriurl': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'last_annotated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            '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 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py	Mon Jan 16 09:57:38 2012 +0100
@@ -6,6 +6,7 @@
 from ldt.core.models import Document
 from guardian.shortcuts import assign, remove_perm, get_perms
 import ldt.indexation
+from ldt.security import get_current_user_or_admin
 from ldt.security.models import SafeModel
 from ldt.security.manager import SafeManager
 from sorl.thumbnail import ImageField
@@ -131,7 +132,8 @@
     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'))
-    last_annotated = models.DateTimeField(default=datetime.datetime.now, verbose_name=_('content.last_annotated'))
+    last_annotated = models.DateTimeField(default=datetime.datetime.now, verbose_name=_('content.last_annotated'), blank=True, null=True)
+    front_project = models.ForeignKey('Project', null=True, blank=True)
         
     class Meta:
         ordering = ["title"]
@@ -206,9 +208,28 @@
     #TODO: better manage the change in .iri name and error scenario (save in temp file + rename
     def save(self, *args, **kwargs):
         
-        self.sync_iri_file()        
-        # update it 
+        create_front_project = False
+        # update it
+        self.sync_iri_file()
+        
+        if not self.pk:
+            create_front_project = True
+            
+            if not self.nb_annotation:
+                self.nb_annotation = 0
+            if not self.stat_annotation:
+                self.stat_annotation = '0,0'     
+
         super(Content, self).save(*args, **kwargs)
+        
+        if create_front_project: 
+            # We need a primary key for self in create_project, so
+            # save() has to be called first
+            user = get_current_user_or_admin()
+            self.front_project = Project.create_project(user,'front_%s' % self.iri_id, [self], cuttings=['chapitrage', 'contribution'] )
+            self.front_project.publish(allow_write=True)
+            assign('ldt_utils.change_content', user, self)
+            self.save()
             
     def __unicode__(self):
         return str(self.id) + ": " + self.iri_id
@@ -407,7 +428,7 @@
     stream_mode = property(**stream_mode())
 
     @staticmethod
-    def create_project(user, title, contents, description='', groups=[], set_icon=True):
+    def create_project(user, title, contents, description='', groups=[], set_icon=True, cuttings=[]):
 #        owner = Owner.objects.get(user=user) #@UndefinedVariable
         owner = user
         project = Project(title=title, owner=owner, description=description)
@@ -420,13 +441,14 @@
         assign('change_project', user, project)           
                         
         for content in contents:
-            project.add_contents([content])
+            project.add_contents([content])        
         
         if set_icon:
             project.set_icon()
         project.save()
-                        
-        return create_ldt(project, user)
+               
+        return create_ldt(project, user, cuttings)
+
 
     def copy_project(self, user, title, description='', group=None):
         project = Project(title=title, owner=user, description=description)
@@ -439,12 +461,14 @@
             project.add_contents([content])
         return project
     
-    def publish(self):
+    def publish(self, allow_write=False):
         if not self.pk:
             self.save()
         self.state = 2
         everyone = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
         assign('ldt_utils.view_project', everyone, self)
+        if allow_write:
+            assign('ldt_utils.change_project', everyone, self)
         self.save()
         
     def unpublish(self):
@@ -453,8 +477,10 @@
         self.state = 1
         everyone = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
         remove_perm('ldt_utils.view_project', everyone, self)
+        remove_perm('ldt_utils.change_project', everyone, self)
         self.save()
         
+        
     def set_icon(self):
         default_image = os.path.basename(settings.DEFAULT_CONTENT_ICON)
 
@@ -475,13 +501,20 @@
     def add_contents(self, contents):
         for content in contents:
             contribution = AnnotationStat.objects.create(project=self, content=content)
-            contribution.save()  
+            contribution.save() 
+            
+    def remove_contents(self, contents):
+        AnnotationStat.objects.filter(project=self, content__in=contents).delete()
+         
         
 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"))
+    
+    def __unicode__(self):
+        return "%s::%s" % (self.project.ldt_id, self.content.iri_id)
 
 class Segment(SafeModel):
     
--- a/src/ldt/ldt/ldt_utils/projectserializer.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/projectserializer.py	Mon Jan 16 09:57:38 2012 +0100
@@ -69,18 +69,17 @@
             
             # sets cutting to display in first position for the metadataplayer
             if self.first_cutting:
-                first_cutting = "c_%s" % self.first_cutting.upper()
                 
                 annotation_types = new_display['annotation_types']
                 if len(annotation_types) > 1:
                     index = -1
                     for i, s in enumerate(annotation_types):
-                        if s == first_cutting: 
+                        if s == self.first_cutting: 
                             index = i
                             break
                     if index >= 0:
                         annotation_types[0], annotation_types[index] = annotation_types[index], annotation_types[0]
-                
+            
             self.views_dict[display_id] = new_display
             
     
@@ -165,7 +164,7 @@
                 element_begin = element_node.attrib[u"begin"]
                 element_duration = element_node.attrib[u"dur"]
                 element_media = content.iri_id
-                element_color = element_node.attrib[u"color"]
+                element_color = element_node.attrib.get(u"color", "")
                 element_ldt_src = element_node.attrib.get(u"src", "")
                 
                 element_title = reduce_text_node(element_node, "title/text()")        
@@ -416,22 +415,9 @@
         res['views'] = self.views_dict.values() if len(self.views_dict) > 0 else None
         
         res['annotation-types'] = self.annotation_types_dict.values() if len(self.annotation_types_dict) > 0 else None
-        res['annotations'] = self.annotations_dict.values() if len(self.annotations_dict) > 0 else None 
-
-
-        if self.first_cutting:
-            first_cutting = "c_%s" % self.first_cutting.upper()
-            
-            index = -1
-            for i, ann in enumerate(res['annotation-types']):
-                if ann['id'] == first_cutting:
-                    index = i
-                    break
-                 
-            if index > 0:
-                res['annotation-types'][0],  res['annotation-types'][1] = res['annotation-types'][1],  res['annotation-types'][0]
+        res['annotations'] = self.annotations_dict.values() if len(self.annotations_dict) > 0 else None
         
-        return res
+        return res 
     
     def get_annotations(self, first_cutting=True):
         
--- a/src/ldt/ldt/ldt_utils/stat.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/stat.py	Mon Jan 16 09:57:38 2012 +0100
@@ -88,8 +88,10 @@
     contributions = AnnotationStat.objects.filter(project=instance)
     
     for c in contributions:
-        content = contents.get(id=c.content.id)        
-        content.nb_annotation -= c.nb_annotation
+        content = contents.get(id=c.content.id)
+        
+        if c.nb_annotation:        
+            content.nb_annotation -= c.nb_annotation
         
         if c.stat:
             content_stat = get_buckets_from_string(content.stat_annotation)
--- a/src/ldt/ldt/ldt_utils/templates/front/front_search_results.html	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_search_results.html	Mon Jan 16 09:57:38 2012 +0100
@@ -145,7 +145,7 @@
                             <a href="{% url ldt.ldt_utils.views.lignesdetemps.index_segment segment.project_id segment.iri_id segment.ensemble_id segment.decoupage_id segment.element_id %}"><img src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" /></a>
                             <!--p class="duree_segment">{{ segment.duration|str_duration:"::" }}</p-->
                         </div>
-                        <h4 class="title_segment"><a class="blue under" href="{% url ldt.ldt_utils.views.lignesdetemps.index_segment segment.project_id segment.iri_id segment.ensemble_id segment.decoupage_id segment.element_id %}">
+                        <h4 class="title_segment"><a class="blue under" href="{% url ldt.ldt_utils.views.front.annot_content segment.iri_id segment.decoupage_id %}">
                           {% if segment.title %}{{ segment.title }}{% else %}{% trans "No title" %}{% endif %}</a></h4>
                         <p class="text_segment">{% if segment.context %}{{ segment.context }}{% endif %}<br/>{% trans "Begin" %} : {{ segment.begin|str_duration:"::" }} - {% trans "duration" %} : {{ segment.duration|str_duration:"::" }}</h4>
                     </li>
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html	Mon Jan 16 09:57:38 2012 +0100
@@ -56,6 +56,10 @@
 		});
 		
 		public_checkbox($("#public input"));
+		
+		if ('{{form_status}}' == 'empty') {
+			resize_modal_window($("#add_content"));
+		}
 			
 	});
 	
@@ -75,6 +79,10 @@
 	</div>
 	{% endif %}
 
+	{{ media_form.errors }}
+	{{ picture_form.errors }}
+	{{ content_form.errors }}
+
 	<div id="add_content" class="span-18 last">
 	<div class="projectscontentstitle">{% trans "Create content" %}</div>
 	<form action="{{create_content_action}}" enctype="multipart/form-data" id="my_form" method="POST" enctype="multipart/form-data" >
@@ -95,6 +103,12 @@
 		<div>{{ media_form.external_id.errors }}{{ media_form.external_id.label_tag }}{{media_form.external_id}}</div>
 		<div>{{ media_form.external_publication_url.errors }}{{ media_form.external_publication_url.label_tag }}{{media_form.external_publication_url}}</div>
 		<div id="public">{{ content_form.is_public }}<label>{% trans  "publish for everyone" %}</label></div>
+		
+		<div>
+		{% if iri_id and user.is_staff %}
+		{{ content_form.front_project.label_tag }}{{ content_form.front_project }}
+		{% endif %}
+		</div>
 	</div>
 	<div id="contentright" class="span-9 last" >
 		<div>{{ content_form.external_id.errors }}{{ content_form.external_id.label_tag }}{{content_form.external_id}}</div>
--- a/src/ldt/ldt/ldt_utils/urls.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/urls.py	Mon Jan 16 09:57:38 2012 +0100
@@ -43,6 +43,7 @@
     url(r'^updateGroup/(?P<group_id>.*)$', 'views.group.update_group'),
     url(r'^front/$', 'views.front.front_home'),
     url(r'^front/group/(?P<group_id>.*)$', 'views.front.group_info'),
+    url(r'^front/playerCutting/(?P<content_iri_id>.*)/(?P<cutting_id>.*)/$', 'views.front.annot_content'),
     url(r'^front/player/(?P<content_iri_id>.*)$', 'views.front.annot_content'),
     url(r'^front/search/$', 'views.front.search_index'),
     url(r'^front/searchListing', 'views.front.search_listing'),
--- a/src/ldt/ldt/ldt_utils/utils.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/utils.py	Mon Jan 16 09:57:38 2012 +0100
@@ -171,7 +171,7 @@
         self.to_add = True
         
     #   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"):
+    def add(self, media, cutting_id, cutting_title, title, text, tags_list, begin, dur, author, date, view_id="0", color="2194379"):
         """
         Add an annotation to a project. begin and dur must be strings. Default color is yellow.
         """
@@ -202,7 +202,8 @@
             path_ensemble = lxml.etree.SubElement(path_content[0], 'ensemble')
             path_ensemble.set('id', 'g_' + generate_uuid())
             path_ensemble.set('title', _('Personal cutting'))
-            path_ensemble.set('author', 'undefined')
+            path_ensemble.set('author', 'IRI')
+            path_ensemble.set('abstract', 'IRI')
             path_ensemble = [path_ensemble]
         #else:
         #    path_ensemble = path_content[0].xpath('ensemble')
@@ -264,7 +265,7 @@
             tag_node = lxml.etree.SubElement(tags, 'tag')
             tag_node.text = tag
         
-        return id_annotation
+        return cutting_id, id_annotation
     
     def save(self):
         if self.to_add:
@@ -276,7 +277,7 @@
        self.save()       
             
 
-def create_ldt(project, user):
+def create_ldt(project, user, cuttings=[]):
     """create xml"""
 
     
@@ -311,12 +312,12 @@
             elementMedia.set('video', settings.STREAM_URL)
         elementMedia.set('pict', "")
         elementMedia.set('extra', "")
-
+        
     if not idsel:
         idsel = ""
 
     #node annotations
-    lxml.etree.SubElement(iri, 'annotations')
+    annotations = lxml.etree.SubElement(iri, 'annotations')
     
     #node displays
     elementDisplays = lxml.etree.SubElement(iri, 'displays')
@@ -356,6 +357,26 @@
     #node edits
     lxml.etree.SubElement(iri, 'edits')
     
+    # add cuttings to the first content if necessary
+    if cuttings and contentList:
+        content = contentList[0]
+        
+        content_node = lxml.etree.SubElement(annotations, 'content')
+        content_node.set('id', content.iri_id)
+        ensemble = lxml.etree.SubElement(content_node, 'ensemble')
+        ensemble.set('id', generate_uuid())
+        ensemble.set('author', 'undefined')
+        ensemble.set('abstract', '')
+        
+        for cutting in cuttings:
+            cutting_node = lxml.etree.SubElement(ensemble, 'decoupage')
+            cutting_node.set('author', 'perso')
+            cutting_node.set('id', generate_uuid())
+            title = lxml.etree.SubElement(cutting_node, 'title')
+            title.text = cutting
+            lxml.etree.SubElement(cutting_node, 'abstract')
+            lxml.etree.SubElement(cutting_node, 'elements')
+    
     #write dom in Project.ldt 
     project.ldt = lxml.etree.tostring(iri, pretty_print=True)
     
--- a/src/ldt/ldt/ldt_utils/views/content.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/content.py	Mon Jan 16 09:57:38 2012 +0100
@@ -11,7 +11,7 @@
 from ldt.ldt_utils.forms import ContentForm, MediaForm
 from guardian.shortcuts import remove_perm
 from ldt.ldt_utils.models import Content, Media
-from ldt.security.utils import assign_perm_to_obj, add_change_attr, get_userlist, get_userlist_model, get_userlist_group
+from ldt.security.utils import assign_perm_to_obj, add_change_attr, get_userlist, get_userlist_model
 from ldt.security.cache import cached_assign
 from ldt.user.forms import PictureForm
 from urllib2 import urlparse
@@ -186,7 +186,7 @@
                     
 
             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'):
+                for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title', 'front_project'):
                     setattr(media, attribute, cleaned_data.get(attribute))
                 mimetype = cleaned_data.get('mimetype_field', None)
                 if not mimetype:
@@ -223,6 +223,9 @@
                 if not created:
                     for attribute in ('iriurl', 'title', 'description', 'duration', 'content_creation_date', 'tags', 'media_obj'):
                         setattr(content, attribute, content_defaults[attribute])
+                        
+                    if request.user.is_staff and content_defaults.has_key('front_project'):
+                        content.front_project = content_defaults['front_project']
                 content.save()
                
                 picture_form.model = content
--- a/src/ldt/ldt/ldt_utils/views/front.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/front.py	Mon Jan 16 09:57:38 2012 +0100
@@ -61,7 +61,7 @@
 
 
 @login_required
-def annot_content(request, content_iri_id):
+def annot_content(request, content_iri_id, cutting_id=None):
     # Get the wanted content
     content = Content.objects.get(iri_id=content_iri_id)
     # Get the content src to see if it is a youtube video
@@ -73,7 +73,7 @@
     # Vars for player
     player_id = "player_project_" + proj.ldt_id
     
-    json_url = reverse("ldt.ldt_utils.views.json.project_json_id", args=[proj.ldt_id])
+    json_url = reverse("ldt.ldt_utils.views.json.project_json_cutting_id", args=[proj.ldt_id, cutting_id])
     player_width = 550
     player_height = 380
     stream_mode = proj.stream_mode
--- a/src/ldt/ldt/ldt_utils/views/group.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/group.py	Mon Jan 16 09:57:38 2012 +0100
@@ -20,8 +20,7 @@
         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 = get_objects_for_group(grp, 'ldt_utils.view_project').exclude(title__startswith='front')
     
     project_list = add_change_attr(request.user, project_list)
     
--- a/src/ldt/ldt/ldt_utils/views/json.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/json.py	Mon Jan 16 09:57:38 2012 +0100
@@ -9,30 +9,36 @@
 import ldt.auth as ldt_auth
 from guardian.shortcuts import get_objects_for_user
 
+
+# TODO : for tests only, we use Project.objects
+# should be set to Project.safe_objects for production 
+
 def project_json_id(request, id): 
     
-    project = get_object_or_404(Project.safe_objects, ldt_id=id)
+    project = get_object_or_404(Project.objects, ldt_id=id)
 
     return project_json(request, project, False)
 
 def project_json_cutting_id(request, id, cutting_id):
 
-    project = get_object_or_404(Project.safe_objects, ldt_id=id)
+    project = get_object_or_404(Project.objects, ldt_id=id)
 
     return project_json(request, project, first_cutting=cutting_id)
 
 def project_json_externalid(request, id): 
         
-    res_proj = get_list_or_404(Project.safe_objects.order_by('-modification_date'), contents__external_id=id) #@UndefinedVariable
+    res_proj = get_list_or_404(Project.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, first_cutting=None): # Not checked
+def project_json(request, project, serialize_contents=True, first_cutting=None):
     
-    if not ldt_auth.check_access(request.user, project):
-        return HttpResponseForbidden(_("You can not access this project"))
+# TODO : the following lines have been uncommented for tests only
+# they should not be commented for production
+#    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:
@@ -58,7 +64,8 @@
         escape_bool = {'true': True, 'false': False, "0": False, "1": True}.get(escape_str.lower())
         
     viewable_contents = get_objects_for_user(request.user, 'ldt_utils.view_content', klass=project.contents.all())
-    viewable_contents = [c.iri_id for c in viewable_contents]    
+    viewable_contents = [c.iri_id for c in viewable_contents]
+        
     ps = ProjectSerializer(project, serialize_contents, viewable_contents=viewable_contents, first_cutting=first_cutting)
     project_dict = ps.serialize_to_cinelab()
     
--- a/src/ldt/ldt/ldt_utils/views/project.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/project.py	Mon Jan 16 09:57:38 2012 +0100
@@ -198,6 +198,8 @@
         if len(filter) > 0 and filter[0] == '_':
             filter = filter[1:]
         query &= Q(title__icontains=filter)
+        
+    query &= ~Q(title__startswith='front')
     
     is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
     show_username = True
--- a/src/ldt/ldt/ldt_utils/views/workspace.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/workspace.py	Mon Jan 16 09:57:38 2012 +0100
@@ -32,7 +32,7 @@
     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
+    project_list = add_change_attr(request.user, Project.safe_objects.filter(owner=request.user).exclude(title__startswith='front')) #@UndefinedVariable
 
     is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
     
@@ -74,7 +74,7 @@
 def published_project(request): 
 
     # get list of all published projects
-    project_list = Project.safe_objects.filter(state=2) #@UndefinedVariable
+    project_list = Project.safe_objects.filter(state=2).exclude(title__startswith='front') #@UndefinedVariable
     # Search form
     form = SearchForm()
 
--- a/src/ldt/ldt/security/__init__.py	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/security/__init__.py	Mon Jan 16 09:57:38 2012 +0100
@@ -36,6 +36,13 @@
     get_anonymous_user.anonymous_user = User.objects.get(id=settings.ANONYMOUS_USER_ID)
     return get_anonymous_user.anonymous_user 
 
+def get_current_user_or_admin():
+    current = get_current_user()
+    if current:
+        return current
+    admin = User.objects.filter(is_superuse=True)[0]
+    return admin
+
 def protect_models():
     cls_list = get_models_to_protect()
     if cls_list:
@@ -62,27 +69,27 @@
         
     return cls_list
 
-def protect_model(cls):  
+def protect_model(cls):
+    if not hasattr(cls, 'unsafe_save'):
+        cls.unsafe_save = cls.save
+        cls.unsafe_delete = cls.delete
+        class_name = cls.__name__.lower()
+        cls.save = change_security(class_name)(cls.save)
+        cls.delete = change_security(class_name)(cls.delete)    
     
-    cls.old_save = cls.save
-    cls.old_delete = cls.delete
-    class_name = cls.__name__.lower()
-    cls.save = change_security(class_name)(cls.save)
-    cls.delete = change_security(class_name)(cls.delete)    
-    
-def unprotect_model(cls): 
-    if hasattr(cls, 'old_save'):
-        cls.save = cls.old_save 
-        cls.delete = cls.old_delete 
-        del cls.old_save    
-        del cls.old_delete
+def unprotect_model(cls):     
+    if hasattr(cls, 'unsafe_save'):
+        cls.save = cls.unsafe_save 
+        cls.delete = cls.unsafe_delete 
+        del cls.unsafe_save    
+        del cls.unsafe_delete
         cls.safe_objects.user = None 
         cls.safe_objects.check_perm = False
         
 def change_security(cls_name):
     def wrapper(func):
         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/static/ldt/css/front_home.css	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/static/ldt/css/front_home.css	Mon Jan 16 09:57:38 2012 +0100
@@ -13,6 +13,7 @@
 }
 
 #derniers_medias .li_media {
+    position: relative;
     height: 225px;
     width: 300px;
 }
@@ -22,7 +23,8 @@
     list-style: none;
 }
 .graph_annotation {
-    background: url(./imgs/whitealpha.png); margin:148px -296px; position:absolute;
+    background: url(./imgs/whitealpha.png); position:absolute;
+    z-index: 2; width: 294px; height: 20px; left: 3px; top: 148px;
 }
 
 /* Plus annotés */
@@ -68,4 +70,4 @@
 
 .lock_group {
     background: url(./imgs/lock.png); width: 11px; height: 13px; position: absolute; left: 45px; top: 34px;
-}
\ No newline at end of file
+}
--- a/src/ldt/ldt/static/ldt/js/projectscontents.js	Mon Jan 16 09:56:08 2012 +0100
+++ b/src/ldt/ldt/static/ldt/js/projectscontents.js	Mon Jan 16 09:57:38 2012 +0100
@@ -180,7 +180,7 @@
         filters: ['iframe'],
         sizes: {
             minW: 740,
-            minH: 550
+            minH: 520
         },
         closeOnClick:false,
         callbacks: {
@@ -196,7 +196,7 @@
                 });                
 
                 nm.store.iframe.width(730);
-                nm.store.iframe.height(540);
+                nm.store.iframe.height(510);
             }
         }
     });