# # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2005 Donald N. Allingham # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id$ #------------------------------------------------------------------------- # # Standard python modules # #------------------------------------------------------------------------- import os import urlparse from gettext import gettext as _ #------------------------------------------------------------------------- # # GTK/Gnome modules # #------------------------------------------------------------------------- import gobject import gtk import gnome import gnome.ui import gtk.glade try: from gnomecanvas import CanvasGroup, CanvasRect, CanvasPixbuf, CanvasText except: from gnome.canvas import CanvasGroup, CanvasRect, CanvasPixbuf, CanvasText #------------------------------------------------------------------------- # # gramps modules # #------------------------------------------------------------------------- import const import Utils import GrampsKeys import NameDisplay import PluginMgr import RelLib import RelImage import ListModel import SelectObject import GrampsMime import Sources import DateEdit import DateHandler import Date import ImgManip import Spell from QuestionDialog import ErrorDialog from DdTargets import DdTargets _IMAGEX = 140 _IMAGEY = 150 _PAD = 5 _last_path = "" _iconlist_refs = [] #------------------------------------------------------------------------- # # ImageSelect class # #------------------------------------------------------------------------- class ImageSelect: def __init__(self, path, db, parent, parent_window=None): """Creates an edit window. Associates a person with the window.""" self.path = path; self.db = db self.dataobj = None self.parent = parent self.parent_window = parent_window self.canvas_list = {} self.p_map = {} self.canvas = None def add_thumbnail(self, photo): "should be overrridden" pass def load_images(self): "should be overrridden" pass def internal_toggled(self, obj): self.fname.set_sensitive(not obj.get_active()) def create_add_dialog(self): """Create the gnome dialog for selecting a new photo and entering its description.""" if self.path == '': return self.glade = gtk.glade.XML(const.imageselFile,"imageSelect","gramps") self.window = self.glade.get_widget("imageSelect") self.fname = self.glade.get_widget("fname") self.image = self.glade.get_widget("image") self.internal = self.glade.get_widget("internal") self.internal.connect('toggled',self.internal_toggled) self.description = self.glade.get_widget("photoDescription") self.temp_name = "" Utils.set_titles(self.window,self.glade.get_widget('title'), _('Select a media object')) self.glade.signal_autoconnect({ "on_fname_update_preview" : self.on_name_changed, "on_help_imagesel_clicked" : self.on_help_imagesel_clicked, }) if os.path.isdir(_last_path): self.fname.set_current_folder(_last_path) if self.parent_window: self.window.set_transient_for(self.parent_window) self.window.show() self.val = self.window.run() if self.val == gtk.RESPONSE_OK: self.on_savephoto_clicked() self.window.destroy() def on_help_imagesel_clicked(self,obj): """Display the relevant portion of GRAMPS manual""" gnome.help_display('gramps-manual','gramps-edit-quick') self.val = self.window.run() def on_name_changed(self, obj): """The filename has changed. Verify it and load the picture.""" filename = unicode(self.fname.get_filename()) basename = os.path.basename(filename) (root,ext) = os.path.splitext(basename) old_title = unicode(self.description.get_text()) if old_title == "" or old_title == self.temp_name: self.description.set_text(root) self.temp_name = root if os.path.isfile(filename): mtype = GrampsMime.get_type(filename) if mtype and mtype.startswith("image"): image = RelImage.scale_image(filename,const.thumbScale) self.image.set_from_pixbuf(image) else: i = Utils.find_mime_type_pixbuf(mtype) self.image.set_from_pixbuf(i) def on_savephoto_clicked(self): """Save the photo in the dataobj object. (Required function)""" global _last_path filename = self.fname.get_filename() _last_path = os.path.dirname(filename) description = unicode(self.description.get_text()) internal = self.internal.get_active() if not internal: if os.path.exists(filename) == 0: msgstr = _("Cannot import %s") msgstr2 = _("The filename supplied could not be found.") ErrorDialog(msgstr % filename, msgstr2) return already_imported = None trans = self.db.transaction_begin() for o_id in self.db.get_media_object_handles(): o = self.db.get_object_from_handle(o_id) if o.get_path() == filename: already_imported = o break if already_imported: oref = RelLib.MediaRef() oref.set_reference_handle(already_imported.get_handle()) self.dataobj.add_media_reference(oref) self.add_thumbnail(oref) else: mtype = GrampsMime.get_type(filename) mobj = RelLib.MediaObject() if description == "": description = os.path.basename(filename) mobj.set_description(description) mobj.set_mime_type(mtype) mobj.set_path(filename) else: trans = self.db.transaction_begin() mobj = RelLib.MediaObject() mobj.set_description(description) mobj.set_mime_type(None) self.savephoto(mobj,trans) self.db.transaction_commit(trans,'Edit Media Objects') self.parent.lists_changed = 1 self.load_images() def savephoto(self, photo, transaction): """Save the photo in the dataobj object - must be overridden""" pass _drag_targets = [ ('STRING', 0, 0), ('text/plain',0,0), ('text/uri-list',0,2), ('application/x-rootwin-drop',0,1)] #------------------------------------------------------------------------- # # Gallery class - This class handles all the logic underlying a # picture gallery. This class does not load or contain the widget # data structure to actually display the gallery. # #------------------------------------------------------------------------- class Gallery(ImageSelect): def __init__(self, dataobj, commit, path, icon_list, db, parent, parent_window=None): ImageSelect.__init__(self, path, db, parent, parent_window) self.commit = commit if path: icon_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, [DdTargets.MEDIAOBJ.target()]+_drag_targets, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) icon_list.connect('event',self.item_event) icon_list.connect("drag_data_received", self.on_photolist_drag_data_received) icon_list.connect("drag_data_get", self.on_photolist_drag_data_get) icon_list.connect("drag_begin", self.on_drag_begin) _iconlist_refs.append(icon_list) self.in_event = 0 # Remember arguments self.path = path; self.dataobj = dataobj; self.iconlist = icon_list; self.root = self.iconlist.root() self.old_media_list = [RelLib.MediaRef(ref) for ref in dataobj.get_media_list()] # Local object variables self.y = 0 self.remember_x = -1 self.remember_y = -1 self.button = None self.drag_item = None self.sel = None self.photo = None def close(self): self.iconlist.hide() if self.canvas_list: for a in self.canvas_list.values(): a[0].destroy() a[1].destroy() a[2].destroy() self.p_map = None self.canvas_list = None def on_canvas1_event(self,obj,event): """ Handle resize events over the canvas, redrawing if the size changes """ pass def on_drag_begin(self,obj,context): if const.dnd_images: handle = self.sel_obj.get_reference_handle() media_obj = self.db.get_object_from_handle(handle) pix = ImgManip.get_thumbnail_image(media_obj.get_path(), media_obj.get_mime_type()) context.set_icon_pixbuf(pix,0,0) def item_event(self, widget, event=None): if self.in_event: return False self.in_event = 1 if self.button and event.type == gtk.gdk.MOTION_NOTIFY : if widget.drag_check_threshold(int(self.remember_x),int(self.remember_y), int(event.x),int(event.y)): self.drag_item = widget.get_item_at(self.remember_x, self.remember_y) icon_index = self.get_index(widget,event.x,event.y) if icon_index == -1: return for i in self.dataobj.get_media_list(): handle = i.get_reference_handle() m = self.db.get_object_from_handle(handle) media_list = self.dataobj.get_media_list() if icon_index >= len(media_list): return False self.sel_obj = media_list[icon_index] handle = self.sel_obj.get_reference_handle() media_obj = self.db.get_object_from_handle(handle) if self.drag_item: widget.drag_begin([DdTargets.MEDIAOBJ.target()]+_drag_targets, gtk.gdk.ACTION_COPY|gtk.gdk.ACTION_MOVE, self.button, event) self.in_event = 0 return True style = self.iconlist.get_style() if event.type == gtk.gdk.BUTTON_PRESS: if event.button == 1: # Remember starting position. item = widget.get_item_at(event.x,event.y) if item: (i,t,b,self.photo,oid) = self.p_map[item] t.set(fill_color_gdk=style.fg[gtk.STATE_SELECTED]) b.set(fill_color_gdk=style.bg[gtk.STATE_SELECTED]) if self.sel: (i,t,b,photo,oid) = self.p_map[self.sel] t.set(fill_color_gdk=style.fg[gtk.STATE_NORMAL]) b.set(fill_color_gdk=style.bg[gtk.STATE_NORMAL]) self.sel = item self.remember_x = event.x self.remember_y = event.y self.button = event.button self.in_event = 0 return True elif event.button == 3: item = widget.get_item_at(event.x,event.y) if item: (i,t,b,self.photo,oid) = self.p_map[item] self.show_popup(self.photo,event) self.in_event = 0 return True elif event.type == gtk.gdk.BUTTON_RELEASE: self.button = 0 elif event.type == gtk.gdk.MOTION_NOTIFY: if event.state & gtk.gdk.BUTTON1_MASK: # Get the new position and move by the difference new_x = event.x new_y = event.y self.remember_x = new_x self.remember_y = new_y self.in_event = 0 return True if event.type == gtk.gdk.EXPOSE: self.load_images() self.in_event = 0 return False def savephoto(self,photo,transaction): """Save the photo in the dataobj object. (Required function)""" self.db.add_object(photo,transaction) oref = RelLib.MediaRef() oref.set_reference_handle(photo.get_handle()) self.dataobj.add_media_reference(oref) def add_thumbnail(self, photo): """Scale the image and add it to the IconList.""" oid = photo.get_reference_handle() media_obj = self.db.get_object_from_handle(oid) if self.canvas_list.has_key(photo): (grp,item,text,x,y) = self.canvas_list[photo] if x != self.cx or y != self.cy: grp.move(self.cx-x,self.cy-y) else: description = media_obj.get_description() if len(description) > 20: description = "%s..." % description[0:20] try: mtype = media_obj.get_mime_type() image = ImgManip.get_thumbnail_image(media_obj.get_path(),mtype) except gobject.GError,msg: ErrorDialog(str(msg)) image = gtk.gdk.pixbuf_new_from_file(const.icon) except: image = gtk.gdk.pixbuf_new_from_file(const.icon) x = image.get_width() y = image.get_height() grp = self.root.add(CanvasGroup,x=self.cx,y=self.cy) xloc = (_IMAGEX-x)/2 yloc = (_IMAGEY-y)/2 style = self.iconlist.get_style() box = grp.add(CanvasRect,x1=0,x2=_IMAGEX,y1=_IMAGEY-20, y2=_IMAGEY, fill_color_gdk=style.bg[gtk.STATE_NORMAL]) item = grp.add(CanvasPixbuf, pixbuf=image,x=xloc, y=yloc) text = grp.add(CanvasText, x=_IMAGEX/2, anchor=gtk.ANCHOR_CENTER, justification=gtk.JUSTIFY_CENTER, y=_IMAGEY-10, text=description) # make sure that the text string doesn't exceed the size of the box bnds = text.get_bounds() while bnds[0] <0: description = description[0:-4] + "..." text.set(text=description) bnds = text.get_bounds() for i in [ item, text, box, grp ] : self.p_map[i] = (item,text,box,photo,oid) i.show() self.canvas_list[photo] = (grp,item,text,self.cx,self.cy) self.cx += _PAD + _IMAGEX if self.cx + _PAD + _IMAGEX > self.x: self.cx = _PAD self.cy += _PAD + _IMAGEY def load_images(self): """clears the currentImages list to free up any cached Imlibs. Then add each photo in the place's list of photos to the photolist window.""" self.pos = 0 self.cx = _PAD self.cy = _PAD (self.x,self.y) = self.iconlist.get_size() self.max = (self.x)/(_IMAGEX+_PAD) for photo in self.dataobj.get_media_list(): self.add_thumbnail(photo) if self.cy > self.y: self.iconlist.set_scroll_region(0,0,self.x,self.cy) else: self.iconlist.set_scroll_region(0,0,self.x,self.y) if self.dataobj.get_media_list(): Utils.bold_label(self.parent.gallery_label) else: Utils.unbold_label(self.parent.gallery_label) def get_index(self,obj,x,y): x_offset = int(x)/(_IMAGEX+_PAD) y_offset = int(y)/(_IMAGEY+_PAD) index = (y_offset*(self.max))+x_offset return min(index,len(self.dataobj.get_media_list())) def on_photolist_drag_data_received(self,w, context, x, y, data, info, time): if data and data.format == 8: icon_index = self.get_index(w,x,y) d = data.data.replace('\0',' ').strip() protocol,site,mfile,j,k,l = urlparse.urlparse(d) if protocol == "file": name = mfile mime = GrampsMime.get_type(name) photo = RelLib.MediaObject() photo.set_path(name) photo.set_mime_type(mime) basename = os.path.basename(name) (root,ext) = os.path.splitext(basename) photo.set_description(root) trans = self.db.transaction_begin() self.savephoto(photo,trans) if GrampsKeys.get_media_reference() == 0: photo.set_path(name) self.db.transaction_commit(trans,_("Drag Media Object")) self.parent.lists_changed = 1 if GrampsKeys.get_media_global(): GlobalMediaProperties(self.db,photo, self,self.parent_window) elif protocol != "": import urllib u = urllib.URLopener() try: tfile,headers = u.retrieve(d) except (IOError,OSError), msg: t = _("Could not import %s") % d ErrorDialog(t,str(msg)) return mime = GrampsMime.get_type(tfile) photo = RelLib.MediaObject() photo.set_mime_type(mime) photo.set_description(d) photo.set_path(tfile) trans = self.db.transaction_begin() self.db.add_object(photo,trans) self.db.transaction_commit(trans,_("Drag Media Object")) oref = RelLib.MediaRef() oref.set_reference_handle(photo.get_handle()) self.dataobj.add_media_reference(oref) # This code seems to be reproducing what is already done. # try: # photo.set_path(name) # except: # photo.set_path(tfile) # return self.add_thumbnail(oref) self.parent.lists_changed = 1 if GrampsKeys.get_media_global(): GlobalMediaProperties(self.db,photo, self,self.parent_window) else: if self.db.has_object_handle(data.data): icon_index = self.get_index(w,x,y) index = 0 for p in self.dataobj.get_media_list(): if data.data == p.get_reference_handle(): if index == icon_index or icon_index == -1: return else: nl = self.dataobj.get_media_list() item = nl[index] if icon_index == 0: del nl[index] nl = [item] + nl else: del nl[index] nl = nl[0:icon_index] + [item] + nl[icon_index:] self.dataobj.set_media_list(nl) self.parent.lists_changed = 1 self.load_images() return index = index + 1 oref = RelLib.MediaRef() oref.set_reference_handle(data.data) self.dataobj.add_media_reference(oref) self.add_thumbnail(oref) self.parent.lists_changed = 1 if GrampsKeys.get_media_global(): LocalMediaProperties(oref,self.path,self,self.parent_window) def on_photolist_drag_data_get(self,w, context, selection_data, info, time): if info == 1: return data = self.p_map[self.drag_item] selection_data.set(selection_data.target, 8, data[4]) self.drag_item = None def on_add_media_clicked(self, obj): """User wants to add a new photo. Create a dialog to find out which photo they want.""" self.create_add_dialog() def on_select_media_clicked(self,obj): """User wants to add a new object that is already in a database. Create a dialog to find out which object they want.""" s_o = SelectObject.SelectObject(self.db,_("Select an Object")) obj = s_o.run() if not obj: return oref = RelLib.MediaRef() oref.set_reference_handle(obj.get_handle()) self.dataobj.add_media_reference(oref) self.add_thumbnail(oref) self.parent.lists_changed = 1 self.load_images() def on_delete_media_clicked(self, obj): """User wants to delete a new photo. Remove it from the displayed thumbnails, and remove it from the dataobj photo list.""" if self.sel: (i,t,b,photo,oid) = self.p_map[self.sel] val = self.canvas_list[photo] val[0].hide() val[1].hide() val[2].hide() l = self.dataobj.get_media_list() l.remove(photo) self.dataobj.set_media_list(l) self.parent.lists_changed = 1 self.load_images() def on_edit_media_clicked(self, obj): """User wants to delete a new photo. Remove it from the displayed thumbnails, and remove it from the dataobj photo list.""" if self.sel: (i,t,b,photo,oid) = self.p_map[self.sel] base_obj = self.db.get_object_from_handle(photo.get_reference_handle()) if base_obj.get_mime_type(): LocalMediaProperties(photo,self.path,self,self.parent_window) else: import NoteEdit NoteEdit.NoteEditor(base_obj,self.parent,self.parent_window, self.note_callback) def note_callback(self,data): trans = self.db.transaction_begin() self.db.commit_media_object(data,trans) self.db.transaction_commit(trans,_("Edit Media Object")) def show_popup(self, photo, event): """Look for right-clicks on a picture and create a popup menu of the available actions.""" menu = gtk.Menu() menu.set_title(_("Media Object")) obj = self.db.get_object_from_handle(photo.get_reference_handle()) mtype = obj.get_mime_type() progname = GrampsMime.get_application(mtype) if progname and len(progname) > 1: Utils.add_menuitem(menu,_("Open in %s") % progname[1], photo,self.popup_view_photo) if mtype and mtype.startswith("image"): Utils.add_menuitem(menu,_("Edit with the GIMP"), photo,self.popup_edit_photo) Utils.add_menuitem(menu,_("Edit Object Properties"),photo, self.popup_change_description) menu.popup(None,None,None,event.button,event.time) def popup_view_photo(self, obj): """Open this picture in a picture viewer""" photo = obj.get_data('o') Utils.view_photo(self.db.get_object_from_handle(photo.get_reference_handle())) def popup_edit_photo(self, obj): """Open this picture in a picture editor""" photo = obj.get_data('o') if os.fork() == 0: obj = self.db.get_object_from_handle(photo.get_reference_handle()) os.execvp(const.editor,[const.editor, obj.get_path()]) def popup_change_description(self, obj): """Bring up a window allowing the user to edit the description of a picture.""" photo = obj.get_data('o') LocalMediaProperties(photo,self.path,self) #------------------------------------------------------------------------- # # LocalMediaProperties # #------------------------------------------------------------------------- class LocalMediaProperties: def __init__(self,photo,path,parent,parent_window=None): self.parent = parent if photo: if self.parent.parent.child_windows.has_key(photo): self.parent.parent.child_windows[photo].present(None) return else: self.win_key = photo else: self.win_key = self self.child_windows = {} self.photo = photo self.db = parent.db self.obj = self.db.get_object_from_handle(photo.get_reference_handle()) self.alist = photo.get_attribute_list()[:] self.lists_changed = 0 fname = self.obj.get_path() self.change_dialog = gtk.glade.XML(const.imageselFile,"change_description","gramps") title = _('Media Reference Editor') self.window = self.change_dialog.get_widget('change_description') Utils.set_titles(self.window, self.change_dialog.get_widget('title'), title) descr_window = self.change_dialog.get_widget("description") self.pixmap = self.change_dialog.get_widget("pixmap") self.attr_type = self.change_dialog.get_widget("attr_type") self.attr_value = self.change_dialog.get_widget("attr_value") self.attr_details = self.change_dialog.get_widget("attr_details") self.attr_list = self.change_dialog.get_widget("attr_list") titles = [(_('Attribute'),0,150),(_('Value'),0,100)] self.attr_label = self.change_dialog.get_widget("attr_local") self.notes_label = self.change_dialog.get_widget("notes_local") self.flowed = self.change_dialog.get_widget("flowed") self.preform = self.change_dialog.get_widget("preform") self.atree = ListModel.ListModel(self.attr_list,titles, self.on_attr_list_select_row, self.on_update_attr_clicked) self.slist = self.change_dialog.get_widget("src_list") self.sources_label = self.change_dialog.get_widget("source_label") if self.obj: self.srcreflist = [RelLib.SourceRef(ref) for ref in self.photo.get_source_references()] else: self.srcreflist = [] self.sourcetab = Sources.SourceTab(self.srcreflist,self, self.change_dialog, self.window, self.slist, self.change_dialog.get_widget('add_src'), self.change_dialog.get_widget('edit_src'), self.change_dialog.get_widget('del_src')) descr_window.set_text(self.obj.get_description()) mtype = self.obj.get_mime_type() self.pix = ImgManip.get_thumbnail_image(self.obj.get_path(),mtype) self.pixmap.set_from_pixbuf(self.pix) self.change_dialog.get_widget("private").set_active(photo.get_privacy()) self.change_dialog.get_widget("gid").set_text(self.obj.get_gramps_id()) self.change_dialog.get_widget("path").set_text(fname) mt = Utils.get_mime_description(mtype) self.change_dialog.get_widget("type").set_text(mt) self.notes = self.change_dialog.get_widget("notes") self.spell = Spell.Spell(self.notes) if self.photo.get_note(): self.notes.get_buffer().set_text(self.photo.get_note()) Utils.bold_label(self.notes_label) if self.photo.get_note_format() == 1: self.preform.set_active(1) else: self.flowed.set_active(1) self.change_dialog.signal_autoconnect({ "on_add_attr_clicked": self.on_add_attr_clicked, "on_notebook_switch_page": self.on_notebook_switch_page, "on_update_attr_clicked": self.on_update_attr_clicked, "on_delete_attr_clicked" : self.on_delete_attr_clicked, "on_help_clicked" : self.on_help_clicked, "on_ok_clicked" : self.on_ok_clicked, "on_cancel_clicked" : self.close, "on_local_delete_event" : self.on_delete_event, }) media_obj = self.db.get_object_from_handle(self.photo.get_reference_handle()) gnote = self.change_dialog.get_widget('global_notes') spell = Spell.Spell(gnote) global_note = gnote.get_buffer() global_note.insert_at_cursor(media_obj.get_note()) self.redraw_attr_list() if parent_window: self.window.set_transient_for(parent_window) self.add_itself_to_menu() self.window.show() def on_delete_event(self,obj,b): self.close_child_windows() self.remove_itself_from_menu() def close(self,obj): self.close_child_windows() self.remove_itself_from_menu() self.window.destroy() def close_child_windows(self): for child_window in self.child_windows.values(): child_window.close(None) self.child_windows = {} def add_itself_to_menu(self): self.parent.parent.child_windows[self.win_key] = self label = _('Media Reference') self.parent_menu_item = gtk.MenuItem(label) self.parent_menu_item.set_submenu(gtk.Menu()) self.parent_menu_item.show() self.parent.parent.winsmenu.append(self.parent_menu_item) self.winsmenu = self.parent_menu_item.get_submenu() self.menu_item = gtk.MenuItem(_('Reference Editor')) self.menu_item.connect("activate",self.present) self.menu_item.show() self.winsmenu.append(self.menu_item) def remove_itself_from_menu(self): del self.parent.parent.child_windows[self.win_key] self.menu_item.destroy() self.winsmenu.destroy() self.parent_menu_item.destroy() def present(self,obj): self.window.present() def redraw_attr_list(self): self.atree.clear() self.amap = {} for attr in self.alist: d = [attr.get_type(),attr.get_value()] node = self.atree.add(d,attr) self.amap[str(attr)] = node if self.alist: Utils.bold_label(self.attr_label) else: Utils.unbold_label(self.attr_label) def on_notebook_switch_page(self,obj,junk,page): t = self.notes.get_buffer() text = unicode(t.get_text(t.get_start_iter(),t.get_end_iter(),False)) if text: Utils.bold_label(self.notes_label) else: Utils.unbold_label(self.notes_label) def on_apply_clicked(self): priv = self.change_dialog.get_widget("private").get_active() t = self.notes.get_buffer() text = unicode(t.get_text(t.get_start_iter(),t.get_end_iter(),False)) note = self.photo.get_note() format = self.preform.get_active() if text != note or priv != self.photo.get_privacy(): self.photo.set_note(text) self.photo.set_privacy(priv) self.parent.lists_changed = 1 self.parent.parent.lists_changed = 1 if format != self.photo.get_note_format(): self.photo.set_note_format(format) if self.lists_changed: self.photo.set_attribute_list(self.alist) self.photo.set_source_reference_list(self.srcreflist) self.parent.lists_changed = 1 self.parent.parent.lists_changed = 1 trans = self.db.transaction_begin() self.db.commit_media_object(self.obj,trans) self.db.transaction_commit(trans,_("Edit Media Object")) def on_help_clicked(self, obj): """Display the relevant portion of GRAMPS manual""" gnome.help_display('gramps-manual','gramps-edit-complete') def on_ok_clicked(self,obj): self.on_apply_clicked() self.close(obj) def on_attr_list_select_row(self,obj): store,node = self.atree.get_selected() if node: attr = self.atree.get_object(node) self.attr_type.set_label(attr.get_type()) self.attr_value.set_text(attr.get_value()) else: self.attr_type.set_label('') self.attr_value.set_text('') def attr_callback(self,attr): self.redraw_attr_list() self.atree.select_iter(self.amap[str(attr)]) def on_update_attr_clicked(self,obj): import AttrEdit store,node = self.atree.get_selected() if node: attr = self.atree.get_object(node) AttrEdit.AttributeEditor(self,attr,"Media Object", PluginMgr.get_image_attributes(), self.attr_callback) def on_delete_attr_clicked(self,obj): if Utils.delete_selected(obj,self.alist): self.lists_changed = 1 self.redraw_attr_list() def on_add_attr_clicked(self,obj): import AttrEdit AttrEdit.AttributeEditor(self,None,"Media Object", PluginMgr.get_image_attributes(), self.attr_callback) #------------------------------------------------------------------------- # # GlobalMediaProperties # #------------------------------------------------------------------------- class GlobalMediaProperties: def __init__(self,db,obj,parent,parent_window=None): self.parent = parent self.dp = DateHandler.parser self.dd = DateHandler.displayer if obj: if self.parent.parent.child_windows.has_key(obj.get_handle()): self.parent.parent.child_windows[obj.get_handle()].present(None) return else: self.win_key = obj.get_handle() else: self.win_key = self self.child_windows = {} self.obj = obj self.lists_changed = 0 self.db = db if obj: self.date_object = Date.Date(self.obj.get_date_object()) self.alist = self.obj.get_attribute_list()[:] self.refs = 0 else: self.date_object = Date.Date() self.alist = [] self.refs = 1 self.path = self.db.get_save_path() self.change_dialog = gtk.glade.XML(const.imageselFile, "change_global","gramps") mode = not self.db.readonly title = _('Media Properties Editor') self.window = self.change_dialog.get_widget('change_global') self.date_entry = self.change_dialog.get_widget('date') self.date_entry.set_editable(mode) if self.obj: self.date_entry.set_text(self.dd.display(self.date_object)) Utils.set_titles(self.window, self.change_dialog.get_widget('title'),title) self.descr_window = self.change_dialog.get_widget("description") self.descr_window.set_editable(mode) self.notes = self.change_dialog.get_widget("notes") self.notes.set_editable(mode) self.spell = Spell.Spell(self.notes) self.date_edit = self.change_dialog.get_widget("date_edit") self.date_edit.set_sensitive(mode) self.date_check = DateEdit.DateEdit( self.date_object, self.date_entry, self.date_edit, self.window) self.pixmap = self.change_dialog.get_widget("pixmap") self.attr_type = self.change_dialog.get_widget("attr_type") self.attr_value = self.change_dialog.get_widget("attr_value") self.attr_details = self.change_dialog.get_widget("attr_details") self.attr_list = self.change_dialog.get_widget("attr_list") self.attr_label = self.change_dialog.get_widget("attrGlobal") self.notes_label = self.change_dialog.get_widget("notesGlobal") self.refs_label = self.change_dialog.get_widget("refsGlobal") self.flowed = self.change_dialog.get_widget("global_flowed") self.flowed.set_sensitive(mode) self.preform = self.change_dialog.get_widget("global_preform") self.preform.set_sensitive(mode) titles = [(_('Attribute'),0,150),(_('Value'),1,100)] self.atree = ListModel.ListModel(self.attr_list,titles, self.on_attr_list_select_row, self.on_update_attr_clicked) self.slist = self.change_dialog.get_widget("src_list") self.sources_label = self.change_dialog.get_widget("sourcesGlobal") if self.obj: self.srcreflist = [RelLib.SourceRef(ref) for ref in self.obj.get_source_references()] else: self.srcreflist = [] self.sourcetab = Sources.SourceTab( self.srcreflist,self, self.change_dialog, self.window, self.slist, self.change_dialog.get_widget('gl_add_src'), self.change_dialog.get_widget('gl_edit_src'), self.change_dialog.get_widget('gl_del_src')) self.descr_window.set_text(self.obj.get_description()) mtype = self.obj.get_mime_type() if mtype: pb = ImgManip.get_thumbnail_image(self.obj.get_path(),mtype) self.pixmap.set_from_pixbuf(pb) descr = Utils.get_mime_description(mtype) self.change_dialog.get_widget("type").set_text(descr) else: self.change_dialog.get_widget("type").set_text(_('Note')) self.pixmap.hide() self.change_dialog.get_widget("gid").set_text(self.obj.get_gramps_id()) self.update_info() if self.obj.get_note(): self.notes.get_buffer().set_text(self.obj.get_note()) Utils.bold_label(self.notes_label) if self.obj.get_note_format() == 1: self.preform.set_active(1) else: self.flowed.set_active(1) self.change_dialog.signal_autoconnect({ "on_cancel_clicked" : self.close, "on_up_clicked" : self.on_up_clicked, "on_down_clicked" : self.on_down_clicked, "on_ok_clicked" : self.on_ok_clicked, "on_apply_clicked" : self.on_apply_clicked, "on_add_attr_clicked" : self.on_add_attr_clicked, "on_notebook_switch_page": self.on_notebook_switch_page, "on_delete_attr_clicked" : self.on_delete_attr_clicked, "on_update_attr_clicked" : self.on_update_attr_clicked, "on_help_clicked" : self.on_help_clicked, "on_global_delete_event" : self.on_delete_event, }) for name in ['gl_del_src','gl_add_src','add_attr','del_attr','ok']: self.change_dialog.get_widget(name).set_sensitive(mode) self.redraw_attr_list() if parent_window: self.window.set_transient_for(parent_window) self.add_itself_to_menu() self.window.show() if not self.refs: Utils.temp_label(self.refs_label,self.window) gobject.idle_add(self.display_refs) def on_delete_event(self,obj,b): self.close_child_windows() self.remove_itself_from_menu() def close(self,obj): self.close_child_windows() self.remove_itself_from_menu() self.window.destroy() def close_child_windows(self): for child_window in self.child_windows.values(): child_window.close(None) self.child_windows = {} def add_itself_to_menu(self): self.parent.parent.child_windows[self.win_key] = self label = _('Media Object') self.parent_menu_item = gtk.MenuItem(label) self.parent_menu_item.set_submenu(gtk.Menu()) self.parent_menu_item.show() self.parent.parent.winsmenu.append(self.parent_menu_item) self.winsmenu = self.parent_menu_item.get_submenu() self.menu_item = gtk.MenuItem(_('Properties Editor')) self.menu_item.connect("activate",self.present) self.menu_item.show() self.winsmenu.append(self.menu_item) def remove_itself_from_menu(self): del self.parent.parent.child_windows[self.win_key] self.menu_item.destroy() self.winsmenu.destroy() self.parent_menu_item.destroy() def present(self,obj): self.window.present() def on_up_clicked(self,obj): store,node = self.atree.get_selected() if node: row = self.atree.get_row(node) if row != 0: self.atree.select_row(row-1) def on_down_clicked(self,obj): model,node = self.atree.get_selected() if not node: return row = self.atree.get_row(node) self.atree.select_row(row+1) def update_info(self): fname = self.obj.get_path() self.change_dialog.get_widget("path").set_text(fname) def redraw_attr_list(self): self.atree.clear() self.amap = {} for attr in self.alist: d = [attr.get_type(),attr.get_value()] node = self.atree.add(d,attr) self.amap[str(attr)] = node if self.alist: Utils.bold_label(self.attr_label) else: Utils.unbold_label(self.attr_label) def button_press(self,obj): store,node = self.refmodel.selection.get_selected() if not node: return def display_refs(self): self.refs = 1 (person_list,family_list,event_list,place_list,source_list ) = Utils.get_media_referents(self.obj.get_handle(),self.db) any = person_list or family_list or event_list or place_list or source_list titles = [(_('Type'),0,150),(_('ID'),1,75),(_('Name'),2,150)] self.refmodel = ListModel.ListModel( self.change_dialog.get_widget("refinfo"), titles,event_func=self.button_press) for handle in person_list: person = self.db.get_person_from_handle(handle) name = NameDisplay.displayer.display(person) gramps_id = person.get_gramps_id() self.refmodel.add([_("Person"),gramps_id,name]) for handle in family_list: family = self.db.get_family_from_handle(handle) name = Utils.family_name(family,self.db) gramps_id = family.get_gramps_id() self.refmodel.add([_("Family"),gramps_id,name]) for handle in event_list: event = self.db.get_event_from_handle(handle) name = event.get_name() gramps_id = event.get_gramps_id() self.refmodel.add([_("Event"),gramps_id,name]) for handle in place_list: place = self.db.get_place_from_handle(handle) name = place.get_title() gramps_id = place.get_gramps_id() self.refmodel.add([_("Place"),gramps_id,name]) for handle in source_list: source = self.db.get_source_from_handle(handle) name = source.get_title() gramps_id = source.get_gramps_id() self.refmodel.add([_("Source"),gramps_id,name]) if any: Utils.bold_label(self.refs_label,self.window) else: Utils.unbold_label(self.refs_label,self.window) def on_notebook_switch_page(self,obj,junk,page): if page == 3 and not self.refs: Utils.temp_label(self.refs_label,self.window) gobject.idle_add(self.display_refs) t = self.notes.get_buffer() text = unicode(t.get_text(t.get_start_iter(),t.get_end_iter(),False)) if text: Utils.bold_label(self.notes_label) else: Utils.unbold_label(self.notes_label) def get_place(self,field,makenew=0): text = unicode(field.get_text().strip()) if text: if self.pdmap.has_key(text): return self.pdmap[text] elif makenew: place = RelLib.Place() place.set_title(text) trans = self.db.transaction_begin() self.db.add_place(place,trans) self.db.transaction_commit(trans,_('Add Place (%s)' % text)) self.pdmap[text] = place.get_handle() self.add_places.append(place) return place.get_handle() else: return None else: return None def on_apply_clicked(self, obj): t = self.notes.get_buffer() text = unicode(t.get_text(t.get_start_iter(),t.get_end_iter(),False)) desc = unicode(self.descr_window.get_text()) note = self.obj.get_note() path = self.change_dialog.get_widget('path').get_text() self.obj.set_path(path) if not self.date_object.is_equal(self.obj.get_date_object()): self.obj.set_date_object(self.date_object) format = self.preform.get_active() if text != note or desc != self.obj.get_description(): self.obj.set_note(text) self.obj.set_description(desc) if format != self.obj.get_note_format(): self.obj.set_note_format(format) if self.lists_changed: self.obj.set_attribute_list(self.alist) self.obj.set_source_reference_list(self.srcreflist) trans = self.db.transaction_begin() self.db.commit_media_object(self.obj,trans) self.db.transaction_commit(trans,_("Edit Media Object")) def on_help_clicked(self, obj): """Display the relevant portion of GRAMPS manual""" gnome.help_display('gramps-manual','adv-media') def on_ok_clicked(self, obj): self.on_apply_clicked(obj) self.close(obj) def on_attr_list_select_row(self,obj): store,node = self.atree.get_selected() if node: attr = self.atree.get_object(node) self.attr_type.set_label(attr.get_type()) self.attr_value.set_text(attr.get_value()) else: self.attr_type.set_label('') self.attr_value.set_text('') def attr_callback(self,attr): self.redraw_attr_list() self.atree.select_iter(self.amap[str(attr)]) def on_update_attr_clicked(self,obj): import AttrEdit store,node = self.atree.get_selected() if node: attr = self.atree.get_object(node) AttrEdit.AttributeEditor(self,attr,"Media Object", PluginMgr.get_image_attributes(), self.attr_callback) def on_delete_attr_clicked(self,obj): if Utils.delete_selected(obj,self.alist): self.lists_changed = 1 self.redraw_attr_list() def on_add_attr_clicked(self,obj): import AttrEdit AttrEdit.AttributeEditor(self,None,"Media Object", PluginMgr.get_image_attributes(), self.attr_callback) class DeleteMediaQuery: def __init__(self,media_handle,db,the_lists): self.db = db self.media_handle = media_handle self.the_lists = the_lists def query_response(self): trans = self.db.transaction_begin() self.db.disable_signals() (person_list,family_list,event_list, place_list,source_list) = self.the_lists for handle in person_list: person = self.db.get_person_from_handle(handle) new_list = [ photo for photo in person.get_media_list() \ if photo.get_reference_handle() != self.media_handle ] person.set_media_list(new_list) self.db.commit_person(person,trans) for handle in family_list: family = self.db.get_family_from_handle(handle) new_list = [ photo for photo in family.get_media_list() \ if photo.get_reference_handle() != self.media_handle ] family.set_media_list(new_list) self.db.commit_family(family,trans) for handle in event_list: event = self.db.get_event_from_handle(handle) new_list = [ photo for photo in event.get_media_list() \ if photo.get_reference_handle() != self.media_handle ] event.set_media_list(new_list) self.db.commit_event(event,trans) for handle in place_list: place = self.db.get_place_from_handle(handle) new_list = [ photo for photo in place.get_media_list() \ if photo.get_reference_handle() != self.media_handle ] place.set_media_list(new_list) self.db.commit_place(place,trans) for handle in source_list: source = self.db.get_source_from_handle(handle) new_list = [ photo for photo in source.get_media_list() \ if photo.get_reference_handle() != self.media_handle ] source.set_media_list(new_list) self.db.commit_source(source,trans) self.db.enable_signals() self.db.remove_object(self.media_handle,trans) self.db.transaction_commit(trans,_("Remove Media Object")) def build_dropdown(entry,strings): store = gtk.ListStore(str) for value in strings: node = store.append() store.set(node,0,value) completion = gtk.EntryCompletion() completion.set_text_column(0) completion.set_model(store) entry.set_completion(completion)