diff --git a/apps/mimetype/api.py b/apps/mimetype/api.py index e76a55be65..4e598497a1 100644 --- a/apps/mimetype/api.py +++ b/apps/mimetype/api.py @@ -38,6 +38,7 @@ mimetype_icons = { 'application/vnd.ms-powerpoint': 'file_extension_pps.png', 'application/wav' : 'file_extension_wav.png', 'application/x-wav' : 'file_extension_wav.png', + 'application/vnd.oasis.opendocument.text' : 'ODF_textdocument_32x32.png', 'image/jpeg' : 'file_extension_jpeg.png', 'image/png' : 'file_extension_png.png', @@ -89,7 +90,7 @@ def get_mimetype(filepath): if USE_PYTHON_MAGIC: if os.path.exists(filepath): try: - source = open(filepath, 'r') + source = open(filepath, 'rb') mime = magic.Magic(mime=True) file_mimetype = mime.from_buffer(source.read()) source.seek(0) diff --git a/apps/sources/__init__.py b/apps/sources/__init__.py index b8a4aa65b5..1dbd807eb8 100644 --- a/apps/sources/__init__.py +++ b/apps/sources/__init__.py @@ -7,6 +7,7 @@ from permissions.api import register_permission, set_namespace_title from sources.staging import StagingFile from sources.models import WebForm, StagingFolder, SourceTransformation +from sources.widgets import staging_file_thumbnail PERMISSION_SOURCES_SETUP_VIEW = {'namespace': 'sources_setup', 'name': 'sources_setup_view', 'label': _(u'View existing document sources')} PERMISSION_SOURCES_SETUP_EDIT = {'namespace': 'sources_setup', 'name': 'sources_setup_edit', 'label': _(u'Edit document sources')} @@ -19,7 +20,6 @@ register_permission(PERMISSION_SOURCES_SETUP_EDIT) register_permission(PERMISSION_SOURCES_SETUP_DELETE) register_permission(PERMISSION_SOURCES_SETUP_CREATE) - staging_file_preview = {'text': _(u'preview'), 'class': 'fancybox-noscaling', 'view': 'staging_file_preview', 'args': ['source.source_type', 'source.pk', 'object.id'], 'famfam': 'zoom'} staging_file_delete = {'text': _(u'delete'), 'view': 'staging_file_delete', 'args': ['source.source_type', 'source.pk', 'object.id'], 'famfam': 'delete', 'keep_query': True} @@ -37,7 +37,7 @@ setup_source_transformation_delete = {'text': _(u'delete'), 'view': 'setup_sourc source_list = {'text': _(u'Document sources'), 'view': 'setup_web_form_list', 'famfam': 'page_add', 'children_url_regex': [r'sources/setup']} -register_links(StagingFile, [staging_file_preview, staging_file_delete]) +register_links(StagingFile, [staging_file_delete]) register_links(SourceTransformation, [setup_source_transformation_edit, setup_source_transformation_delete]) @@ -54,3 +54,9 @@ register_links(StagingFolder, [setup_source_transformation_list, setup_source_ed register_links(['setup_source_transformation_create', 'setup_source_transformation_edit', 'setup_source_transformation_delete', 'setup_source_transformation_list'], [setup_source_transformation_create], menu_name='sidebar') source_views = ['setup_web_form_list', 'setup_staging_folder_list', 'setup_source_edit', 'setup_source_delete', 'setup_source_create', 'setup_source_transformation_list', 'setup_source_transformation_edit', 'setup_source_transformation_delete', 'setup_source_transformation_create'] + +register_model_list_columns(StagingFile, [ + {'name':_(u'thumbnail'), 'attribute': + lambda x: staging_file_thumbnail(x) + }, + ]) diff --git a/apps/sources/staging.py b/apps/sources/staging.py index 2ceddc85c5..230eb44dab 100644 --- a/apps/sources/staging.py +++ b/apps/sources/staging.py @@ -7,7 +7,11 @@ from django.core.exceptions import ObjectDoesNotExist from django.utils.translation import ugettext from django.utils.translation import ugettext_lazy as _ +from mimetype.api import get_icon_file_path, get_error_icon_file_path, \ + get_mimetype from converter.api import convert, cache_cleanup +from converter.exceptions import UnknownFormat, UnkownConvertError + DEFAULT_STAGING_DIRECTORY = u'/tmp' @@ -41,10 +45,12 @@ def _return_new_class(): return type('StagingFile', (StagingFile,), dict(StagingFile.__dict__)) -def create_staging_file_class(request, source): +def create_staging_file_class(request, directory_path, source=None): cls = _return_new_class() #cls.set_path(evaluate_user_staging_path(request, source)) - cls.set_path(source) + cls.set_path(directory_path) + if source is not None: + cls.set_source(source) return cls @@ -54,11 +60,16 @@ class StagingFile(object): specifics to the view """ path = DEFAULT_STAGING_DIRECTORY + source = None @classmethod def set_path(cls, path): cls.path = path + @classmethod + def set_source(cls, source): + cls.source = source + @classmethod def get_all(cls): """ @@ -68,7 +79,7 @@ class StagingFile(object): staging_files = [] for filename in get_all_files(cls.path): staging_files.append(StagingFile( - filepath=os.path.join(cls.path, filename))) + filepath=os.path.join(cls.path, filename), source=cls.source)) return staging_files @@ -84,10 +95,13 @@ class StagingFile(object): else: raise ObjectDoesNotExist - def __init__(self, filepath): + def __init__(self, filepath, source=None): + self.source = source self.filepath = filepath self.filename = os.path.basename(filepath) - self._id = HASH_FUNCTION(open(filepath).read()) + fd = open(filepath, 'rb') + self._id = HASH_FUNCTION(fd.read()) + fd.close() def __unicode__(self): return self.filename @@ -121,7 +135,10 @@ class StagingFile(object): else: raise OSError(ugettext(u'Unable to delete staging file: %s') % exc) - def preview(self, preview_size, transformations): - errors = [] - output_file = convert(self.filepath, size=preview_size, cleanup_files=False, transformations=transformations) - return output_file, errors + def get_image(self, size, transformations): + try: + return convert(self.filepath, size=size, cleanup_files=False, transformations=transformations) + except UnknownFormat: + return get_icon_file_path(get_mimetype(self.filepath)) + except UnkownConvertError: + return get_error_icon_file_path() diff --git a/apps/sources/urls.py b/apps/sources/urls.py index 5d6a015f92..969cefd1aa 100644 --- a/apps/sources/urls.py +++ b/apps/sources/urls.py @@ -5,6 +5,7 @@ from sources.models import SOURCE_CHOICE_WEB_FORM, SOURCE_CHOICE_STAGING urlpatterns = patterns('sources.views', url(r'^staging_file/type/(?P\w+)/(?P\d+)/(?P\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'), url(r'^staging_file/type/(?P\w+)/(?P\d+)/(?P\w+)/delete/$', 'staging_file_delete', (), 'staging_file_delete'), + url(r'^staging_file/type/staging_folder/(?P\d+)/(?P\w+)/thumbnail/$', 'staging_file_thumbnail', (), 'staging_file_thumbnail'), url(r'^upload/interactive/(?P\w+)/(?P\d+)/$', 'upload_interactive', (), 'upload_interactive'), url(r'^upload/interactive/$', 'upload_interactive', (), 'upload_interactive'), diff --git a/apps/sources/views.py b/apps/sources/views.py index 3a5b241353..e7decbef3c 100644 --- a/apps/sources/views.py +++ b/apps/sources/views.py @@ -17,6 +17,7 @@ from documents.literals import PERMISSION_DOCUMENT_CREATE from documents.literals import HISTORY_DOCUMENT_CREATED from documents.models import RecentDocument, Document, DocumentType from document_indexing.api import update_indexes +from documents.conf.settings import THUMBNAIL_SIZE from history.api import create_history from metadata.api import save_metadata_list, \ decode_metadata_from_url, metadata_repr_as_list @@ -161,7 +162,7 @@ def upload_interactive(request, source_type=None, source_id=None): elif source_type == SOURCE_CHOICE_STAGING: staging_folder = get_object_or_404(StagingFolder, pk=source_id) context['source'] = staging_folder - StagingFile = create_staging_file_class(request, staging_folder.folder_path) + StagingFile = create_staging_file_class(request, staging_folder.folder_path, source=staging_folder) if request.method == 'POST': form = StagingDocumentForm(request.POST, request.FILES, cls=StagingFile, document_type=document_type, @@ -290,32 +291,38 @@ def staging_file_preview(request, source_type, source_id, staging_file_id): check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE]) staging_folder = get_object_or_404(StagingFolder, pk=source_id) StagingFile = create_staging_file_class(request, staging_folder.folder_path) - try: - transformations, errors=SourceTransformation.objects.get_for_object_as_list(staging_folder) - - output_file, errors = StagingFile.get(staging_file_id).preview( - preview_size=staging_folder.get_preview_size(), - transformations=transformations - ) - if errors and (request.user.is_staff or request.user.is_superuser): - for error in errors: - messages.warning(request, _(u'Staging file transformation error: %(error)s') % { - 'error': error - }) + transformations, errors = SourceTransformation.objects.get_for_object_as_list(staging_folder) + + output_file = StagingFile.get(staging_file_id).get_image( + size=staging_folder.get_preview_size(), + transformations=transformations + ) + if errors and (request.user.is_staff or request.user.is_superuser): + for error in errors: + messages.warning(request, _(u'Staging file transformation error: %(error)s') % { + 'error': error + }) - except UnkownConvertError, e: - if request.user.is_staff or request.user.is_superuser: - messages.error(request, e) + return sendfile.sendfile(request, output_file) - output_file = os.path.join(settings.MEDIA_ROOT, u'images', PICTURE_ERROR_MEDIUM) - except UnknownFormat: - output_file = os.path.join(settings.MEDIA_ROOT, u'images', PICTURE_UNKNOWN_MEDIUM) - except Exception, e: - if request.user.is_staff or request.user.is_superuser: - messages.error(request, e) - output_file = os.path.join(settings.MEDIA_ROOT, u'images', PICTURE_ERROR_MEDIUM) - finally: - return sendfile.sendfile(request, output_file) + +def staging_file_thumbnail(request, source_id, staging_file_id): + check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE]) + staging_folder = get_object_or_404(StagingFolder, pk=source_id) + StagingFile = create_staging_file_class(request, staging_folder.folder_path, source=staging_folder) + transformations, errors = SourceTransformation.objects.get_for_object_as_list(staging_folder) + + output_file = StagingFile.get(staging_file_id).get_image( + size=THUMBNAIL_SIZE, + transformations=transformations + ) + if errors and (request.user.is_staff or request.user.is_superuser): + for error in errors: + messages.warning(request, _(u'Staging file transformation error: %(error)s') % { + 'error': error + }) + + return sendfile.sendfile(request, output_file) def staging_file_delete(request, source_type, source_id, staging_file_id): diff --git a/apps/sources/widgets.py b/apps/sources/widgets.py index 01626a9b4b..0bb5b02ac2 100644 --- a/apps/sources/widgets.py +++ b/apps/sources/widgets.py @@ -1,6 +1,9 @@ from django import forms from django.utils.safestring import mark_safe from django.utils.encoding import force_unicode +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ +from django.core.urlresolvers import reverse class FamFamRadioFieldRenderer(forms.widgets.RadioFieldRenderer): @@ -20,3 +23,15 @@ class FamFamRadioFieldRenderer(forms.widgets.RadioFieldRenderer): class FamFamRadioSelect(forms.widgets.RadioSelect): renderer = FamFamRadioFieldRenderer + + +def staging_file_thumbnail(staging_file): + #try: + return mark_safe(u'%(string)s' % { + 'url': reverse('staging_file_preview', args=[staging_file.source.source_type, staging_file.source.pk, staging_file.id]), + 'thumbnail': reverse('staging_file_thumbnail', args=[staging_file.source.pk, staging_file.id]), + 'media_url': settings.MEDIA_URL, + 'string': _(u'thumbnail') + }) +# except: +# return u''