Fixed multiple date/ time issues. Thank you, Nick Hall.

svn: r17386
This commit is contained in:
Rob G. Healey 2011-05-03 06:47:17 +00:00
parent eb533c8ecc
commit 0754b5d653

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
@ -28,7 +27,8 @@
# ***************************************************************************** # *****************************************************************************
import os, sys import os, sys
from datetime import datetime, date from datetime import datetime, date
import time, calendar import calendar, time
# abilty to escape certain characters from output... # abilty to escape certain characters from output...
from xml.sax.saxutils import escape as _html_escape from xml.sax.saxutils import escape as _html_escape
@ -165,7 +165,7 @@ _TOOLTIPS = {
# set up Exif keys for Image.exif_keys # set up Exif keys for Image.exif_keys
_DATAMAP = { _DATAMAP = {
"Exif.Image.ImageDescription" : "Description", "Exif.Image.ImageDescription" : "Description",
"Exif.Image.DateTime" : "ModDateTime", "Exif.Image.DateTime" : "Modified",
"Exif.Image.Artist" : "Artist", "Exif.Image.Artist" : "Artist",
"Exif.Image.Copyright" : "Copyright", "Exif.Image.Copyright" : "Copyright",
"Exif.Photo.DateTimeOriginal" : "DateTime", "Exif.Photo.DateTimeOriginal" : "DateTime",
@ -234,29 +234,6 @@ def _return_month(month):
break break
return month return month
def _split_values(text):
"""
splits a variable into its pieces
"""
# a hypen
if "-" in text:
separator = "-"
# a period
elif "." in text:
separator = "."
# a colon
elif ":" in text:
separator = ":"
# a space
else:
separator = " "
return [value for value in text.split(separator)]
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------
# Gramplet class # Gramplet class
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------
@ -276,6 +253,16 @@ class EditExifMetadata(Gramplet):
self.MediaDataTags = False self.MediaDataTags = False
self.connect_signal("Media", self.update) self.connect_signal("Media", self.update)
vbox = self.build_gui()
self.gui.get_container_widget().remove(self.gui.textview)
self.gui.get_container_widget().add_with_viewport(vbox)
vbox.show_all()
# provide tooltips for all fields and buttons...
_setup_widget_tooltips(self.exif_widgets)
def build_gui(self):
vbox = gtk.VBox() vbox = gtk.VBox()
@ -330,6 +317,9 @@ class EditExifMetadata(Gramplet):
# Image Description # Image Description
("Description", _("Description"), None, False, [], True, 0), ("Description", _("Description"), None, False, [], True, 0),
# Last Modified Date/ Time
("Modified", _("Last Changed"), None, True, [], True, 0),
# Artist field # Artist field
("Artist", _("Artist"), None, False, [], True, 0), ("Artist", _("Artist"), None, False, [], True, 0),
@ -372,18 +362,13 @@ class EditExifMetadata(Gramplet):
if _MAGICK_FOUND: if _MAGICK_FOUND:
# Delete All Metadata button... # Delete All Metadata button...
hsd_box.add( self.__create_button( hsd_box.add(self.__create_button(
"Delete", False, self.__delete_dialog, gtk.STOCK_DELETE, False) ) "Delete", False, self.__delete_dialog, gtk.STOCK_DELETE, False))
# adds Exif Metadata Viewing Area # adds Exif Metadata Viewing Area
vbox.pack_start(view, padding =10) vbox.pack_start(view, padding =10)
self.gui.get_container_widget().remove(self.gui.textview) return vbox
self.gui.get_container_widget().add_with_viewport(vbox)
vbox.show_all()
# provide tooltips for all fields and buttons...
_setup_widget_tooltips(self.exif_widgets)
def update_has_data(self): def update_has_data(self):
active_handle = self.get_active('Media') active_handle = self.get_active('Media')
@ -423,6 +408,21 @@ class EditExifMetadata(Gramplet):
return False return False
def activate_buttons(self, ButtonList):
"""
Enable/ activate the buttons that are in ButtonList
"""
for ButtonName in ButtonList:
self.exif_widgets[ButtonName].set_sensitive(True)
def deactivate_buttons(self, ButtonList):
"""
disable/ de-activate buttons in ButtonList
"""
for ButtonName in ButtonList:
self.exif_widgets[ButtonName].set_sensitive(False)
def main(self): # return false finishes def main(self): # return false finishes
""" """
get the active media, mime type, and reads the image metadata get the active media, mime type, and reads the image metadata
@ -682,7 +682,7 @@ class EditExifMetadata(Gramplet):
def _mark_dirty(self, obj): def _mark_dirty(self, obj):
pass pass
def _get_exif_KeyTag(self, KeyTag): def _get_value(self, KeyTag):
""" """
gets the value from the Exif Key, and returns it... gets the value from the Exif Key, and returns it...
@ -708,61 +708,41 @@ class EditExifMetadata(Gramplet):
""" """
# set has data flag... # set has data flag...
self.set_has_data( len(self.MediaDataTags) > 0) self.set_has_data(len(self.MediaDataTags) > 0)
# Activate Clear and Save buttons...
self.activate_buttons(["Clear", "Save"])
# check to see if we got metadata from the media object? # check to see if we got metadata from the media object?
if self.MediaDataTags: if self.MediaDataTags:
# clears all Message Area labels...
self.exif_widgets["Message:Area"].set_text("")
# activate CopyTo button... # activate CopyTo button...
self.activate_buttons(["CopyTo"]) self.activate_buttons(["CopyTo"])
# set Message Area to Display...
self.exif_widgets["Message:Area"].set_text(_("Displaying image Exif metadata..."))
for KeyTag in self.MediaDataTags: for KeyTag in self.MediaDataTags:
tagValue = self._get_exif_KeyTag(KeyTag)
if tagValue:
if LesserVersion:
label = self.plugin_image.tagDetails(KeyTag)[0]
human_value = self.plugin_image.interpretedExifValue(KeyTag)
else:
try:
tag = self.plugin_image[KeyTag]
label = tag.label
human_value = tag.human_value
except AttributeError:
human_value = False
if human_value is not False: if LesserVersion:
if KeyTag in ("Exif.Image.DateTime", "Exif.Photo.DateTimeOriginal", label = self.plugin_image.tagDetails(KeyTag)[0]
"Exif.Photo.DateTimeDigitized"): human_value = self.plugin_image.interpretedExifValue(KeyTag)
human_value = _process_date( self._get_exif_KeyTag(KeyTag) )
self.model.append( (self.plugin_image, label, human_value) ) else:
else: try:
# display "No Exif metadata" message... tag = self.plugin_image[KeyTag]
self.exif_widgets["Message:Area"].set_text(_("No Exif metadata for this image...")) label = tag.label
human_value = tag.human_value
except AttributeError:
human_value = False
# set has_data flag... if KeyTag in ("Exif.Image.DateTime",
self.set_has_data(False) "Exif.Photo.DateTimeOriginal",
"Exif.Photo.DateTimeDigitized"):
human_value = _process_datetime(self._get_value(KeyTag))
# Activate Clear and Save buttons.. if human_value is not False:
self.activate_buttons(["Clear", "Save"]) self.model.append((self.plugin_image, label, human_value))
def activate_buttons(self, ButtonList):
"""
Enable/ activate the buttons that are in ButtonList
"""
for ButtonName in ButtonList:
self.exif_widgets[ButtonName].set_sensitive(True)
def deactivate_buttons(self, ButtonList):
"""
disable/ de-activate buttons in ButtonList
"""
for ButtonName in ButtonList:
self.exif_widgets[ButtonName].set_sensitive(False)
def CopyTo(self, obj): def CopyTo(self, obj):
""" """
@ -783,7 +763,7 @@ class EditExifMetadata(Gramplet):
# name for matching to exif_widgets # name for matching to exif_widgets
widgetsName = _DATAMAP[KeyTag] widgetsName = _DATAMAP[KeyTag]
tagValue = self._get_exif_KeyTag(KeyTag) tagValue = self._get_value(KeyTag)
if tagValue: if tagValue:
if widgetsName in ["Description", "Artist", "Copyright"]: if widgetsName in ["Description", "Artist", "Copyright"]:
@ -791,16 +771,16 @@ class EditExifMetadata(Gramplet):
# Original Date of the image... # Original Date of the image...
elif widgetsName == "DateTime": elif widgetsName == "DateTime":
use_date = self._get_exif_KeyTag(KeyTag) use_date = self._get_value(KeyTag)
use_date = _process_date(use_date) if use_date else False use_date = _process_datetime(use_date) if use_date else False
if use_date is not False: if use_date is not False:
self.exif_widgets[widgetsName].set_text(use_date) self.exif_widgets[widgetsName].set_text(use_date)
# LatitudeRef, Latitude, LongitudeRef, Longitude... # LatitudeRef, Latitude, LongitudeRef, Longitude...
elif widgetsName == "Latitude": elif widgetsName == "Latitude":
latitude = self._get_exif_KeyTag(KeyTag) latitude = self._get_value(KeyTag)
longitude = self._get_exif_KeyTag(_DATAMAP["Longitude"] ) longitude = self._get_value(_DATAMAP["Longitude"] )
# if latitude and longitude exist, display them? # if latitude and longitude exist, display them?
if (latitude and longitude): if (latitude and longitude):
@ -817,10 +797,10 @@ class EditExifMetadata(Gramplet):
if (not latfail and not longfail): if (not latfail and not longfail):
# Latitude Direction Reference # Latitude Direction Reference
LatitudeRef = self._get_exif_KeyTag(_DATAMAP["LatitudeRef"] ) LatitudeRef = self._get_value(_DATAMAP["LatitudeRef"] )
# Longitude Direction Reference # Longitude Direction Reference
LongitudeRef = self._get_exif_KeyTag(_DATAMAP["LongitudeRef"] ) LongitudeRef = self._get_value(_DATAMAP["LongitudeRef"] )
# set display for Latitude GPS Coordinates # set display for Latitude GPS Coordinates
self.exif_widgets["Latitude"].set_text( self.exif_widgets["Latitude"].set_text(
@ -1062,8 +1042,10 @@ class EditExifMetadata(Gramplet):
self._set_exif_KeyTag(_DATAMAP["Description"], self.exif_widgets["Description"].get_text() ) self._set_exif_KeyTag(_DATAMAP["Description"], self.exif_widgets["Description"].get_text() )
# Modify Date/ Time... not a data field, but saved anyway... # Modify Date/ Time... not a data field, but saved anyway...
ModDateTime = _format_datetime(datetime.now() ) self._set_exif_KeyTag(_DATAMAP["Modified"], datetime.now() )
self._set_exif_KeyTag(_DATAMAP["ModDateTime"], _write_date(ModDateTime) )
# display modified Date/ Time
self.exif_widgets["Modified"].set_text(_format_datetime(datetime.now() ) )
# Artist/ Author data field # Artist/ Author data field
self._set_exif_KeyTag(_DATAMAP["Artist"], self.exif_widgets["Artist"].get_text() ) self._set_exif_KeyTag(_DATAMAP["Artist"], self.exif_widgets["Artist"].get_text() )
@ -1074,12 +1056,9 @@ class EditExifMetadata(Gramplet):
# Original Date/ Time data field # Original Date/ Time data field
DateTime = self.exif_widgets["DateTime"].get_text() DateTime = self.exif_widgets["DateTime"].get_text()
if DateTime: if DateTime:
if type(DateTime) is not datetime: DateTime = _process_datetime(DateTime, False)
DateTime = _process_date(DateTime) if DateTime is not False:
self._set_exif_KeyTag(_DATAMAP["DateTime"], DateTime)
if type(DateTime) == datetime:
self.exif_widgets["DateTime"].set_text(_format_datetime(DateTime) )
self._set_exif_KeyTag(_DATAMAP["DateTime"], _write_date(DateTime) )
# Latitude/ Longitude data fields # Latitude/ Longitude data fields
latitude = self.exif_widgets["Latitude"].get_text() latitude = self.exif_widgets["Latitude"].get_text()
@ -1297,18 +1276,19 @@ def rational_to_dms(coords):
return deg, min, sec return deg, min, sec
def _format_datetime(exif_dt): def _format_datetime(exif_date):
""" """
Convert a python datetime object into a string for display, using the Convert a python datetime object into a string for display, using the
standard Gramps date format. standard Gramps date format.
""" """
if type(exif_dt) is not datetime:
return '' if not isinstance(exif_date, datetime):
return ""
date_part = gen.lib.Date() date_part = gen.lib.Date()
date_part.set_yr_mon_day(exif_dt.year, exif_dt.month, exif_dt.day) date_part.set_yr_mon_day(exif_date.year, exif_date.month, exif_date.day)
date_str = _dd.display(date_part) date_str = _dd.display(date_part)
time_str = exif_dt.strftime('%H:%M:%S') time_str = exif_date.strftime('%H:%M:%S')
return _('%(date)s %(time)s') % {'date': date_str, 'time': time_str} return _('%(date)s %(time)s') % {'date': date_str, 'time': time_str}
@ -1318,6 +1298,7 @@ def _get_date_format(datestr):
""" """
# attempt to determine the dateformat of the variable passed to it... # attempt to determine the dateformat of the variable passed to it...
tmpDate = False
for dateformat in ["%Y-%m-%d %H:%M:%S", "%Y %m %d %H:%M:%S", for dateformat in ["%Y-%m-%d %H:%M:%S", "%Y %m %d %H:%M:%S",
"%Y-%b-%d %H:%M:%S", "%Y %b %d %H:%M:%S", "%Y-%b-%d %H:%M:%S", "%Y %b %d %H:%M:%S",
"%Y-%B-%d %H:%M:%S", "%Y %B %d %H:%M:%S", "%Y-%B-%d %H:%M:%S", "%Y %B %d %H:%M:%S",
@ -1335,80 +1316,97 @@ def _get_date_format(datestr):
# datestring format not found... # datestring format not found...
except ValueError: except ValueError:
tmpDate = False pass
return tmpDate return tmpDate
def _write_date(wdatetime): def _create_datetime(pyear, pmonth, day, hour, minutes, seconds):
""" """
handle thes Original Date/ Time field for saving will create and retrun a str or datetime from (
year, month, day, hour, minutes, and seconds) ...
if the year is less than 1900, then it will return a string representation...
""" """
datestr = _get_date_format(wdatetime) # do some error trapping...
if datestr is not False: if pmonth > 12:
wyear, wmonth, day, hour, minutes, seconds = datestr[0:6] pmonth = 12
elif pmonth <= 0:
pmonth = 1
# do some error trapping... if hour >= 24:
if wmonth > 12: wmonth = 12 hour = 23
if day == 0: day = 1 elif hour < 0:
if hour >= 24: hour = 0 hour = 0
if minutes > 59: minutes = 59
if seconds > 59: seconds = 59
# get the number of days in year for all months if minutes > 59:
numdays = [0] + [calendar.monthrange(year, month)[1] for year minutes = 59
in [wyear] for month in range(1, 13) ] elif minutes < 0:
minutes = 0
if seconds > 59:
seconds = 59
elif seconds < 0:
seconds = 0
# Make sure that day number is not greater than number of days in that month... # get the number of days in year for all months
if day > numdays[wmonth]: day = numdays[wmonth] numdays = [0] + [calendar.monthrange(year, month)[1] for year in [pyear] for month in range(1, 13) ]
if day > numdays[pmonth]:
day = numdays[pmonth]
elif day <= 0:
day = 1
if wyear < 1900: if pyear < 1900:
try: try:
tmpDate = "%04d-%s-%02d %02d:%02d:%02d" % (wyear, _dd.long_months[wmonth], day, tmpDate = "%04d-%s-%02d %02d:%02d:%02d" % (pyear, _dd.long_months[pmonth], day,
hour, minutes, seconds) hour, minutes, seconds)
except ValueError: except ValueError:
tmpDate = "" tmpDate = False
else:
try:
tmpDate = datetime(wyear, wmonth, day, hour, minutes, seconds)
except ValueError:
tmpDate = ""
return tmpDate
else: else:
return "" try:
tmpDate = datetime(pyear, pmonth, day, hour, minutes, seconds)
def _process_date(tmpDate):
except ValueError:
tmpDate = False
if tmpDate is False:
tmpDate = ""
return tmpDate
def _process_datetime(tmpDate, exif_type =True):
""" """
will attempt to parse the date/ time Exif metadata entry into its pieces... will attempt to parse the date/ time Exif metadata entry into its pieces...
(year, month, day, hour, minutes, seconds) (year, month, day, hour, minutes, seconds)
""" """
if not tmpDate: if not tmpDate:
return "" return False
datetype = type(tmpDate) datetype = type(tmpDate)
# if variable is already in datetime.datetime() format, return it? # if variable is already in datetime.datetime() format, return it?
if datetype == datetime: if datetype == datetime:
return _format_datetime(tmpDate) pyear, pmonth, day = tmpDate.year, tmpDate.month, tmpDate.day
hour, minutes, seconds = tmpDate.hour, tmpDate.minute, tmpDate.second
elif datetype in [date, gen.lib.date.Date, list]: elif any(datetype == value for value in [date, gen.lib.date.Date, list] ):
hour, minutes, seconds = time.localtime()[3:6] hour, minutes, seconds = time.localtime()[3:6]
# ImageDateTime is in datetime.date format # datetime.date format
if datetype == date: if isinstance(tmpDate, date):
pyear, pmonth, day = tmpDate.year, tmpDate.month, tmpDate.day pyear, pmonth, day = tmpDate.year, tmpDate.month, tmpDate.day
# ImageDateTime is in gen.lib.date.Date format # gen.lib.date.Date format
elif datetype == gen.lib.date.Date: elif isinstance(tmpDate, gen.lib.date.Date):
pyear, pmonth, day = tmpDate.get_year(), tmpDate.get_month(), tmpDate.get_day() pyear, pmonth, day = tmpDate.get_year(), tmpDate.get_month(), tmpDate.get_day()
# ImageDateTime is in list format # list format
else: else:
pyear, pmonth, day = tmpDate[0].year, tmpDate[0].month, tmpDate[0].day pyear, pmonth, day = tmpDate[0].year, tmpDate[0].month, tmpDate[0].day
# datetime is in string format... # string format...
elif datetype == str: elif datetype == str:
datestr = _get_date_format(tmpDate) datestr = _get_date_format(tmpDate)
@ -1418,44 +1416,24 @@ def _process_date(tmpDate):
else: else:
pyear, pmonth, day, hour, minutes, seconds = [False]*6 pyear, pmonth, day, hour, minutes, seconds = [False]*6
# do some error trapping... if (not pyear and not pmonth):
if pmonth > 12: pmonth = 12 tmpDate = False
if day == 0: day = 1
if hour >= 24: hour = 0
if minutes > 59: minutes = 59
if seconds > 59: seconds = 59
# get the number of days in year for all months
numdays = [0] + [calendar.monthrange(year, month)[1] for year
in [pyear] for month in range(1, 13) ]
if day > numdays[pmonth]:
day = numdays[pmonth]
if pyear < 1900:
try:
tmpDate = "%04d-%s-%02d %02d:%02d:%02d" % (pyear, _dd.long_months[pmonth], day,
hour, minutes, seconds)
except ValueError:
tmpDate = ""
else: else:
try:
tmpDate = datetime(pyear, pmonth, day, hour, minutes, seconds)
except ValueError: # create datetime...
tmpDate = False tmpDate = _create_datetime(pyear, pmonth, day, hour, minutes, seconds)
if tmpDate is not False: if tmpDate is not False:
if type(tmpDate) == datetime:
return _format_datetime(tmpDate) if isinstance(tmpDate, datetime):
else:
try: # for display only...
return "%04d-%s-%02d %02d:%02d:%02d" % (pyear, _dd.long_months[pmonth], day, # make datetime displayed as user has set in preferences...
hour, minutes, seconds) if exif_type:
except ValueError: tmpDate = _format_datetime(tmpDate)
return ""
else: return tmpDate
return ""
def _setup_widget_tooltips(Exif_widgets): def _setup_widget_tooltips(Exif_widgets):
""" """