Add checksum to media objects

svn: r22870
This commit is contained in:
Nick Hall 2013-08-15 17:49:51 +00:00
parent 8d9f6558e5
commit 2d8b44db89
10 changed files with 98 additions and 17 deletions

View File

@ -24,8 +24,10 @@
from __future__ import with_statement, unicode_literals
import sys
import os
from ..lib.markertype import MarkerType
from ..lib.tag import Tag
from ..utils.file import create_checksum
import time
import logging
LOG = logging.getLogger(".citation")
@ -54,10 +56,11 @@ def gramps_upgrade_17(self):
1. This upgrade adds tags to event, place, repository, source and
citation objects.
2. Data of Source becomes SourceAttributes Secondary Object
3. Add checksum field to media objects.
"""
length = (len(self.event_map) + len(self.place_map) +
len(self.repository_map) + len(self.source_map) +
len(self.citation_map))
len(self.citation_map) + len(self.media_map))
self.set_total(length)
# ---------------------------------
@ -166,6 +169,27 @@ def gramps_upgrade_17(self):
txn.put(handle, new_citation)
self.update()
# ---------------------------------
# Modify Media
# ---------------------------------
# Add new checksum field.
base_path = self.metadata[b'mediapath']
for handle in self.media_map.keys():
media = self.media_map[handle]
new_media = list(media)
if os.path.isabs(new_media[2]):
full_path = new_media[2]
else:
full_path = os.path.join(base_path, new_media[2])
checksum = create_checksum(full_path)
new_media = new_media[:5] + [checksum] + new_media[5:]
new_media = tuple(new_media)
with BSDDBTxn(self.env, self.media_map) as txn:
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_media)
self.update()
# Bump up database version. Separate transaction to save metadata.
with BSDDBTxn(self.env, self.metadata) as txn:
txn.put(b'version', 17)

View File

@ -86,11 +86,13 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
self.path = source.path
self.mime = source.mime
self.desc = source.desc
self.checksum = source.checksum
self.thumb = source.thumb
else:
self.path = ""
self.mime = ""
self.desc = ""
self.checksum = ""
self.thumb = None
def serialize(self, no_text_date = False):
@ -112,6 +114,7 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
:rtype: tuple
"""
return (self.handle, self.gramps_id, self.path, self.mime, self.desc,
self.checksum,
AttributeBase.serialize(self),
CitationBase.serialize(self),
NoteBase.serialize(self),
@ -145,6 +148,7 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
"path": self.path,
"mime": self.mime,
"desc": self.desc,
"checksum": self.checksum,
"attribute_list": AttributeBase.to_struct(self),
"citation_list": CitationBase.to_struct(self),
"note_list": NoteBase.to_struct(self),
@ -162,7 +166,7 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
:type data: tuple
"""
(self.handle, self.gramps_id, self.path, self.mime, self.desc,
attribute_list, citation_list, note_list, self.change,
self.checksum, attribute_list, citation_list, note_list, self.change,
date, tag_list, self.private) = data
AttributeBase.unserialize(self, attribute_list)
@ -287,3 +291,12 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
def get_description(self):
"""Return the description of the image."""
return self.desc
def set_checksum(self, text):
"""Set the checksum of the image."""
self.checksum = text
def get_checksum(self):
"""Return the checksum of the image."""
return self.checksum

View File

@ -34,6 +34,8 @@ File and folder related utility functions
import os
import sys
import shutil
import io
import hashlib
import logging
LOG = logging.getLogger(".gen.utils.file")
@ -294,3 +296,15 @@ def fix_encoding(value, errors='strict'):
return value.decode(encoding=codeset, errors=errors)
else:
return value
def create_checksum(full_path):
"""
Create a md5 hash for the given file.
"""
full_path = os.path.normpath(full_path)
try:
with io.open(full_path, 'rb') as media_file:
md5sum = hashlib.md5(media_file.read()).hexdigest()
except IOError:
md5sum = ''
return md5sum

View File

@ -64,7 +64,7 @@ from gramps.gen.constfunc import cuni
from gramps.gen.lib import MediaObject, MediaRef
from gramps.gen.db import DbTxn
from gramps.gen.utils.file import (media_path_full, media_path, relative_path,
fix_encoding)
fix_encoding, create_checksum)
from ...thumbnails import get_thumbnail_image
from gramps.gen.errors import WindowActiveError
from gramps.gen.mime import get_type, is_valid_type
@ -525,6 +525,9 @@ class GalleryTab(ButtonTab, DbGUIElement):
if not is_valid_type(mime):
return
photo = MediaObject()
self.uistate.set_busy_cursor(True)
photo.set_checksum(create_checksum(name))
self.uistate.set_busy_cursor(False)
base_dir = cuni(media_path(self.dbstate.db))
if os.path.exists(base_dir):
name = relative_path(name, base_dir)

View File

@ -49,8 +49,8 @@ from gramps.gen.lib import MediaObject, NoteType
from gramps.gen.db import DbTxn
from gramps.gen.mime import get_description, get_type
from ..thumbnails import get_thumbnail_image, find_mime_type_pixbuf
from gramps.gen.utils.file import (media_path_full, find_file,
get_unicode_path_from_file_chooser)
from gramps.gen.utils.file import (media_path_full, find_file, create_checksum,
get_unicode_path_from_file_chooser)
from .editprimary import EditPrimary
from ..widgets import (MonitoredDate, MonitoredEntry, PrivacyButton,
MonitoredTagList)
@ -263,8 +263,15 @@ class EditMedia(EditPrimary):
fname = self.obj.get_path()
self.file_path.set_text(fname)
self.determine_mime()
self.update_checksum()
self.draw_preview()
def update_checksum(self):
self.uistate.set_busy_cursor(True)
media_path = media_path_full(self.dbstate.db, self.obj.get_path())
self.obj.set_checksum(create_checksum(os.path.normpath(media_path)))
self.uistate.set_busy_cursor(False)
def save(self, *obj):
self.ok_button.set_sensitive(False)

View File

@ -49,8 +49,8 @@ from ..utils import open_file_with_default_application
from gramps.gen.const import THUMBSCALE
from gramps.gen.mime import get_description, get_type
from ..thumbnails import get_thumbnail_image, find_mime_type_pixbuf
from gramps.gen.utils.file import (media_path_full, find_file,
get_unicode_path_from_file_chooser)
from gramps.gen.utils.file import (media_path_full, find_file, create_checksum,
get_unicode_path_from_file_chooser)
from gramps.gen.lib import NoteType
from gramps.gen.db import DbTxn
from ..glade import Glade
@ -553,7 +553,14 @@ class EditMediaRef(EditReference):
for obj in (self.descr_window, self.path_obj):
obj.update()
self.determine_mime()
self.update_checksum()
self.draw_preview()
def update_checksum(self):
self.uistate.set_busy_cursor(True)
media_path = media_path_full(self.dbstate.db, self.source.get_path())
self.source.set_checksum(create_checksum(os.path.normpath(media_path)))
self.uistate.set_busy_cursor(False)
def select_file(self, val):
self.determine_mime()

View File

@ -137,9 +137,9 @@ class MediaModel(FlatBaseModel):
return cuni(data[1])
def column_date(self,data):
if data[9]:
if data[10]:
date = Date()
date.unserialize(data[9])
date.unserialize(data[10])
return cuni(displayer.display(date))
return ''
@ -156,17 +156,17 @@ class MediaModel(FlatBaseModel):
return cuni(data[0])
def column_private(self, data):
if data[11]:
if data[12]:
return 'gramps-lock'
else:
# There is a problem returning None here.
return ''
def sort_change(self,data):
return "%012x" % data[8]
return "%012x" % data[9]
def column_change(self,data):
return format_time(data[8])
return format_time(data[9])
def column_tooltip(self,data):
return cuni('Media tooltip')
@ -183,7 +183,7 @@ class MediaModel(FlatBaseModel):
"""
tag_color = "#000000000000"
tag_priority = None
for handle in data[10]:
for handle in data[11]:
tag = self.db.get_tag_from_handle(handle)
this_priority = tag.get_priority()
if tag_priority is None or this_priority < tag_priority:
@ -195,5 +195,5 @@ class MediaModel(FlatBaseModel):
"""
Return the sorted list of tags.
"""
tag_list = list(map(self.get_tag_name, data[10]))
tag_list = list(map(self.get_tag_name, data[11]))
return ', '.join(sorted(tag_list, key=glocale.sort_key))

View File

@ -1216,6 +1216,7 @@ class GrampsXmlWriter(UpdateCallback):
mime_type = obj.get_mime_type()
path = obj.get_path()
desc = obj.get_description()
checksum = obj.get_checksum()
if desc:
desc_text = ' description="%s"' % self.fix(desc)
else:
@ -1229,9 +1230,9 @@ class GrampsXmlWriter(UpdateCallback):
# Always export path with \ replaced with /. Otherwise import
# from Windows to Linux of gpkg's path to images does not work.
path = path.replace('\\','/')
self.g.write('%s<file src="%s" mime="%s"%s/>\n'
self.g.write('%s<file src="%s" mime="%s" checksum="%s"%s/>\n'
% (" "*(index+1), self.fix(path), self.fix(mime_type),
desc_text))
checksum, desc_text))
self.write_attribute_list(obj.get_attribute_list())
self.write_note_list(obj.get_note_list(), index+1)
dval = obj.get_date_object()

View File

@ -62,6 +62,7 @@ from gramps.gen.errors import GrampsImportError
from gramps.gen.utils.id import create_id
from gramps.gen.utils.db import family_name
from gramps.gen.utils.unknown import make_unknown, create_explanation_note
from gramps.gen.utils.file import create_checksum
from gramps.gen.datehandler import parser, set_date
from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY,
@ -1603,6 +1604,14 @@ class GrampsParser(UpdateCallback):
if self.all_abs and not os.path.isabs(src):
self.all_abs = False
self.info.add('relative-path', None, None)
if 'checksum' in attrs:
self.object.checksum = attrs['checksum']
else:
if os.path.isabs(src):
full_path = src
else:
full_path = os.path.join(self.mediapath, src)
self.object.checksum = create_checksum(full_path)
def start_childof(self, attrs):
"""

View File

@ -63,7 +63,7 @@ from gramps.gui.views.treemodels import MediaModel
from gramps.gen.constfunc import win, cuni
from gramps.gen.config import config
from gramps.gen.utils.file import (media_path, relative_path, media_path_full,
fix_encoding)
fix_encoding, create_checksum)
from gramps.gen.utils.db import get_media_referents
from gramps.gui.views.bookmarks import MediaBookmarks
from gramps.gen.mime import get_type, is_valid_type
@ -199,6 +199,9 @@ class MediaView(ListView):
if not is_valid_type(mime):
return
photo = MediaObject()
self.uistate.set_busy_cursor(True)
photo.set_checksum(create_checksum(name))
self.uistate.set_busy_cursor(False)
base_dir = cuni(media_path(self.dbstate.db))
if os.path.exists(base_dir):
name = relative_path(name, base_dir)