diff --git a/src/plugins/gramplet/MediaMetadata.py b/src/plugins/gramplet/MediaMetadata.py
index 5c24bba4b..c487cb55b 100644
--- a/src/plugins/gramplet/MediaMetadata.py
+++ b/src/plugins/gramplet/MediaMetadata.py
@@ -19,7 +19,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-# $Id: AttributesGramplet.py 16035 2010-10-24 14:43:47Z bmcage $
+# $Id: $
#
# *****************************************************************************
@@ -35,12 +35,9 @@ from xml.sax.saxutils import escape as _html_escape
#------------------------------------------------
# Gtk/ Gramps modules
#------------------------------------------------
-
-from gen.plug import Gramplet
+import gtk
from gen.ggettext import gettext as _
-import gen.mime
-
# import the pyexiv2 library classes for this addon
_DOWNLOAD_LINK = "http://tilloy.net/dev/pyexiv2/"
pyexiv2_required = True
@@ -50,14 +47,14 @@ try:
if pyexiv2.version_info < REQ_pyexiv2_VERSION:
pyexiv2_required = False
+except AttributeError:
+ pyexiv2_required = False
+
except ImportError:
raise Exception(_("The, pyexiv2, python binding library, to exiv2 is not "
"installed on this computer.\n It can be downloaded from here: %s\n"
"You will need to download at least pyexiv2-%d.%d.%d .") % (
REQ_pyexiv2_VERSION, _DOWNLOAD_LINK))
-
-except AttributeError:
- pyexiv2_required = False
if not pyexiv2_required:
raise Exception(_("The minimum required version for pyexiv2 must be pyexiv2-%d.%d.%d\n"
@@ -65,52 +62,14 @@ if not pyexiv2_required:
REQ_pyexiv2_VERSION, _DOWNLOAD_LINK))
# import the required classes for use in this gramplet
-from pyexiv2 import ExifTag, ImageMetadata, IptcTag, Rational
+from pyexiv2 import ImageMetadata
from gen.plug import Gramplet
from DateHandler import displayer as _dd
import gen.lib
import Utils
-
-#------------------------------------------------
-# Support functions
-#------------------------------------------------
-def _return_month(month):
- """
- returns either an integer of the month number or the abbreviated month name
-
- @param: rmonth -- can be one of:
- 10, "10", or ( "Oct" or "October" )
- """
-
- if isinstance(month, str):
- for s, l, i in _allmonths:
- found = any(month == value for value in [s, l])
- if found:
- month = int(i)
- break
- else:
- for s, l, i in _allmonths:
- if str(month) == i:
- month = l
- break
- return month
-
-def _split_values(text):
- """
- splits a variable into its pieces
- """
-
- if "-" in text:
- separator = "-"
- elif "." in text:
- separator = "."
- elif ":" in text:
- separator = ":"
- else:
- separator = " "
- return [value for value in text.split(separator)]
+import gen.mime
# -----------------------------------------------------------------------------
# Constants
@@ -143,14 +102,57 @@ class MediaMetadata(Gramplet):
"""
def init(self):
- # set all dirty variables to False to begin this gramplet
- _dirty_image = False
+ self.exif_column_width = 15
+ self.exif_widgets = {}
- plugin_image = False
+ # set all dirty variables to False to begin this gramplet
+ self._dirty_image = False
+
+ self.plugin_image = False
mtype = False
- self.set_text(_("No Family Tree loaded."))
- self.set_use_markup(True)
+ rows = gtk.VBox()
+ for items in [
+ ("ActiveImage", _("Active Image"), None, True, [], False, 0, None),
+ ("Artist", _("Artist"), None, False, [], False, 0, None),
+ ("Copyright", _("Copyright"), None, False, [], False, 0, None),
+
+ # Manual Date
+ ("NewDate", _("Date"), None, False, [], False, 0, None),
+
+ # Manual Time
+ ("NewTime", _("Time"), None, False, [], False, 0, None),
+
+ # Latitude and Longitude for this image
+ ("Latitude", _("Latitude"), None, False, [], False, 0, None),
+ ("Longitude", _("Longitude"), None, False, [], False, 0, None),
+
+ # keywords describing your image
+ ("Keywords", _("Keywords"), None, False, [], False, 0, None) ]:
+
+ pos, text, choices, readonly, callback, dirty, default, source = items
+ row = self.make_row(pos, text, choices, readonly, callback, dirty, default, source)
+ rows.pack_start(row, False)
+
+ # separator before description textbox
+ rows.pack_start( gtk.HSeparator(), True )
+
+ # description textbox label
+ label = gtk.Label()
+ label.set_text("%s" % _("Description"))
+ label.set_use_markup(True)
+ rows.pack_start(label, False)
+
+ # description textbox field
+ description_box = gtk.TextView()
+ description_box.set_wrap_mode(gtk.WRAP_WORD)
+ description_box.set_editable(True)
+ self.exif_widgets["Description"] = description_box.get_buffer()
+ rows.pack_start(description_box, True, True, 0)
+
+ self.gui.get_container_widget().remove(self.gui.textview)
+ self.gui.get_container_widget().add_with_viewport(rows)
+ rows.show_all()
def post_init(self):
self.connect_signal("Media", self.update)
@@ -164,19 +166,21 @@ class MediaMetadata(Gramplet):
def main(self): # return false finishes
- self.set_text("")
+ # clear all data entry fields
+ self.clear_metadata(None)
+
active_handle = self.get_active('Media')
active_media = self.dbstate.db.get_object_from_handle(active_handle)
if not active_media:
return
- # get mime type and make sure it is an image
+ # get mime type and make sure it is an image?
mime_type = active_media.get_mime_type()
mtype = gen.mime.get_description(mime_type)
if mime_type and mime_type.startswith("image"):
value, filetype = mime_type.split("/")
- # make sure it is within the allowable media types?
+ # make sure it is a media type that can be used by exiv2?
found = any(_type == filetype for _type in _valid_types)
if not found:
return
@@ -192,58 +196,50 @@ class MediaMetadata(Gramplet):
return
# define plugin media
- plugin_image = ImageMetadata(image_path)
+ self.plugin_image = ImageMetadata(image_path)
# read media metadata
- plugin_image.read()
+ self.plugin_image.read()
# display media description
title = active_media.get_description()
- self.render_text(_("Active media") + ": %s" % title)
- self.append_text("\n")
-
- # display Media mime type
- self.append_text(_("Mime type") + ": " + mtype)
- self.append_text("\n\n")
+ self.exif_widgets["ActiveImage"].set_text(title)
# set up image metadata keys for use in this gramplet
- dataKeyTags = [KeyTag for KeyTag in plugin_image.exif_keys if KeyTag in _DATAMAP ]
+ dataKeyTags = [KeyTag for KeyTag in self.plugin_image.exif_keys if KeyTag in _DATAMAP ]
for KeyTag in dataKeyTags:
# Media image Artist
if KeyTag == ImageArtist:
- self.append_text(_("Artist") + ": " + _get_value(KeyTag, plugin_image))
- self.append_text("\n")
+ self.exif_widgets["Artist"].set_text(_get_value(KeyTag, self.plugin_image)
+ )
# media image Copyright
elif KeyTag == ImageCopyright:
- self.append_text(_("Copyright") + ": " + _get_value(KeyTag, plugin_image))
- self.append_text("\n\n")
+ self.exif_widgets["Copyright"].set_text(_get_value(KeyTag, self.plugin_image)
+ )
# media image DateTime
elif KeyTag == ImageDateTime:
# date1 may come from the image metadata
# date2 may come from the Gramps database
- date1 = _get_value( KeyTag, plugin_image )
+ date1 = _get_value( KeyTag, self.plugin_image )
date2 = active_media.get_date_object()
use_date = date1 or date2
if use_date:
rdate, rtime = self.process_date(use_date)
- self.append_text(_("Date") + ": " + rdate)
- self.append_text("\n")
-
- self.append_text(_("Time") + ": " + rtime)
- self.append_text("\n\n")
+ self.exif_widgets["NewDate"].set_text(rdate)
+ self.exif_widgets["NewTime"].set_text(rtime)
# Latitude and Latitude Reference
elif KeyTag == ImageLatitude:
- latitude = _get_value(ImageLatitude, plugin_image)
- longitude = _get_value(ImageLongitude, plugin_image)
+ latitude = _get_value(ImageLatitude, self.plugin_image)
+ longitude = _get_value(ImageLongitude, self.plugin_image)
# if latitude and longitude exist, display them...
if (latitude and longitude):
@@ -252,32 +248,31 @@ class MediaMetadata(Gramplet):
deg, min, sec = rational_to_dms(latitude)
# Latitude Direction Reference
- LatitudeRef = _get_value(ImageLatitudeRef, plugin_image)
+ LatitudeRef = _get_value(ImageLatitudeRef, self.plugin_image)
- self.append_text(_("Latitude") + ": " + """%s° %s′ %s″ %s""" % (
- deg, min, sec, LatitudeRef)
+ self.exif_widgets["Latitude"].set_text(
+ """%s° %s′ %s″ %s""" % (deg, min, sec, LatitudeRef)
)
- self.append_text("\n")
# split longitude metadata into degrees, minutes, and seconds
deg, min, sec = rational_to_dms(longitude)
# Longitude Direction Reference
- LongitudeRef = _get_value(ImageLongitudeRef, plugin_image)
+ LongitudeRef = _get_value(ImageLongitudeRef, self.plugin_image)
- self.append_text(_("Longitude") + ": " + """%s° %s′ %s″ %s""" % (
- deg, min, sec, LongitudeRef)
+ self.exif_widgets["Longitude"].set_text(
+ """%s° %s′ %s″ %s""" % (deg, min, sec, LongitudeRef)
)
- self.append_text("\n\n")
# Image Description Field
elif KeyTag == ImageDescription:
- self.append_text(_("Description") + ": " + _get_value(ImageDescription, plugin_image))
- self.append_text("\n")
+ self.exif_widgets["Description"].set_text(
+ _get_value(ImageDescription, self.plugin_image)
+ )
# image Keywords
words = ""
- keyWords = _get_value(IptcKeywords, plugin_image)
+ keyWords = _get_value(IptcKeywords, self.plugin_image)
if keyWords:
index = 1
for word in keyWords:
@@ -285,10 +280,91 @@ class MediaMetadata(Gramplet):
if index is not len(keyWords):
words += ","
index += 1
- self.append_text(_("Keywords") + ": " + words)
- self.append_text("\n")
+ self.exif_widgets["Keywords"].set_text(words)
- self.append_text("\n", scroll_to="begin")
+ def make_row(self, pos, text, choices=None, readonly=False, callback_list=[],
+ mark_dirty=False, default=0, source=None):
+ import gtk
+ # Data Entry: Active Person
+ row = gtk.HBox()
+ label = gtk.Label()
+ if readonly:
+ label.set_text("%s" % text)
+ label.set_width_chars(self.exif_column_width)
+ label.set_use_markup(True)
+ self.exif_widgets[pos] = gtk.Label()
+ self.exif_widgets[pos].set_alignment(0.0, 0.5)
+ self.exif_widgets[pos].set_use_markup(True)
+ label.set_alignment(0.0, 0.5)
+ row.pack_start(label, False)
+ row.pack_start(self.exif_widgets[pos], False)
+ else:
+ label.set_text("%s: " % text)
+ label.set_width_chars(self.exif_column_width)
+ label.set_alignment(1.0, 0.5)
+ if choices == None:
+ self.exif_widgets[pos] = gtk.Entry()
+ if mark_dirty:
+ self.exif_widgets[pos].connect("changed", self._mark_dirty_image)
+ row.pack_start(label, False)
+ row.pack_start(self.exif_widgets[pos], True)
+ else:
+ eventBox = gtk.EventBox()
+ self.exif_widgets[pos] = gtk.combo_box_new_text()
+ eventBox.add(self.exif_widgets[pos])
+ for add_type in choices:
+ self.exif_widgets[pos].append_text(add_type)
+ self.exif_widgets[pos].set_active(default)
+ if mark_dirty:
+ self.exif_widgets[pos].connect("changed", self._mark_dirty_image)
+ row.pack_start(label, False)
+ row.pack_start(eventBox, True)
+ if source:
+ label = gtk.Label()
+ label.set_text("%s: " % source[0])
+ label.set_width_chars(self.de_source_width)
+ label.set_alignment(1.0, 0.5)
+ self.exif_widgets[source[1] + ":Label"] = label
+ self.exif_widgets[source[1]] = gtk.Entry()
+ if mark_dirty:
+ self.exif_widgets[source[1]].connect("changed", self._mark_dirty_image)
+ row.pack_start(label, False)
+ row.pack_start(self.exif_widgets[source[1]], True)
+ if not self.show_source:
+ self.exif_widgets[source[1]].hide()
+ for name, text, cbtype, callback in callback_list:
+ if cbtype == "button":
+ label = gtk.Label()
+ label.set_text(text)
+ self.exif_widgets[pos + ":" + name + ":Label"] = label
+ row.pack_start(label, False)
+ icon = gtk.STOCK_EDIT
+ size = gtk.ICON_SIZE_MENU
+ button = gtk.Button()
+ image = gtk.Image()
+ image.set_from_stock(icon, size)
+ button.add(image)
+ button.set_relief(gtk.RELIEF_NONE)
+ button.connect("clicked", callback)
+ self.exif_widgets[pos + ":" + name] = button
+ row.pack_start(button, False)
+ elif cbtype == "checkbox":
+ button = gtk.CheckButton(text)
+ button.set_active(True)
+ button.connect("clicked", callback)
+ self.exif_widgets[pos + ":" + name] = button
+ row.pack_start(button, False)
+ row.show_all()
+ return row
+
+ def clear_metadata(self, obj):
+ """
+ clears all data fields to nothing
+ """
+
+ for key in [ "ActiveImage", "Artist", "Copyright", "NewDate", "NewTime",
+ "Latitude", "Longitude", "Keywords", "Description" ]:
+ self.exif_widgets[key].set_text( "" )
def process_date(self, tmpDate):
"""
@@ -395,3 +471,42 @@ def rational_to_dms(rational_coords):
rs, rest = rs.split("/")
return rd, rm, rs
+
+#------------------------------------------------
+# Support functions
+#------------------------------------------------
+def _return_month(month):
+ """
+ returns either an integer of the month number or the abbreviated month name
+
+ @param: rmonth -- can be one of:
+ 10, "10", or ( "Oct" or "October" )
+ """
+
+ if isinstance(month, str):
+ for s, l, i in _allmonths:
+ found = any(month == value for value in [s, l])
+ if found:
+ month = int(i)
+ break
+ else:
+ for s, l, i in _allmonths:
+ if str(month) == i:
+ month = l
+ break
+ return month
+
+def _split_values(text):
+ """
+ splits a variable into its pieces
+ """
+
+ if "-" in text:
+ separator = "-"
+ elif "." in text:
+ separator = "."
+ elif ":" in text:
+ separator = ":"
+ else:
+ separator = " "
+ return [value for value in text.split(separator)]