Fixed an error in saving Altitude. Some cleanup of code

svn: r17940
This commit is contained in:
Rob G. Healey 2011-07-20 01:53:04 +00:00
parent aa8369263c
commit 146653eb3f

View File

@ -31,7 +31,7 @@ import calendar
import time import time
from PIL import Image from PIL import Image
# 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
from itertools import chain from itertools import chain
@ -83,7 +83,7 @@ else:
# version_info attribute does not exist prior to v0.2.0 # version_info attribute does not exist prior to v0.2.0
OLD_API = True OLD_API = True
# define the Exiv2 command... # define the Exiv2 command
system_platform = os.sys.platform system_platform = os.sys.platform
if system_platform == "win32": if system_platform == "win32":
EXIV2_FOUND = "exiv2.exe" if Utils.search_for("exiv2.exe") else False EXIV2_FOUND = "exiv2.exe" if Utils.search_for("exiv2.exe") else False
@ -142,12 +142,12 @@ _vtypes = [".bmp", ".dng", ".exv", ".jp2", ".jpeg", ".jpg", ".nef", ".pef",
".pgf", ".png", ".psd", ".srw", ".tiff"] ".pgf", ".png", ".psd", ".srw", ".tiff"]
_VALIDIMAGEMAP = dict( (index, imgtype) for index, imgtype in enumerate(_vtypes) ) _VALIDIMAGEMAP = dict( (index, imgtype) for index, imgtype in enumerate(_vtypes) )
# valid converting types for PIL.Image... # valid converting types for PIL.Image
# there are more image formats that PIL.Image can convert to, # there are more image formats that PIL.Image can convert to,
# but they are not usable in exiv2/ pyexiv2... # but they are not usable in exiv2/ pyexiv2
_validconvert = [_("<-- Image Types -->"), ".bmp", ".jpg", ".png", ".tiff"] _validconvert = [_("<-- Image Types -->"), ".bmp", ".jpg", ".png", ".tiff"]
# set up Exif keys for Image Exif metadata keypairs... # set up Exif keys for Image Exif metadata keypairs
_DATAMAP = { _DATAMAP = {
"Exif.Image.ImageDescription" : "Description", "Exif.Image.ImageDescription" : "Description",
"Exif.Photo.DateTimeOriginal" : "Original", "Exif.Photo.DateTimeOriginal" : "Original",
@ -165,72 +165,72 @@ _DATAMAP = {
_DATAMAP = dict((key, val) for key, val in _DATAMAP.items() ) _DATAMAP = dict((key, val) for key, val in _DATAMAP.items() )
_DATAMAP.update( (val, key) for key, val in _DATAMAP.items() ) _DATAMAP.update( (val, key) for key, val in _DATAMAP.items() )
# define tooltips for all data entry fields... # define tooltips for all data entry fields
_TOOLTIPS = { _TOOLTIPS = {
# Edit:Message notification area... # Edit Message Area
"Edit:Message" : _("User notification area for the Edit Area window."), "EditMessage" : _("Display area for Editing Area"),
# Media Object Title... # Media Object Title
"MediaTitle" : _("Warning: Changing this entry will update the Media " "MediaTitle" : _("Warning: Changing this entry will update the Media "
"object title field in Gramps not Exiv2 metadata."), "object title field in Gramps not Exiv2 metadata."),
# Description... # Description
"Description" : _("Provide a short descripion for this image."), "Description" : _("Provide a short descripion for this image."),
# Last Change/ Modify Date/ Time... # Last Change/ Modify Date/ Time
"Modified" : _("This is the date/ time that the image was last changed/ modified.\n" "Modified" : _("This is the date/ time that the image was last changed/ modified.\n"
"Example: 2011-05-24 14:30:00"), "Example: 2011-05-24 14:30:00"),
# Artist... # Artist
"Artist" : _("Enter the Artist/ Author of this image. The person's name or " "Artist" : _("Enter the Artist/ Author of this image. The person's name or "
"the company who is responsible for the creation of this image."), "the company who is responsible for the creation of this image."),
# Copyright... # Copyright
"Copyright" : _("Enter the copyright information for this image. \n"), "Copyright" : _("Enter the copyright information for this image. \n"),
# Original Date/ Time... # Original Date/ Time
"Original" : _("The original date/ time when the image was first created/ taken as in a photograph.\n" "Original" : _("The original date/ time when the image was first created/ taken as in a photograph.\n"
"Example: 1830-01-1 09:30:59"), "Example: 1830-01-1 09:30:59"),
# GPS Latitude coordinates... # GPS Latitude coordinates
"Latitude" : _("Enter the Latitude GPS coordinates for this image,\n" "Latitude" : _("Enter the Latitude GPS coordinates for this image,\n"
"Example: 43.722965, 43 43 22 N, 38° 38 03″ N, 38 38 3"), "Example: 43.722965, 43 43 22 N, 38° 38 03″ N, 38 38 3"),
# GPS Longitude coordinates... # GPS Longitude coordinates
"Longitude" : _("Enter the Longitude GPS coordinates for this image,\n" "Longitude" : _("Enter the Longitude GPS coordinates for this image,\n"
"Example: 10.396378, 10 23 46 E, 105° 6 6″ W, -105 6 6"), "Example: 10.396378, 10 23 46 E, 105° 6 6″ W, -105 6 6"),
# GPS Altitude (in meters)... # GPS Altitude (in meters)
"Altitude" : _("This is the measurement of Above or Below Sea Level. It is measured in meters." "Altitude" : _("This is the measurement of Above or Below Sea Level. It is measured in meters."
"Example: 200.558, -200.558") } "Example: 200.558, -200.558") }
_TOOLTIPS = dict( (key, tooltip) for key, tooltip in _TOOLTIPS.items() ) _TOOLTIPS = dict( (key, tooltip) for key, tooltip in _TOOLTIPS.items() )
# define tooltips for all buttons... # define tooltips for all buttons
# common buttons for all images... # common buttons for all images
_BUTTONTIPS = { _BUTTONTIPS = {
# Wiki Help button... # Wiki Help button
"Help" : _("Displays the Gramps Wiki Help page for 'Edit Image Exif Metadata' " "Help" : _("Displays the Gramps Wiki Help page for 'Edit Image Exif Metadata' "
"in your web browser."), "in your web browser."),
# Edit screen button... # Edit screen button
"Edit" : _("This will open up a new window to allow you to edit/ modify " "Edit" : _("This will open up a new window to allow you to edit/ modify "
"this image's Exif metadata.\n It will also allow you to be able to " "this image's Exif metadata.\n It will also allow you to be able to "
"Save the modified metadata."), "Save the modified metadata."),
# Thumbnail Viewing Window button... # Thumbnail Viewing Window button
"Thumbnail" : _("Will produce a Popup window showing a Thumbnail Viewing Area"), "Thumbnail" : _("Will produce a Popup window showing a Thumbnail Viewing Area"),
# Image Type button... # Image Type button
"ImageTypes" : _("Select from a drop- down box the image file type that you " "ImageTypes" : _("Select from a drop- down box the image file type that you "
"would like to convert your non- Exiv2 compatible media object to."), "would like to convert your non- Exiv2 compatible media object to."),
# Convert to different image type... # Convert to different image type
"Convert" : _("If your image is not of an image type that can have " "Convert" : _("If your image is not of an image type that can have "
"Exif metadata read/ written to/from, convert it to a type that can?"), "Exif metadata read/ written to/from, convert it to a type that can?"),
# Delete/ Erase/ Wipe Exif metadata button... # Delete/ Erase/ Wipe Exif metadata button
"Delete" : _("WARNING: This will completely erase all Exif metadata " "Delete" : _("WARNING: This will completely erase all Exif metadata "
"from this image! Are you sure that you want to do this?") } "from this image! Are you sure that you want to do this?") }
@ -248,13 +248,10 @@ class EditExifMetadata(Gramplet):
seconds symbol = \2033 seconds symbol = \2033
""" """
def init(self): def init(self):
"""create variables, and build display"""
self.exif_widgets = {} self.exif_widgets, self.dates, self.coordinates = {}, {}, {}
self.dates = {} self.orig_image, self.plugin_image, self.image_path = [False]*3
self.coordinates = {}
self.orig_image = False
self.plugin_image = False
vbox = self.__build_gui() vbox = self.__build_gui()
self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().remove(self.gui.textview)
@ -262,7 +259,6 @@ class EditExifMetadata(Gramplet):
self.dbstate.db.connect('media-update', self.update) self.dbstate.db.connect('media-update', self.update)
self.connect_signal('Media', self.update) self.connect_signal('Media', self.update)
self.update()
def __build_gui(self): def __build_gui(self):
""" """
@ -271,39 +267,39 @@ class EditExifMetadata(Gramplet):
main_vbox = gtk.VBox(False, 0) main_vbox = gtk.VBox(False, 0)
main_vbox.set_border_width(10) main_vbox.set_border_width(10)
# Displays the file name... # Displays the file name
medialabel = gtk.HBox(False, 0) medialabel = gtk.HBox(False, 0)
label = self.__create_label("MediaLabel", False, False, False) label = self.__create_label("MediaLabel", False, False, False)
medialabel.pack_start(label, expand =False) medialabel.pack_start(label, expand =False)
main_vbox.pack_start(medialabel, expand =False, fill =True, padding =0) main_vbox.pack_start(medialabel, expand =False, fill =True, padding =0)
# Displays mime type information... # Displays mime type information
mimetype = gtk.HBox(False, 0) mimetype = gtk.HBox(False, 0)
label = self.__create_label("MimeType", False, False, False) label = self.__create_label("MimeType", False, False, False)
mimetype.pack_start(label, expand =False) mimetype.pack_start(label, expand =False)
main_vbox.pack_start(mimetype, expand =False, fill =True, padding =0) main_vbox.pack_start(mimetype, expand =False, fill =True, padding =0)
# image dimensions... # image dimensions
imagesize = gtk.HBox(False, 0) imagesize = gtk.HBox(False, 0)
label = self.__create_label("ImageSize", False, False, False) label = self.__create_label("ImageSize", False, False, False)
imagesize.pack_start(label, expand =False, fill =False, padding =0) imagesize.pack_start(label, expand =False, fill =False, padding =0)
main_vbox.pack_start(imagesize, expand =False, fill =True, padding =0) main_vbox.pack_start(imagesize, expand =False, fill =True, padding =0)
# Displays all plugin messages... # Displays all plugin messages
messagearea = gtk.HBox(False, 0) messagearea = gtk.HBox(False, 0)
label = self.__create_label("MessageArea", False, False, False) label = self.__create_label("MessageArea", False, False, False)
messagearea.pack_start(label, expand =False) messagearea.pack_start(label, expand =False)
main_vbox.pack_start(messagearea, expand =False, fill =True, padding =0) main_vbox.pack_start(messagearea, expand =False, fill =True, padding =0)
# Separator line before the buttons... # Separator line before the buttons
main_vbox.pack_start(gtk.HSeparator(), expand =False, fill =True, padding =5) main_vbox.pack_start(gtk.HSeparator(), expand =False, fill =True, padding =5)
# Thumbnail, ImageType, and Convert buttons... # Thumbnail, ImageType, and Convert buttons
new_hbox = gtk.HBox(False, 0) new_hbox = gtk.HBox(False, 0)
main_vbox.pack_start(new_hbox, expand =False, fill =True, padding =5) main_vbox.pack_start(new_hbox, expand =False, fill =True, padding =5)
new_hbox.show() new_hbox.show()
# Thumbnail button... # Thumbnail button
event_box = gtk.EventBox() event_box = gtk.EventBox()
new_hbox.pack_start(event_box, expand =False, fill =True, padding =5) new_hbox.pack_start(event_box, expand =False, fill =True, padding =5)
event_box.show() event_box.show()
@ -312,7 +308,7 @@ class EditExifMetadata(Gramplet):
"Thumbnail", _("Thumbnail"), [self.thumbnail_view]) "Thumbnail", _("Thumbnail"), [self.thumbnail_view])
event_box.add(button) event_box.add(button)
# Image Types... # Image Types
event_box = gtk.EventBox() event_box = gtk.EventBox()
new_hbox.pack_start(event_box, expand =False, fill =True, padding =5) new_hbox.pack_start(event_box, expand =False, fill =True, padding =5)
event_box.show() event_box.show()
@ -325,7 +321,7 @@ class EditExifMetadata(Gramplet):
self.exif_widgets["ImageTypes"] = combo_box self.exif_widgets["ImageTypes"] = combo_box
combo_box.show() combo_box.show()
# Convert button... # Convert button
event_box = gtk.EventBox() event_box = gtk.EventBox()
new_hbox.pack_start(event_box, expand =False, fill =True, padding =5) new_hbox.pack_start(event_box, expand =False, fill =True, padding =5)
event_box.show() event_box.show()
@ -334,10 +330,10 @@ class EditExifMetadata(Gramplet):
"Convert", False, [self.__convert_dialog], gtk.STOCK_CONVERT) "Convert", False, [self.__convert_dialog], gtk.STOCK_CONVERT)
event_box.add(button) event_box.add(button)
# Connect the changed signal to ImageType... # Connect the changed signal to ImageType
self.exif_widgets["ImageTypes"].connect("changed", self.changed_cb) self.exif_widgets["ImageTypes"].connect("changed", self.changed_cb)
# Help, Edit, and Delete buttons... # Help, Edit, and Delete buttons
new_hbox = gtk.HBox(False, 0) new_hbox = gtk.HBox(False, 0)
main_vbox.pack_start(new_hbox, expand =False, fill =True, padding =5) main_vbox.pack_start(new_hbox, expand =False, fill =True, padding =5)
new_hbox.show() new_hbox.show()
@ -351,14 +347,14 @@ class EditExifMetadata(Gramplet):
widget, text, callback, icon, is_sensitive) widget, text, callback, icon, is_sensitive)
new_hbox.pack_start(button, expand =False, fill =True, padding =5) new_hbox.pack_start(button, expand =False, fill =True, padding =5)
# add viewing model... # add viewing model
self.view = MetadataView() self.view = MetadataView()
main_vbox.pack_start(self.view, expand =False, fill =True, padding =5) main_vbox.pack_start(self.view, expand =False, fill =True, padding =5)
# Separator line before the Total... # Separator line before the Total
main_vbox.pack_start(gtk.HSeparator(), expand =False, fill =True, padding =5) main_vbox.pack_start(gtk.HSeparator(), expand =False, fill =True, padding =5)
# number of key/ value pairs shown... # number of key/ value pairs shown
label = self.__create_label("Total", False, False, False) label = self.__create_label("Total", False, False, False)
main_vbox.pack_start(label, expand =False, fill =True, padding =5) main_vbox.pack_start(label, expand =False, fill =True, padding =5)
@ -384,24 +380,24 @@ class EditExifMetadata(Gramplet):
""" """
get the active media, mime type, and reads the image metadata get the active media, mime type, and reads the image metadata
*** disable all buttons at first, then activate as needed... *** disable all buttons at first, then activate as needed
# Help will never be disabled... # Help will never be disabled
""" """
db = self.dbstate.db db = self.dbstate.db
# deactivate all buttons except Help... # deactivate all buttons except Help
self.deactivate_buttons(["Convert", "Edit", "ImageTypes", "Delete"]) self.deactivate_buttons(["Convert", "Edit", "ImageTypes", "Delete"])
imgtype_format = [] imgtype_format = []
# display all button tooltips only... # display all button tooltips only
# 1st argument is for Fields, 2nd argument is for Buttons... # 1st argument is for Fields, 2nd argument is for Buttons
self._setup_widget_tips(fields =False, buttons =True) self._setup_widget_tips(fields =False, buttons =True)
# clears all labels and display area... # clears all labels and display area
for widget in ["MediaLabel", "MimeType", "ImageSize", "MessageArea", "Total"]: for widget in ["MediaLabel", "MimeType", "ImageSize", "MessageArea", "Total"]:
self.exif_widgets[widget].set_text("") self.exif_widgets[widget].set_text("")
# set Message Ares to Select... # set Message Ares to Select
self.exif_widgets["MessageArea"].set_text(_("Select an image to begin...")) self.exif_widgets["MessageArea"].set_text(_("Select an image to begin..."))
active_handle = self.get_active("Media") active_handle = self.get_active("Media")
@ -409,7 +405,7 @@ class EditExifMetadata(Gramplet):
self.set_has_data(False) self.set_has_data(False)
return return
# get image from database... # get image from database
self.orig_image = db.get_object_from_handle(active_handle) self.orig_image = db.get_object_from_handle(active_handle)
if not self.orig_image: if not self.orig_image:
self.set_has_data(False) self.set_has_data(False)
@ -421,34 +417,34 @@ class EditExifMetadata(Gramplet):
self.set_has_data(False) self.set_has_data(False)
return return
# display file description/ title... # display file description/ title
self.exif_widgets["MediaLabel"].set_text(_html_escape(self.orig_image.get_description())) self.exif_widgets["MediaLabel"].set_text(_html_escape(self.orig_image.get_description()))
# Mime type information... # Mime type information
mime_type = self.orig_image.get_mime_type() mime_type = self.orig_image.get_mime_type()
self.exif_widgets["MimeType"].set_text(gen.mime.get_description(mime_type)) self.exif_widgets["MimeType"].set_text(gen.mime.get_description(mime_type))
# check image read privileges... # check image read privileges
_readable = os.access(self.image_path, os.R_OK) _readable = os.access(self.image_path, os.R_OK)
if not _readable: if not _readable:
self.exif_widgets["MessageArea"].set_text(_("Image is NOT readable,\n" self.exif_widgets["MessageArea"].set_text(_("Image is NOT readable,\n"
"Please choose a different image...")) "Please choose a different image..."))
return return
# check image write privileges... # check image write privileges
_writable = os.access(self.image_path, os.W_OK) _writable = os.access(self.image_path, os.W_OK)
if not _writable: if not _writable:
self.exif_widgets["MessageArea"].set_text(_("Image is NOT writable,\n" self.exif_widgets["MessageArea"].set_text(_("Image is NOT writable,\n"
"You will NOT be able to save Exif metadata....")) "You will NOT be able to save Exif metadata...."))
self.deactivate_buttons(["Edit"]) self.deactivate_buttons(["Edit"])
# get dirpath/ basename, and extension... # get dirpath/ basename, and extension
self.basename, self.extension = os.path.splitext(self.image_path) self.basename, self.extension = os.path.splitext(self.image_path)
if ((mime_type and mime_type.startswith("image/")) and if ((mime_type and mime_type.startswith("image/")) and
self.extension not in _VALIDIMAGEMAP.values() ): self.extension not in _VALIDIMAGEMAP.values() ):
# Convert message... # Convert message
self.exif_widgets["MessageArea"].set_text(_("Please convert this " self.exif_widgets["MessageArea"].set_text(_("Please convert this "
"image to an Exiv2- compatible image type...")) "image to an Exiv2- compatible image type..."))
@ -466,11 +462,11 @@ class EditExifMetadata(Gramplet):
if mime_type: if mime_type:
if mime_type.startswith("image/"): if mime_type.startswith("image/"):
# creates, and reads the plugin image instance... # creates, and reads the plugin image instance
self.plugin_image = self.setup_image(self.image_path) self.plugin_image = self.setup_image(self.image_path)
if self.plugin_image: if self.plugin_image:
# get image width and height... # get image width and height
if not OLD_API: if not OLD_API:
self.exif_widgets["ImageSize"].show() self.exif_widgets["ImageSize"].show()
@ -484,15 +480,15 @@ class EditExifMetadata(Gramplet):
self.activate_buttons(["Thumbnail"]) self.activate_buttons(["Thumbnail"])
# display all Exif tags for this image, # display all Exif tags for this image,
# XmpTag and IptcTag has been purposefully excluded... # XmpTag and IptcTag has been purposefully excluded
self.__display_exif_tags(self.image_path) self.__display_exif_tags(self.image_path)
# has mime, but not an image... # has mime, but not an image
else: else:
self.exif_widgets["MessageArea"].set_text(_("Please choose a different image...")) self.exif_widgets["MessageArea"].set_text(_("Please choose a different image..."))
return return
# has no mime... # has no mime
else: else:
self.exif_widgets["MessageArea"].set_text(_("Please choose a different image...")) self.exif_widgets["MessageArea"].set_text(_("Please choose a different image..."))
return return
@ -507,7 +503,7 @@ class EditExifMetadata(Gramplet):
except (IOError, OSError): except (IOError, OSError):
return False return False
else: # pyexiv2-0.2.0 and above... else: # pyexiv2-0.2.0 and above
try: try:
previews = self.plugin_image.previews previews = self.plugin_image.previews
except (IOError, OSError): except (IOError, OSError):
@ -522,10 +518,10 @@ class EditExifMetadata(Gramplet):
# display exif tags in the treeview # display exif tags in the treeview
has_data = self.view.display_exif_tags(full_path) has_data = self.view.display_exif_tags(full_path)
# update has_data functionality... # update set_has_data functionality
self.set_has_data(has_data) self.set_has_data(has_data)
# activate these buttons... # activate these buttons
self.activate_buttons(["Delete", "Edit"]) self.activate_buttons(["Delete", "Edit"])
def changed_cb(self, ext_value =None): def changed_cb(self, ext_value =None):
@ -534,7 +530,7 @@ class EditExifMetadata(Gramplet):
image extension is not an Exiv2- compatible image? image extension is not an Exiv2- compatible image?
""" """
# get convert image type and check it from ImageTypes drop- down... # get convert image type and check it from ImageTypes drop- down
ext_value = self.exif_widgets["ImageTypes"].get_active() ext_value = self.exif_widgets["ImageTypes"].get_active()
if ext_value >= 1: if ext_value >= 1:
@ -543,22 +539,22 @@ class EditExifMetadata(Gramplet):
if not self.exif_widgets["Convert"].get_sensitive(): if not self.exif_widgets["Convert"].get_sensitive():
self.activate_buttons(["Convert"]) self.activate_buttons(["Convert"])
# connect clicked signal to Convert button... # connect clicked signal to Convert button
self.exif_widgets["Convert"].connect("clicked", self.__convert_dialog) self.exif_widgets["Convert"].connect("clicked", self.__convert_dialog)
def _setup_widget_tips(self, fields =None, buttons =None): def _setup_widget_tips(self, fields =None, buttons =None):
""" """
set up widget tooltips... set up widget tooltips
* data fields * data fields
* buttons * buttons
""" """
# if True, setup tooltips for all Data Entry Fields... # if True, setup tooltips for all Data Entry Fields
if fields: if fields:
for widget, tooltip in _TOOLTIPS.items(): for widget, tooltip in _TOOLTIPS.items():
self.exif_widgets[widget].set_tooltip_text(tooltip) self.exif_widgets[widget].set_tooltip_text(tooltip)
# if True, setup tooltips for all Buttons... # if True, setup tooltips for all Buttons
if buttons: if buttons:
for widget, tooltip in _BUTTONTIPS.items(): for widget, tooltip in _BUTTONTIPS.items():
self.exif_widgets[widget].set_tooltip_text(tooltip) self.exif_widgets[widget].set_tooltip_text(tooltip)
@ -617,7 +613,7 @@ class EditExifMetadata(Gramplet):
for call_ in callback: for call_ in callback:
button.connect("clicked", call_) button.connect("clicked", call_)
# attach a addon widget to the button for later manipulation... # attach a addon widget to the button for later manipulation
self.exif_widgets[pos] = button self.exif_widgets[pos] = button
if not sensitive: if not sensitive:
@ -695,7 +691,7 @@ class EditExifMetadata(Gramplet):
if not previews: if not previews:
return pbloader, width, height return pbloader, width, height
# Get the largest preview available... # Get the largest preview available
preview = previews[-1] preview = previews[-1]
width, height = preview.dimensions width, height = preview.dimensions
except (IOError, OSError): except (IOError, OSError):
@ -719,7 +715,7 @@ class EditExifMetadata(Gramplet):
main_vbox.pack_start(hbox, expand =False, fill =False, padding =5) main_vbox.pack_start(hbox, expand =False, fill =False, padding =5)
hbox.show() hbox.show()
# Get the resulting pixbuf and build an image to be displayed... # Get the resulting pixbuf and build an image to be displayed
pixbuf = pbloader.get_pixbuf() pixbuf = pbloader.get_pixbuf()
pbloader.close() pbloader.close()
@ -733,10 +729,10 @@ class EditExifMetadata(Gramplet):
def __convert_dialog(self, object): def __convert_dialog(self, object):
""" """
Handles the Convert question Dialog... Handles the Convert question Dialog
""" """
# Convert and delete original file or just convert... # Convert and delete original file or just convert
OptionDialog(_("Edit Image Exif Metadata"), _("WARNING: You are about to convert this " OptionDialog(_("Edit Image Exif Metadata"), _("WARNING: You are about to convert this "
"image into a .jpeg image. Are you sure that you want to do this?"), "image into a .jpeg image. Are you sure that you want to do this?"),
_("Convert and Delete"), self.__convert_delete, _("Convert"), self.__convert_only) _("Convert and Delete"), self.__convert_delete, _("Convert"), self.__convert_only)
@ -752,25 +748,25 @@ class EditExifMetadata(Gramplet):
if full_path is None: if full_path is None:
full_path = self.image_path full_path = self.image_path
# get image filepath and its filename... # get image filepath and its filename
filepath, basename = os.path.split(self.basename) filepath, basename = os.path.split(self.basename)
# get extension selected for converting this image... # get extension selected for converting this image
ext_type = self.exif_widgets["ImageTypes"].get_active() ext_type = self.exif_widgets["ImageTypes"].get_active()
if ext_type == 0: if ext_type == 0:
return False return False
basename += self._VCONVERTMAP[ext_type] basename += self._VCONVERTMAP[ext_type]
# new file name and dirpath... # new file name and dirpath
dest_file = os.path.join(filepath, basename) dest_file = os.path.join(filepath, basename)
# open source image file... # open source image file
im = Image.open(full_path) im = Image.open(full_path)
im.save(dest_file) im.save(dest_file)
# pyexiv2 source image file... # pyexiv2 source image file
if OLD_API: # prior to pyexiv2-0.2.0... if OLD_API: # prior to pyexiv2-0.2.0
src_meta = pyexiv2.Image(full_path) src_meta = pyexiv2.Image(full_path)
src_meta.readMetadata() src_meta.readMetadata()
else: else:
@ -781,24 +777,24 @@ class EditExifMetadata(Gramplet):
if _get_exif_keypairs(src_meta): if _get_exif_keypairs(src_meta):
if OLD_API: # prior to pyexiv2-0.2.0 if OLD_API: # prior to pyexiv2-0.2.0
# Identify the destination image file... # Identify the destination image file
dest_meta = pyexiv2.Image(dest_file) dest_meta = pyexiv2.Image(dest_file)
dest_meta.readMetadata() dest_meta.readMetadata()
# copy source metadata to destination file... # copy source metadata to destination file
src_meta.copy(dest_meta, comment =False) src_meta.copy(dest_meta, comment =False)
# writes all Exif Metadata to image even if the fields are all empty so as to remove the value... # writes all Exif Metadata to image even if the fields are all empty so as to remove the value
self.write_metadata(dest_meta) self.write_metadata(dest_meta)
else: # pyexiv2-0.2.0 and above... else: # pyexiv2-0.2.0 and above
# Identify the destination image file... # Identify the destination image file
dest_meta = pyexiv2.ImageMetadata(dest_file) dest_meta = pyexiv2.ImageMetadata(dest_file)
dest_meta.read() dest_meta.read()
# copy source metadata to destination file... # copy source metadata to destination file
src_meta.copy(dest_meta, comment =False) src_meta.copy(dest_meta, comment =False)
# writes all Exif Metadata to image even if the fields are all empty so as to remove the value... # writes all Exif Metadata to image even if the fields are all empty so as to remove the value
self.write_metadata(dest_meta) self.write_metadata(dest_meta)
return dest_file return dest_file
@ -815,7 +811,7 @@ class EditExifMetadata(Gramplet):
newfilepath = self.__convert_copy(full_path) newfilepath = self.__convert_copy(full_path)
if newfilepath: if newfilepath:
# delete original file from this computer and set new filepath... # delete original file from this computer and set new filepath
try: try:
os.remove(full_path) os.remove(full_path)
delete_results = True delete_results = True
@ -827,7 +823,7 @@ class EditExifMetadata(Gramplet):
if (os.path.isfile(newfilepath) and not os.path.isfile(full_path) ): if (os.path.isfile(newfilepath) and not os.path.isfile(full_path) ):
self.__update_media_path(newfilepath) self.__update_media_path(newfilepath)
# notify user about the convert, delete, and new filepath... # notify user about the convert, delete, and new filepath
self.exif_widgets["MessageArea"].set_text(_("Your image has been " self.exif_widgets["MessageArea"].set_text(_("Your image has been "
"converted and the original file has been deleted, and " "converted and the original file has been deleted, and "
"the full path has been updated!")) "the full path has been updated!"))
@ -850,7 +846,7 @@ class EditExifMetadata(Gramplet):
newfilepath = self.__convert_copy(full_path) newfilepath = self.__convert_copy(full_path)
if newfilepath: if newfilepath:
# update the media object path... # update the media object path
self.__update_media_path(newfilepath) self.__update_media_path(newfilepath)
else: else:
self.exif_widgets["MessageArea"].set_text(_("There was an error " self.exif_widgets["MessageArea"].set_text(_("There was an error "
@ -864,7 +860,7 @@ class EditExifMetadata(Gramplet):
if newfilepath: if newfilepath:
db = self.dbstate.db db = self.dbstate.db
# begin database tranaction to save media object new path... # begin database tranaction to save media object new path
with DbTxn(_("Media Path Update"), db) as trans: with DbTxn(_("Media Path Update"), db) as trans:
self.orig_image.set_path(newfilepath) self.orig_image.set_path(newfilepath)
@ -894,7 +890,7 @@ class EditExifMetadata(Gramplet):
""" """
disable/ de-activate buttons in buttonlist disable/ de-activate buttons in buttonlist
*** if All, then disable ALL buttons in the current display... *** if All, then disable ALL buttons in the current display
""" """
if buttonlist == ["All"]: if buttonlist == ["All"]:
@ -904,32 +900,6 @@ class EditExifMetadata(Gramplet):
for widget in buttonlist: for widget in buttonlist:
self.exif_widgets[widget].set_sensitive(False) self.exif_widgets[widget].set_sensitive(False)
def active_buttons(self, obj):
"""
will handle the toggle action of the Edit button.
If there is no Exif metadata, then the data fields are connected to the
'changed' signal to be able to activate the Edit button once data has been entered
into the data fields...
Activate these buttons once info has been entered into the data fields...
"""
if not self.exif_widgets["Edit"].get_sensitive():
self.activate_buttons(["Edit"])
# set Message Area to Entering Data...
self.exif_widgets["MessageArea"].set_text(_("Entering data..."))
if EXIV2_FOUND:
if not self.exif_widgets["Delete"].get_sensitive():
self.activate_buttons(["Delete"])
# if Save is in the list of button tooltips, then check it too?
if "Save" in _BUTTONTIPS.keys():
if not self.exif_widgets["Save"].get_sensitive():
self.activate_buttons(["Save"])
def display_edit(self, object): def display_edit(self, object):
""" """
creates the editing area fields. creates the editing area fields.
@ -990,7 +960,7 @@ class EditExifMetadata(Gramplet):
main_vbox.set_size_request(480, 460) main_vbox.set_size_request(480, 460)
# Notification Area for the Edit Area... # Notification Area for the Edit Area...
label = self.__create_label("Edit:Message", False, width =440, height = 25) label = self.__create_label("EditMessage", False, width =440, height = 25)
main_vbox.pack_start(label, expand = False, fill =True, padding =5) main_vbox.pack_start(label, expand = False, fill =True, padding =5)
# Media Title Frame... # Media Title Frame...
@ -1132,7 +1102,6 @@ class EditExifMetadata(Gramplet):
for (widget, text, callback, icon, is_sensitive) in [ for (widget, text, callback, icon, is_sensitive) in [
("Help", False, [self.__help_page], gtk.STOCK_HELP, True), ("Help", False, [self.__help_page], gtk.STOCK_HELP, True),
("Save", False, [self.save_metadata, ("Save", False, [self.save_metadata,
self.__display_exif_tags,
self.update], gtk.STOCK_SAVE, True), self.update], gtk.STOCK_SAVE, True),
("Clear", False, [self.clear_metadata], gtk.STOCK_CLEAR, True), ("Clear", False, [self.clear_metadata], gtk.STOCK_CLEAR, True),
("Copy", False, [self.__display_exif_tags], gtk.STOCK_COPY, True), ("Copy", False, [self.__display_exif_tags], gtk.STOCK_COPY, True),
@ -1188,25 +1157,23 @@ class EditExifMetadata(Gramplet):
"delete the Exif metadata from this image?"), _("Delete"), "delete the Exif metadata from this image?"), _("Delete"),
self.strip_metadata) self.strip_metadata)
def _get_value(self, keytag): def __get_value(self, key):
""" """
gets the value from the Exif Key, and returns it... gets the value from the Exif Key, and returns it...
@param: keytag -- image metadata key @param: key -- image metadata key
""" """
exifvalue = ''
if OLD_API: if OLD_API:
keyvalu = self.plugin_image[keytag] exifvalue = self.plugin_image[key]
else: else:
try: try:
value = self.plugin_image.__getitem__(keytag) exifvalue = self.plugin_image[key].value
keyvalu = value.value
except (KeyError, ValueError, AttributeError): except (KeyError, ValueError, AttributeError):
keyvalu = False pass
return keyvalu return exifvalue
def clear_metadata(self, object): def clear_metadata(self, object):
""" """
@ -1222,12 +1189,12 @@ class EditExifMetadata(Gramplet):
""" """
if mediadatatags is None: if mediadatatags is None:
mediadatatags = _get_exif_keypairs(self.plugin_image) mediadatatags = _get_exif_keypairs(self.plugin_image)
mediadatatags = [keytag for keytag in mediadatatags if keytag in _DATAMAP] mediadatatags = [key for key in mediadatatags if key in _DATAMAP]
for keytag in mediadatatags: for key in mediadatatags:
widget = _DATAMAP[keytag] widget = _DATAMAP[key]
tag_value = self._get_value(keytag) tag_value = self.__get_value(key)
if tag_value: if tag_value:
if widget in ["Description", "Artist", "Copyright"]: if widget in ["Description", "Artist", "Copyright"]:
@ -1246,7 +1213,7 @@ class EditExifMetadata(Gramplet):
# LatitudeRef, Latitude, LongitudeRef, Longitude... # LatitudeRef, Latitude, LongitudeRef, Longitude...
elif widget == "Latitude": 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 exist, display them?
if (latitude and longitude): if (latitude and longitude):
@ -1263,10 +1230,10 @@ class EditExifMetadata(Gramplet):
if (not latfail and not longfail): if (not latfail and not longfail):
# Latitude Direction Reference # Latitude Direction Reference
latref = self._get_value(_DATAMAP["LatitudeRef"] ) latref = self.__get_value(_DATAMAP["LatitudeRef"] )
# Longitude Direction Reference # Longitude Direction Reference
longref = self._get_value(_DATAMAP["LongitudeRef"] ) longref = self.__get_value(_DATAMAP["LongitudeRef"] )
# set display for Latitude GPS coordinates # set display for Latitude GPS coordinates
latitude = """%s° %s %s%s""" % (latdeg, latmin, latsec, latref) latitude = """%s° %s %s%s""" % (latdeg, latmin, latsec, latref)
@ -1281,7 +1248,7 @@ class EditExifMetadata(Gramplet):
elif widget == "Altitude": elif widget == "Altitude":
altitude = tag_value altitude = tag_value
altref = self._get_value(_DATAMAP["AltitudeRef"]) altref = self.__get_value(_DATAMAP["AltitudeRef"])
if (altitude and altref): if (altitude and altref):
altitude = convert_value(altitude) altitude = convert_value(altitude)
@ -1294,21 +1261,23 @@ class EditExifMetadata(Gramplet):
self.media_title = self.orig_image.get_description() self.media_title = self.orig_image.get_description()
self.exif_widgets["MediaTitle"].set_text(self.media_title) self.exif_widgets["MediaTitle"].set_text(self.media_title)
def _set_value(self, keytag, keyvalu): def __set_value(self, key, widgetvalue):
""" """
sets the value for the metadata keytags sets the value for the metadata keys
""" """
if OLD_API: if OLD_API:
self.plugin_image[keytag] = keyvalu self.plugin_image[key] = widgetvalue
valid = True
else: else:
try: try:
self.plugin_image.__setitem__(keytag, keyvalu) self.plugin_image[key].value = widgetvalue
valid = True
except KeyError: except KeyError:
self.plugin_image[keytag] = pyexiv2.ExifTag(keytag, keyvalu) self.plugin_image[key] = pyexiv2.ExifTag(key, widgetvalue)
valid = True
except (ValueError, AttributeError): except (ValueError, AttributeError):
pass pass
valid = False
def write_metadata(self, plugininstance): def write_metadata(self, plugininstance):
""" """
@ -1319,7 +1288,6 @@ class EditExifMetadata(Gramplet):
""" """
if OLD_API: if OLD_API:
plugininstance.writeMetadata() plugininstance.writeMetadata()
else: else:
plugininstance.write() plugininstance.write()
@ -1356,50 +1324,60 @@ class EditExifMetadata(Gramplet):
return latitude, longitude return latitude, longitude
def save_metadata(self, mediadatatags =None): def save_metadata(self, object):
""" """
gets the information from the plugin data fields gets the information from the plugin data fields
and sets the keytag = keyvalue image metadata and sets the key = widgetvaluee image metadata
""" """
db = self.dbstate.db db = self.dbstate.db
# get a copy of all the widgets and their current values... mediatitle = self.exif_widgets["MediaTitle"].get_text()
mediadatatags = list( (widget, self.exif_widgets[widget].get_text() ) description = self.exif_widgets["Description"].get_text()
for widget in _TOOLTIPS.keys() ) artist = self.exif_widgets["Artist"].get_text()
mediadatatags.sort() copyright = self.exif_widgets["Copyright"].get_text()
for widgetname, widgetvalu in mediadatatags: original = self.dates["Original"]
latitude = self.exif_widgets["Latitude"].get_text()
longitude = self.exif_widgets["Longitude"].get_text()
altitude = self.exif_widgets["Altitude"].get_text()
# Description, Artist, Copyright... mediadatatags = (len(description) +
if widgetname in ["Description", "Artist", "Copyright"]: len(artist) +
self._set_value(_DATAMAP[widgetname], widgetvalu) len(copyright) +
len(latitude) +
len(longitude) +
len(altitude) )
if not mediadatatags:
widgets4clearing = [(widget) for widget in _TOOLTIPS.key()
if widget not in ["MediaTitle", "EditMessage"] ]
for widgetname in widgets4clearing:
self.__set_value(_DATAMAP[widgetname], '')
# set Edit Message to Cleared...
self.exif_widgets["EditMessage"].set_text(_("All Exif metadata has been cleared..."))
else:
for widgetname in _TOOLTIPS.keys():
# Update dynamically updated Modified field... # Update dynamically updated Modified field...
elif widgetname == "Modified": if widgetname == "Modified":
modified = datetime.datetime.now() modified = datetime.datetime.now()
self.exif_widgets[widgetname].set_text(format_datetime(modified) ) self.exif_widgets[widgetname].set_text(format_datetime(modified) )
self.set_datetime(self.exif_widgets[widgetname], widgetname) self.set_datetime(self.exif_widgets[widgetname], widgetname)
if self.dates[widgetname] is not None:
self._set_value(_DATAMAP[widgetname], self.dates[widgetname] )
else:
self._set_value(_DATAMAP[widgetname], widgetvalu)
# Original Date/ Time... # Original Date/ Time...
elif widgetname == "Original": elif widgetname == "Original":
if widgetvalu == '':
self._set_value(_DATAMAP[widgetname], widgetvalu)
else:
self.set_datetime(self.exif_widgets[widgetname], widgetname) self.set_datetime(self.exif_widgets[widgetname], widgetname)
if self.dates[widgetname] is not None:
# modify the media object date if it is not already set? # modify the media object date if it is not already set?
mediaobj_date = self.orig_image.get_date_object() mediaobj_date = self.orig_image.get_date_object()
if mediaobj_date.is_empty(): if mediaobj_date.is_empty():
objdate_ = Date() objdate_ = Date()
widgetvalu = _parse_datetime(widgetvalu) original = _parse_datetime(original)
try: try:
objdate_.set_yr_mon_day(widgetvalu.year, objdate_.set_yr_mon_day(original.year,
widgetvalu.month, original.month,
widgetvalu.day) original.day)
gooddate = True gooddate = True
except ValueError: except ValueError:
gooddate = False gooddate = False
@ -1408,13 +1386,12 @@ class EditExifMetadata(Gramplet):
# begin database tranaction to save media object's date... # begin database tranaction to save media object's date...
with DbTxn(_("Create Date Object"), db) as trans: with DbTxn(_("Create Date Object"), db) as trans:
self.orig_image.set_date_object(objdate_) self.orig_image.set_date_object(objdate_)
db.commit_media_object(self.orig_image, trans) db.commit_media_object(self.orig_image, trans)
db.request_rebuild() db.request_rebuild()
# Latitude/ Longitude... # Latitude/ Longitude...
elif widgetname == "Latitude": elif widgetname == "Latitude":
latitude = self.exif_widgets["Latitude"].get_text()
longitude = self.exif_widgets["Longitude"].get_text()
if (latitude and longitude): if (latitude and longitude):
if (latitude.count(" ") == longitude.count(" ") == 0): if (latitude.count(" ") == longitude.count(" ") == 0):
latitude, longitude = self.convert2dms(latitude, longitude) latitude, longitude = self.convert2dms(latitude, longitude)
@ -1450,33 +1427,21 @@ class EditExifMetadata(Gramplet):
latitude = coords_to_rational(latitude) latitude = coords_to_rational(latitude)
longitude = coords_to_rational(longitude) longitude = coords_to_rational(longitude)
# save LatitudeRef/ Latitude...
self._set_value(_DATAMAP["LatitudeRef"], latref)
self._set_value(_DATAMAP["Latitude"], latitude)
# save LongitudeRef/ Longitude...
self._set_value(_DATAMAP["LongitudeRef"], longref)
self._set_value(_DATAMAP["Longitude"], longitude)
# Altitude, and Altitude Reference... # Altitude, and Altitude Reference...
elif widgetname == "Altitude": elif widgetname == "Altitude":
if widgetvalu: if altitude:
if "-" in widgetvalu: if "-" in altitude:
widgetvalu= widgetvalu.replace("-", "") altitude = altitude.replace("-", "")
altituderef = "1" altituderef = "1"
else: else:
altituderef = "0" altituderef = "0"
# convert altitude to pyexiv2.Rational for saving... # convert altitude to pyexiv2.Rational for saving...
widgetvalu = coords_to_rational(widgetvalu) altitude = altitude2rational(altitude)
else: else:
altituderef = '' altituderef = ''
self._set_value(_DATAMAP["AltitudeRef"], altituderef) elif widgetname == "MediaTitle":
self._set_value(_DATAMAP[widgetname], widgetvalu)
# Media Title Changed or not?
mediatitle = self.exif_widgets["MediaTitle"].get_text()
if (self.media_title and self.media_title is not mediatitle): if (self.media_title and self.media_title is not mediatitle):
with DbTxn(_("Media Title Update"), db) as trans: with DbTxn(_("Media Title Update"), db) as trans:
self.orig_image.set_description(mediatitle) self.orig_image.set_description(mediatitle)
@ -1484,16 +1449,37 @@ class EditExifMetadata(Gramplet):
db.commit_media_object(self.orig_image, trans) db.commit_media_object(self.orig_image, trans)
db.request_rebuild() db.request_rebuild()
# Description
self.__set_value(_DATAMAP["Description"], description)
# Artist
self.__set_value(_DATAMAP["Artist"], artist)
# Copyright
self.__set_value(_DATAMAP["Copyright"], copyright)
# 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 and Latitude
self.__set_value(_DATAMAP["LatitudeRef"], latref)
self.__set_value(_DATAMAP["Latitude"], latitude)
# Longitude Reference and Longitude
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)
# 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... # 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) self.write_metadata(self.plugin_image)
if mediadatatags:
# set Message Area to Saved...
self.exif_widgets["Edit:Message"].set_text(_("Saving Exif metadata to this image..."))
else:
# set Edit Message to Cleared...
self.exif_widgets["Edit:Message"].set_text(_("All Exif metadata has been cleared..."))
def strip_metadata(self, mediadatatags =None): def strip_metadata(self, mediadatatags =None):
""" """
Will completely and irrevocably erase all Exif metadata from this image. Will completely and irrevocably erase all Exif metadata from this image.
@ -1511,8 +1497,8 @@ class EditExifMetadata(Gramplet):
erase_results = False erase_results = False
else: # use pyexiv2 to delete Exif metadata... else: # use pyexiv2 to delete Exif metadata...
for keytag in mediadatatags: for key in mediadatatags:
del self.plugin_image[keytag] del self.plugin_image[key]
erase_results = True erase_results = True
if erase_results: if erase_results:
@ -1557,9 +1543,6 @@ def string_to_rational(coordinate):
""" """
convert string to rational variable for GPS convert string to rational variable for GPS
""" """
if coordinate:
if '.' in coordinate: if '.' in coordinate:
value1, value2 = coordinate.split('.') value1, value2 = coordinate.split('.')
return pyexiv2.Rational(int(float(value1 + value2)), 10**len(value2)) return pyexiv2.Rational(int(float(value1 + value2)), 10**len(value2))
@ -1587,6 +1570,11 @@ def coords_to_rational(coordinates):
return [string_to_rational(coordinate) for coordinate in coordinates] return [string_to_rational(coordinate) for coordinate in coordinates]
def altitude2rational(meters_):
"""convert Altitude to pyexiv2.Rational"""
return [string_to_rational(meters_)]
def convert_value(value): def convert_value(value):
""" """
will take a value from the coordinates and return its value will take a value from the coordinates and return its value
@ -1615,7 +1603,7 @@ def _get_exif_keypairs(plugin_image):
""" """
if plugin_image: if plugin_image:
return [keytag for keytag in (plugin_image.exifKeys() if OLD_API return [key for key in (plugin_image.exifKeys() if OLD_API
else plugin_image.exif_keys) ] else plugin_image.exif_keys) ]
else: else:
return False return False