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 from __future__ import with_statement, unicode_literals
import sys import sys
import os
from ..lib.markertype import MarkerType from ..lib.markertype import MarkerType
from ..lib.tag import Tag from ..lib.tag import Tag
from ..utils.file import create_checksum
import time import time
import logging import logging
LOG = logging.getLogger(".citation") LOG = logging.getLogger(".citation")
@ -54,10 +56,11 @@ def gramps_upgrade_17(self):
1. This upgrade adds tags to event, place, repository, source and 1. This upgrade adds tags to event, place, repository, source and
citation objects. citation objects.
2. Data of Source becomes SourceAttributes Secondary Object 2. Data of Source becomes SourceAttributes Secondary Object
3. Add checksum field to media objects.
""" """
length = (len(self.event_map) + len(self.place_map) + length = (len(self.event_map) + len(self.place_map) +
len(self.repository_map) + len(self.source_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) self.set_total(length)
# --------------------------------- # ---------------------------------
@ -166,6 +169,27 @@ def gramps_upgrade_17(self):
txn.put(handle, new_citation) txn.put(handle, new_citation)
self.update() 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. # Bump up database version. Separate transaction to save metadata.
with BSDDBTxn(self.env, self.metadata) as txn: with BSDDBTxn(self.env, self.metadata) as txn:
txn.put(b'version', 17) txn.put(b'version', 17)

View File

@ -86,11 +86,13 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
self.path = source.path self.path = source.path
self.mime = source.mime self.mime = source.mime
self.desc = source.desc self.desc = source.desc
self.checksum = source.checksum
self.thumb = source.thumb self.thumb = source.thumb
else: else:
self.path = "" self.path = ""
self.mime = "" self.mime = ""
self.desc = "" self.desc = ""
self.checksum = ""
self.thumb = None self.thumb = None
def serialize(self, no_text_date = False): def serialize(self, no_text_date = False):
@ -112,6 +114,7 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
:rtype: tuple :rtype: tuple
""" """
return (self.handle, self.gramps_id, self.path, self.mime, self.desc, return (self.handle, self.gramps_id, self.path, self.mime, self.desc,
self.checksum,
AttributeBase.serialize(self), AttributeBase.serialize(self),
CitationBase.serialize(self), CitationBase.serialize(self),
NoteBase.serialize(self), NoteBase.serialize(self),
@ -145,6 +148,7 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
"path": self.path, "path": self.path,
"mime": self.mime, "mime": self.mime,
"desc": self.desc, "desc": self.desc,
"checksum": self.checksum,
"attribute_list": AttributeBase.to_struct(self), "attribute_list": AttributeBase.to_struct(self),
"citation_list": CitationBase.to_struct(self), "citation_list": CitationBase.to_struct(self),
"note_list": NoteBase.to_struct(self), "note_list": NoteBase.to_struct(self),
@ -162,7 +166,7 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
:type data: tuple :type data: tuple
""" """
(self.handle, self.gramps_id, self.path, self.mime, self.desc, (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 date, tag_list, self.private) = data
AttributeBase.unserialize(self, attribute_list) AttributeBase.unserialize(self, attribute_list)
@ -287,3 +291,12 @@ class MediaObject(CitationBase, NoteBase, DateBase, AttributeBase,
def get_description(self): def get_description(self):
"""Return the description of the image.""" """Return the description of the image."""
return self.desc 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 os
import sys import sys
import shutil import shutil
import io
import hashlib
import logging import logging
LOG = logging.getLogger(".gen.utils.file") LOG = logging.getLogger(".gen.utils.file")
@ -294,3 +296,15 @@ def fix_encoding(value, errors='strict'):
return value.decode(encoding=codeset, errors=errors) return value.decode(encoding=codeset, errors=errors)
else: else:
return value 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.lib import MediaObject, MediaRef
from gramps.gen.db import DbTxn from gramps.gen.db import DbTxn
from gramps.gen.utils.file import (media_path_full, media_path, relative_path, 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 ...thumbnails import get_thumbnail_image
from gramps.gen.errors import WindowActiveError from gramps.gen.errors import WindowActiveError
from gramps.gen.mime import get_type, is_valid_type from gramps.gen.mime import get_type, is_valid_type
@ -525,6 +525,9 @@ class GalleryTab(ButtonTab, DbGUIElement):
if not is_valid_type(mime): if not is_valid_type(mime):
return return
photo = MediaObject() 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)) base_dir = cuni(media_path(self.dbstate.db))
if os.path.exists(base_dir): if os.path.exists(base_dir):
name = relative_path(name, 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.db import DbTxn
from gramps.gen.mime import get_description, get_type from gramps.gen.mime import get_description, get_type
from ..thumbnails import get_thumbnail_image, find_mime_type_pixbuf from ..thumbnails import get_thumbnail_image, find_mime_type_pixbuf
from gramps.gen.utils.file import (media_path_full, find_file, from gramps.gen.utils.file import (media_path_full, find_file, create_checksum,
get_unicode_path_from_file_chooser) get_unicode_path_from_file_chooser)
from .editprimary import EditPrimary from .editprimary import EditPrimary
from ..widgets import (MonitoredDate, MonitoredEntry, PrivacyButton, from ..widgets import (MonitoredDate, MonitoredEntry, PrivacyButton,
MonitoredTagList) MonitoredTagList)
@ -263,8 +263,15 @@ class EditMedia(EditPrimary):
fname = self.obj.get_path() fname = self.obj.get_path()
self.file_path.set_text(fname) self.file_path.set_text(fname)
self.determine_mime() self.determine_mime()
self.update_checksum()
self.draw_preview() 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): def save(self, *obj):
self.ok_button.set_sensitive(False) 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.const import THUMBSCALE
from gramps.gen.mime import get_description, get_type from gramps.gen.mime import get_description, get_type
from ..thumbnails import get_thumbnail_image, find_mime_type_pixbuf from ..thumbnails import get_thumbnail_image, find_mime_type_pixbuf
from gramps.gen.utils.file import (media_path_full, find_file, from gramps.gen.utils.file import (media_path_full, find_file, create_checksum,
get_unicode_path_from_file_chooser) get_unicode_path_from_file_chooser)
from gramps.gen.lib import NoteType from gramps.gen.lib import NoteType
from gramps.gen.db import DbTxn from gramps.gen.db import DbTxn
from ..glade import Glade from ..glade import Glade
@ -553,7 +553,14 @@ class EditMediaRef(EditReference):
for obj in (self.descr_window, self.path_obj): for obj in (self.descr_window, self.path_obj):
obj.update() obj.update()
self.determine_mime() self.determine_mime()
self.update_checksum()
self.draw_preview() 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): def select_file(self, val):
self.determine_mime() self.determine_mime()

View File

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

View File

@ -1216,6 +1216,7 @@ class GrampsXmlWriter(UpdateCallback):
mime_type = obj.get_mime_type() mime_type = obj.get_mime_type()
path = obj.get_path() path = obj.get_path()
desc = obj.get_description() desc = obj.get_description()
checksum = obj.get_checksum()
if desc: if desc:
desc_text = ' description="%s"' % self.fix(desc) desc_text = ' description="%s"' % self.fix(desc)
else: else:
@ -1229,9 +1230,9 @@ class GrampsXmlWriter(UpdateCallback):
# Always export path with \ replaced with /. Otherwise import # Always export path with \ replaced with /. Otherwise import
# from Windows to Linux of gpkg's path to images does not work. # from Windows to Linux of gpkg's path to images does not work.
path = path.replace('\\','/') 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), % (" "*(index+1), self.fix(path), self.fix(mime_type),
desc_text)) checksum, desc_text))
self.write_attribute_list(obj.get_attribute_list()) self.write_attribute_list(obj.get_attribute_list())
self.write_note_list(obj.get_note_list(), index+1) self.write_note_list(obj.get_note_list(), index+1)
dval = obj.get_date_object() 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.id import create_id
from gramps.gen.utils.db import family_name from gramps.gen.utils.db import family_name
from gramps.gen.utils.unknown import make_unknown, create_explanation_note 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.datehandler import parser, set_date
from gramps.gen.display.name import displayer as name_displayer from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY, 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): if self.all_abs and not os.path.isabs(src):
self.all_abs = False self.all_abs = False
self.info.add('relative-path', None, None) 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): 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.constfunc import win, cuni
from gramps.gen.config import config from gramps.gen.config import config
from gramps.gen.utils.file import (media_path, relative_path, media_path_full, 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.gen.utils.db import get_media_referents
from gramps.gui.views.bookmarks import MediaBookmarks from gramps.gui.views.bookmarks import MediaBookmarks
from gramps.gen.mime import get_type, is_valid_type from gramps.gen.mime import get_type, is_valid_type
@ -199,6 +199,9 @@ class MediaView(ListView):
if not is_valid_type(mime): if not is_valid_type(mime):
return return
photo = MediaObject() 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)) base_dir = cuni(media_path(self.dbstate.db))
if os.path.exists(base_dir): if os.path.exists(base_dir):
name = relative_path(name, base_dir) name = relative_path(name, base_dir)