Re- wrote the entire save_metadata() function. Still have a couple little irritating issues, but I will work them out too soon.

svn: r18040
This commit is contained in:
Rob G. Healey 2011-08-17 07:08:31 +00:00
parent 41d3ab4d58
commit f90367ad86

View File

@ -98,7 +98,6 @@ def _parse_datetime(value):
"""
Parse date and time and return a datetime object.
"""
value = value.rstrip()
if not value:
return None
@ -150,6 +149,7 @@ _validconvert = [_("<-- Image Types -->"), ".bmp", ".jpg", ".png", ".tiff"]
# set up Exif keys for Image Exif metadata keypairs
_DATAMAP = {
None : "MediaTitle",
"Exif.Image.ImageDescription" : "Description",
"Exif.Photo.DateTimeOriginal" : "Original",
"Exif.Image.DateTime" : "Modified",
@ -169,20 +169,13 @@ _DATAMAP.update( (val, key) for key, val in _DATAMAP.items() )
# define tooltips for all data entry fields
_TOOLTIPS = {
# Edit Message Area
"EditMessage" : _("Display area for Editing Area"),
# Media Object Title
# Media Object's Title
"MediaTitle" : _("Warning: Changing this entry will update the Media "
"object title field in Gramps not Exiv2 metadata."),
# Description
"Description" : _("Provide a short descripion for this image."),
# Last Change/ Modify Date/ Time
"Modified" : _("This is the date/ time that the image was last changed/ modified.\n"
"Example: 2011-05-24 14:30:00"),
# Artist
"Artist" : _("Enter the Artist/ Author of this image. The person's name or "
"the company who is responsible for the creation of this image."),
@ -194,6 +187,10 @@ _TOOLTIPS = {
"Original" : _("The original date/ time when the image was first created/ taken as in a photograph.\n"
"Example: 1830-01-1 09:30:59"),
# Last Change/ Modify Date/ Time
"Modified" : _("This is the date/ time that the image was last changed/ modified.\n"
"Example: 2011-05-24 14:30:00"),
# GPS Latitude coordinates
"Latitude" : _("Enter the Latitude GPS coordinates for this image,\n"
"Example: 43.722965, 43 43 22 N, 38° 38 03″ N, 38 38 3"),
@ -254,7 +251,6 @@ class EditExifMetadata(Gramplet):
"""
self.exif_widgets = {}
self.dates = {}
self.coordinates = {}
self.orig_image, self.plugin_image, self.image_path = [False]*3
vbox = self.__build_gui()
@ -345,7 +341,7 @@ class EditExifMetadata(Gramplet):
for (widget, text, callback, icon, is_sensitive) in [
("Help", False, [self.__help_page], gtk.STOCK_HELP, True),
("Edit", False, [self.display_edit], gtk.STOCK_EDIT, False),
("Delete", False, [self.__wipe_dialog], gtk.STOCK_DELETE, False) ]:
("Delete", False, [self._wipe_dialog], gtk.STOCK_DELETE, False) ]:
button = self.__create_button(
widget, text, callback, icon, is_sensitive)
@ -1090,8 +1086,6 @@ class EditExifMetadata(Gramplet):
event_box = self.__create_event_entry(widget, 141, 30, 0, "Validate", [self.validate_coordinate])
vbox2.pack_start(event_box, expand =False, fill =False, padding =0)
self.coordinates[widget] = None
# Help, Save, Clear, Copy, and Close buttons...
new_hbox = gtk.HBox(False, 0)
main_vbox.pack_start(new_hbox, expand =False, fill =True, padding =5)
@ -1128,6 +1122,25 @@ class EditExifMetadata(Gramplet):
else:
self.dates[field] = None
def dates4saving(self, exif_dt):
"""
Creates a date format that is appropriate for saving in pyexiv2 date keys
"""
if isinstance(exif_dt, datetime.datetime):
pass
else:
exif_dt = _parse_datetime(exif_dt)
if exif_dt is None:
return None
if exif_dt.year < 1900:
return "%04d:%02d:%02d %02d:%02d:%02d" % (
exif_dt.year, exif_dt.month, exif_dt.day,
exif_dt.hour, exif_dt.minute, exif_dt.second)
else:
return exif_dt
def validate_datetime(self, widget, data, field):
"""
Validate current date and time in text entry
@ -1139,22 +1152,26 @@ class EditExifMetadata(Gramplet):
"""
Validate current latitude or longitude in text entry
"""
# validate the Latitude field...
if field == "Latitude" and not conv_lat_lon(data, "0", "ISO-D"):
return ValidationError(_(u"Invalid latitude (syntax: 18\u00b09'") +
_('48.21"S, -18.2412 or -18:9:48.21)'))
# validate the Longitude field...
if field == "Longitude" and not conv_lat_lon("0", data, "ISO-D"):
return ValidationError(_(u"Invalid longitude (syntax: 18\u00b09'") +
_('48.21"E, -18.2412 or -18:9:48.21)'))
def __wipe_dialog(self, object):
def _wipe_dialog(self, object):
"""
Handles the Delete Dialog...
"""
QuestionDialog(_("Edit Image Exif Metadata"), _("WARNING! You are about to completely "
"delete the Exif metadata from this image?"), _("Delete"),
self.strip_metadata)
"delete the Exif metadata from this image?"), gtk.STOCK_DELETE, self.strip_metadata)
def _get_value(self, key):
self.update()
def __get_value(self, key):
"""
gets the value from the Exif Key, and returns it...
@ -1189,7 +1206,7 @@ class EditExifMetadata(Gramplet):
for key in mediadatatags:
widget = _DATAMAP[key]
tag_value = self._get_value(key)
tag_value = self.__get_value(key)
if widget in ["Description", "Artist", "Copyright"]:
if tag_value:
@ -1213,7 +1230,7 @@ class EditExifMetadata(Gramplet):
# LatitudeRef, Latitude, LongitudeRef, Longitude...
elif widget == "Latitude":
latitude, longitude = tag_value, self._get_value(_DATAMAP["Longitude"])
latitude, longitude = tag_value, self.__get_value(_DATAMAP["Longitude"])
# if latitude and longitude exist, display them?
if (latitude and longitude):
@ -1230,10 +1247,10 @@ class EditExifMetadata(Gramplet):
if (not latfail and not longfail):
# Latitude Direction Reference
latref = self._get_value(_DATAMAP["LatitudeRef"] )
latref = self.__get_value(_DATAMAP["LatitudeRef"] )
# Longitude Direction Reference
longref = self._get_value(_DATAMAP["LongitudeRef"] )
longref = self.__get_value(_DATAMAP["LongitudeRef"] )
# set display for Latitude GPS coordinates
latitude = """%s° %s %s%s""" % (latdeg, latmin, latsec, latref)
@ -1248,7 +1265,7 @@ class EditExifMetadata(Gramplet):
elif widget == "Altitude":
altitude = tag_value
altref = self._get_value(_DATAMAP["AltitudeRef"])
altref = self.__get_value(_DATAMAP["AltitudeRef"])
if (altitude and altref):
altitude = convert_value(altitude)
@ -1267,25 +1284,6 @@ class EditExifMetadata(Gramplet):
self.media_title = self.orig_image.get_description()
self.exif_widgets["MediaTitle"].set_text(self.media_title)
def _set_value(self, key, widgetvalue):
"""
sets the value for the metadata keys
"""
if OLD_API:
self.plugin_image[key] = widgetvalue
valid = True
else:
try:
self.plugin_image[key].value = widgetvalue
valid = True
except KeyError:
self.plugin_image[key] = pyexiv2.ExifTag(key, widgetvalue)
valid = True
except (ValueError, AttributeError):
pass
valid = False
def write_metadata(self, plugininstance):
"""
writes the Exif metadata to the image.
@ -1317,7 +1315,7 @@ class EditExifMetadata(Gramplet):
for display only
"""
if (not latitude and not longitude):
if (not latitude or not longitude):
return [False]*2
latitude, longitude = self.convert_format(latitude, longitude, "DEG-:")
@ -1329,92 +1327,100 @@ class EditExifMetadata(Gramplet):
gets the information from the plugin data fields
and sets the key = widgetvaluee image metadata
"""
db = self.dbstate.db
addon_widgets = [(widget) for widget in _TOOLTIPS.keys() if widget not in ["MediaTitle", "EditMessage"] ]
# set up default variables...
db = self.dbstate.db
valid = 0
latref, longref, altref = [False]*3
# get all data field values...
mediatitle = self.exif_widgets["MediaTitle"].get_text()
description = self.exif_widgets["Description"].get_text()
artist = self.exif_widgets["Artist"].get_text()
copyright = self.exif_widgets["Copyright"].get_text()
# special variables have been set up for the dates...
original = self.exif_widgets["Original"].get_text()
if original:
original = _parse_datetime(original)
modified = datetime.datetime.now()
latitude = self.exif_widgets["Latitude"].get_text()
longitude = self.exif_widgets["Longitude"].get_text()
altitude = self.exif_widgets["Altitude"].get_text()
mediadatatags = (len(description) +
len(artist) +
len(copyright) +
len(latitude) +
len(longitude) +
len(altitude) )
if not mediadatatags:
widgets = ["MediaTitle", "Description", "Artist", "Copyright", "Original", "Modified",
"Latitude", "Longitude", "Altitude"]
values = [mediatitle, description, artist, copyright, original, modified, latitude, longitude, altitude]
for widgetname in addon_widgets:
self._set_value(_DATAMAP[widgetname], '')
namevalues = list(zip(widgets, values))
namevalues = [(w, v) for w, v in namevalues if v]
# set Edit Message to Cleared...
self.exif_widgets["EditMessage"].set_text(_("All Exif metadata has been cleared..."))
if namevalues:
for widgetname, widgetvalue in namevalues:
key = _DATAMAP[widgetname]
else:
for widgetname in addon_widgets:
# Media Object's Title...
# this will only affect the Media object from wthin the database...
if widgetname == "MediaTitle":
if (self.media_title and self.media_title is not mediatitle):
with DbTxn(_("Media Title Update"), db) as trans:
self.orig_image.set_description(mediatitle)
# Update dynamically updated Modified field...
if widgetname == "Modified":
modified = datetime.datetime.now()
self.exif_widgets[widgetname].set_text(format_datetime(modified) )
self.set_datetime(self.exif_widgets[widgetname], widgetname)
db.commit_media_object(self.orig_image, trans)
db.request_rebuild()
# Original Date/ Time...
# original date of image...
elif widgetname == "Original":
# modify the media object date if it is not already set?
mediaobj_date = self.orig_image.get_date_object()
if mediaobj_date.is_empty():
objdate_ = Date()
if isinstance(original, datetime.datetime):
try:
objdate_.set_yr_mon_day(original.year,
original.month,
original.day )
except ValueError:
objdate_ = False
elif isinstance(original, str):
try:
year, month, day = original.split(":", 3)
objdate_.set_yr_mon_day(year,
month,
day )
except ValueError:
objdate_ = False
if original:
mediaobj_date = self.orig_image.get_date_object()
if mediaobj_date.is_empty():
objdate_ = Date()
else:
objdate_ = False
if objdate_:
original = self.dates4saving(original)
if original:
if isinstance(original, datetime.datetime):
try:
objdate_.set_yr_mon_day(original.year,
original.month,
original.day)
except ValueError:
objdate_ = False
# begin database tranaction to save media object's date...
with DbTxn(_("Create Date Object"), db) as trans:
self.orig_image.set_date_object(objdate_)
db.commit_media_object(self.orig_image, trans)
db.request_rebuild()
elif isinstance(original, str):
try:
year, month, day = original.split(":", 3)
# Latitude/ Longitude...
objdate_.set_yr_mon_day(year, month, day)
except ValueError:
objdate_ = False
else:
objdate_ = False
if objdate_:
with DbTxn(_("Media Object Date Updated"), db) as trans:
self.orig_image.set_date_object(objdate_)
db.commit_media_object(self.orig_image, trans)
db.request_rebuild()
self.set_datetime(self.exif_widgets[widgetname], widgetname)
# Latitude Reference, Latitude, Longitude Reference, and Longitude...
# if equal to None, then convert failed?
elif widgetname == "Latitude":
latitude = self.exif_widgets["Latitude"].get_text()
longitude = self.exif_widgets["Longitude"].get_text()
if (latitude and longitude):
latitude, longitude = self.convert2dms(latitude, longitude)
if (latitude and longitude):
latref = "N"
latref = 'N'
if "-" in latitude:
latref = "S"
latitude = latitude.replace("-", "")
longref = "E"
longref = 'E'
if "-" in longitude:
longref = "W"
longitude = longitude.replace("-", "")
@ -1422,66 +1428,56 @@ class EditExifMetadata(Gramplet):
# convert Latitude/ Longitude into pyexiv2.Rational()...
latitude = coords_to_rational(latitude)
longitude = coords_to_rational(longitude)
# Altitude, and Altitude Reference...
# Altitude Reference, and Altitude...
elif widgetname == "Altitude":
if altitude:
if "-" in altitude:
altitude = altitude.replace("-", "")
altituderef = "1"
else:
altituderef = "0"
altref = '0'
if "-" in widgetvalue:
widgetvalue = widgetvalue.replace("-", "")
altref = "1"
# convert altitude to pyexiv2.Rational for saving...
altitude = altitude2rational(altitude)
else:
altituderef = ''
# convert altitude to pyexiv2.Rational for saving...
altitude = altitude2rational(widgetvalue)
elif widgetname == "MediaTitle":
if (self.media_title and self.media_title is not mediatitle):
with DbTxn(_("Media Title Update"), db) as trans:
self.orig_image.set_description(mediatitle)
# get all values for fields to be saved...
# except for MediaTitle which is handled above...
widgets = ["Description", "Artist", "Copyright", "Original", "Modified", "Latitude", "Longitude", "Altitude"]
values = [description, artist, copyright, original, modified, latitude, longitude, altitude]
db.commit_media_object(self.orig_image, trans)
db.request_rebuild()
namevalues = list(zip(widgets, values))
namevalues = [(w, v) for w, v in namevalues if v]
if namevalues:
for widgetname, widgetvalue in namevalues:
key = _DATAMAP[widgetname]
valid = _set_value(self.plugin_image, key, widgetvalue)
# Description
self._set_value(_DATAMAP["Description"], description)
# save all References for (Latitude, Longitude, and Altitude)...
widgets = ["LatitudeRef", "LongitudeRef", "AltitudeRef"]
values = [latref, longref, altref]
# Artist
self._set_value(_DATAMAP["Artist"], artist)
namevalues = list(zip(widgets, values))
namevalues = [(w, v) for w, v in namevalues if v]
if namevalues:
for widgetname, widgetvalue in namevalues:
key = _DATAMAP[widgetname]
valid = _set_value(self.plugin_image, key, widgetvalue)
# Copyright
self._set_value(_DATAMAP["Copyright"], copyright)
# if valid is in [1, 2, 3], then we write to image?
# see _set_value() for further information...
if valid in xrange(1, 4):
# Modified and Original Dates if not None?
for widgetname in ["Modified", "Original"]:
self._set_value(_DATAMAP[widgetname], self.dates[widgetname] if not None else '')
# Latitude Reference, Latitude, Longitude Reference, and Longitude...
# if equal to None, then convert failed?
if (not latitude and not longitude):
self._set_value(_DATAMAP["LatitudeRef"], '')
self._set_value(_DATAMAP["Latitude"], '')
self._set_value(_DATAMAP["LongitudeRef"], '')
self._set_value(_DATAMAP["Longitude"], '')
else:
self._set_value(_DATAMAP["LatitudeRef"], latref)
self._set_value(_DATAMAP["Latitude"], latitude)
self._set_value(_DATAMAP["LongitudeRef"], longref)
self._set_value(_DATAMAP["Longitude"], longitude)
# Altitude Reference and Altitude
self._set_value(_DATAMAP["AltitudeRef"], altituderef)
self._set_value(_DATAMAP["Altitude"], altitude)
# Update dynamically created Modified date...
modified = datetime.datetime.now()
self.exif_widgets["Modified"].set_text(format_datetime(modified))
# set Edit Message to Saved...
self.exif_widgets["EditMessage"].set_text(_("Saving Exif metadata to this image..."))
# writes all Exif Metadata to image even if the fields are all empty so as to remove the value...
self.write_metadata(self.plugin_image)
# writes/ saves only the fields that have values...
self.write_metadata(self.plugin_image)
# update the display...
self.update()
def strip_metadata(self, mediadatatags =None):
"""
@ -1576,3 +1572,27 @@ def _get_exif_keypairs(plugin_image):
else plugin_image.exif_keys) ]
else:
return False
def _set_value(plugininstance, key, widgetvalue_):
"""
sets the value for the metadata keys
"""
if not plugininstance:
return False
valid = 0
try:
if OLD_API:
plugininstance[key] = widgetvalue_
valid = 1
else:
plugininstance[key].value = widgetvalue_
valid = 2
except KeyError:
plugininstance[key] = pyexiv2.ExifTag(key, widgetvalue_)
valid = 3
except (ValueError, AttributeError):
valid = 4
print(key, widgetvalue_, valid)
return valid