Add checksum to media objects
svn: r22870
This commit is contained in:
parent
8d9f6558e5
commit
2d8b44db89
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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))
|
||||||
|
@ -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()
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user