From 0f6897d6b0feb7c8db2f264b314c2e8c833df621 Mon Sep 17 00:00:00 2001 From: Don Allingham Date: Tue, 9 Oct 2001 17:56:26 +0000 Subject: [PATCH] Start of gallery improvements svn: r453 --- gramps/src/EditPerson.glade | 4 +- gramps/src/EditPerson.py | 244 +++------------ gramps/src/EditPlace.py | 214 +------------ gramps/src/EditSource.py | 213 +------------ gramps/src/GrampsParser.py | 73 ++++- gramps/src/ImageSelect.py | 248 ++++++++++++++- gramps/src/Marriage.py | 217 +------------ gramps/src/ReadXML.py | 2 +- gramps/src/RelLib.py | 156 ++++++++- gramps/src/WriteXML.py | 74 +++-- gramps/src/gramps.glade | 608 ++++++++++++++++++++++++++++++++++++ gramps/src/gramps_main.py | 98 +++++- gramps/src/imagesel.glade | 9 +- 13 files changed, 1269 insertions(+), 891 deletions(-) diff --git a/gramps/src/EditPerson.glade b/gramps/src/EditPerson.glade index f93cd1a8d..b4427895c 100644 --- a/gramps/src/EditPerson.glade +++ b/gramps/src/EditPerson.glade @@ -3584,7 +3584,7 @@ editPerson Sat, 09 Dec 2000 22:09:54 GMT - + GTK_RELIEF_NORMAL @@ -3599,7 +3599,7 @@ editPerson Sun, 10 Dec 2000 03:48:08 GMT - + GTK_RELIEF_NORMAL diff --git a/gramps/src/EditPerson.py b/gramps/src/EditPerson.py index ac73ce7fb..eea314833 100644 --- a/gramps/src/EditPerson.py +++ b/gramps/src/EditPerson.py @@ -97,6 +97,8 @@ class EditPerson: # widgets self.window = self.get_widget("editPerson") + self.gallery = PersonGallery(self, self.path, "i%s" % person.getId(), \ + self.top.get_widget("photolist"), self.db) self.notes_field = self.get_widget("personNotes") self.event_name_field = self.get_widget("eventName") self.event_place_field = self.get_widget("eventPlace") @@ -107,7 +109,6 @@ class EditPerson: self.attr_details_field = self.get_widget("attr_details") self.name_details_field = self.get_widget("name_details") self.addr_details_field = self.get_widget("addr_details") - self.photo_list = self.get_widget("photolist") self.attr_list = self.get_widget("attr_list") self.attr_type = self.get_widget("attr_type") self.attr_value = self.get_widget("attr_value") @@ -161,7 +162,6 @@ class EditPerson: self.death = Event(person.getDeath()) self.birth = Event(person.getBirth()) self.pname = Name(person.getPrimaryName()) - self.selected_icon = -1 # Typing CR selects OK button self.window.editable_enters(self.notes_field); @@ -182,7 +182,7 @@ class EditPerson: "on_add_aka_clicked" : on_add_aka_clicked, "on_add_attr_clicked" : on_add_attr_clicked, "on_add_url_clicked" : on_add_url_clicked, - "on_addphoto_clicked" : on_add_photo_clicked, + "on_addphoto_clicked" : self.gallery.on_add_photo_clicked, "on_address_list_select_row": on_addr_list_select_row, "on_aka_delete_clicked" : on_aka_delete_clicked, "on_aka_update_clicked" : on_aka_update_clicked, @@ -194,18 +194,18 @@ class EditPerson: "on_delete_attr_clicked" : on_delete_attr_clicked, "on_delete_event" : on_delete_event, "on_delete_url_clicked" : on_delete_url_clicked, - "on_deletephoto_clicked" : on_delete_photo_clicked, + "on_deletephoto_clicked" : self.gallery.on_delete_photo_clicked, "on_editperson_switch_page" : on_switch_page, "on_event_add_clicked" : on_event_add_clicked, "on_event_delete_clicked" : on_event_delete_clicked, "on_event_select_row" : on_event_select_row, "on_event_update_clicked" : on_event_update_clicked, - "on_makeprimary_clicked" : on_primary_photo_clicked, + "on_makeprimary_clicked" : self.gallery.on_primary_photo_clicked, "on_name_list_select_row" : on_name_list_select_row, "on_name_note_clicked" : on_name_note_clicked, "on_name_source_clicked" : on_primary_name_source_clicked, - "on_photolist_button_press_event" : on_photolist_button_press, - "on_photolist_select_icon" : on_photo_select_icon, + "on_photolist_button_press_event" : self.gallery.on_photolist_button_press_event, + "on_photolist_select_icon" : self.gallery.on_photo_select_icon, "on_update_address_clicked" : on_update_addr_clicked, "on_update_attr_clicked" : on_update_attr_clicked, "on_update_url_clicked" : on_update_url_clicked, @@ -259,7 +259,9 @@ class EditPerson: # load photos into the photo window photo_list = person.getPhotoList() if len(photo_list) != 0: - self.load_photo(photo_list[0].getPath()) + ph = photo_list[0] + object = ph.getReference() + self.load_photo(object.getPath()) # set notes data self.notes_field.set_point(0) @@ -340,33 +342,6 @@ class EditPerson: self.dplace.set_position(0) self.dcause.set_position(0) - #------------------------------------------------------------------------- - # - # add_thumbnail - Scale the image and add it to the IconList. - # - #------------------------------------------------------------------------- - def add_thumbnail(self,photo): - src = os.path.basename(photo.getPath()) - if photo.getPrivate(): - thumb = "%s%s.thumb%s%s" % (self.path,os.sep,os.sep,src) - else: - thumb = "%s%s.thumb%s%s.jpg" % (self.path,os.sep,os.sep,os.path.basename(src)) - RelImage.check_thumb(photo.getPath(),thumb,const.thumbScale) - self.photo_list.append(thumb,photo.getDescription()) - - #------------------------------------------------------------------------- - # - # load_images - add each photo in the person's list of photos to the - # photolist window. - # - #------------------------------------------------------------------------- - def load_images(self): - self.photo_list.freeze() - self.photo_list.clear() - for photo in self.person.getPhotoList(): - self.add_thumbnail(photo) - self.photo_list.thaw() - #------------------------------------------------------------------------- # # load_photo - loads the specfied photo, scales it, and displays it @@ -399,31 +374,42 @@ class EditPerson: #------------------------------------------------------------------------- # -# PersonImageSelect class +# PersonGallery class # #------------------------------------------------------------------------- -class PersonImageSelect(ImageSelect.ImageSelect): +class PersonGallery(ImageSelect.Gallery): #--------------------------------------------------------------------- # - # __init__ - Sub-class an ImageSelect window. The only differences - # between the various subclasses are the initializer arguments, and - # the type of object for which an image is being selected. + # __init__ - Sub-class an ImageSelect.Gallery window. This is + # necessary to add support for the 'Make Primary Image' button. # #--------------------------------------------------------------------- - def __init__(self, epo): - ImageSelect.ImageSelect.__init__(self, epo.path, "i%s" % epo.person.getId()) - self.epo = epo; + def __init__(self, epo, path, prefix, icon_list, db): + ImageSelect.Gallery.__init__(self, epo.person, path, prefix, icon_list, db) + self.epo = epo #--------------------------------------------------------------------- # - # savephoto - Override the savephoto method to store the selected - # photo in a person object + # on_primary_photo_clicked - Make the currently selected photo the + # primary (literally the first) photo for this person. This is the + # photo that shows up in the General tab of the "Edit Person" window. # #--------------------------------------------------------------------- - def savephoto(self, photo): - self.epo.person.addPhoto(photo) - self.epo.add_thumbnail(photo) - + def on_primary_photo_clicked(self, obj): + if self.selectedIcon == None or self.selectedIcon == 0: + return + + photolist = self.dataobj.getPhotoList() + selected_icon = self.selectedIcon + savePhoto = photolist[selected_icon] + for i in range(0,selected_icon): + photolist[selected_icon-i] = photolist[selected_icon-i-1] + photolist[0] = savePhoto + + self.epo.load_photo(savePhoto.getReference().getPath()) + self.load_images() + utils.modified() + #------------------------------------------------------------------------- # @@ -839,49 +825,8 @@ def on_switch_page(obj,a,page): edit_obj = obj.get_data(EDITPERSON) if page == 6 and edit_obj.not_loaded: edit_obj.not_loaded = 0 - edit_obj.load_images() + edit_obj.gallery.load_images() -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_photo_select_icon(obj,iconNumber,event): - obj.get_data(EDITPERSON).selected_icon = iconNumber - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_delete_photo_clicked(obj): - epo = obj.get_data(EDITPERSON) - icon = epo.selected_icon - - if icon != -1: - epo.photo_list.remove(icon) - del epo.person.getPhotoList()[icon] - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_primary_photo_clicked(obj): - epo = obj.get_data(EDITPERSON) - if epo.selected_icon == None or epo.selected_icon == 0: - return - - photolist = epo.person.getPhotoList() - selected_icon = epo.selected_icon - savePhoto = photolist[selected_icon] - for i in range(0,selected_icon): - photolist[selected_icon-i] = photolist[selected_icon-i-1] - photolist[0] = savePhoto - - epo.load_photo(savePhoto.getPath()) - epo.load_images() - utils.modified() #------------------------------------------------------------------------- # @@ -1066,14 +1011,6 @@ def update_name(name,first,last,suffix,note,priv): return changed -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_add_photo_clicked(obj): - PersonImageSelect(obj.get_data(EDITPERSON)) - #------------------------------------------------------------------------- # # @@ -1298,115 +1235,6 @@ def on_birth_source_clicked(obj): epo = obj.get_data(EDITPERSON) Sources.SourceSelector(epo.birth.getSourceRefList(),epo,src_changed) -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_photolist_button_press(obj,event): - myobj = obj.get_data(EDITPERSON) - icon = myobj.selected_icon - if icon == -1: - return - - if event.button == 3: - photo = myobj.person.getPhotoList()[icon] - menu = GtkMenu() - item = GtkTearoffMenuItem() - item.show() - menu.append(item) - utils.add_menuitem(menu,_("View Image"),myobj,on_view_photo) - utils.add_menuitem(menu,_("Edit Image"),myobj,on_edit_photo) - utils.add_menuitem(menu,_("Edit Description"),myobj, - on_change_description) - if photo.getPrivate() == 0: - utils.add_menuitem(menu,_("Convert to private copy"), - myobj, on_convert_to_private) - menu.popup(None,None,None,0,0) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_convert_to_private(obj): - epo = obj.get_data(OBJECT) - photo = epo.person.getPhotoList()[epo.selected_icon] - - prefix = "i%s" % epo.person.getId() - name = RelImage.import_photo(photo.getPath(),epo.path,prefix) - - photo.setPath(name) - photo.setPrivate(1) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_view_photo(obj): - myobj = obj.get_data(OBJECT) - photo = myobj.person.getPhotoList()[myobj.selected_icon] - utils.view_photo(photo) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_edit_photo(obj): - myobj = obj.get_data(OBJECT) - photo = myobj.person.getPhotoList()[myobj.selected_icon] - if os.fork() == 0: - os.execvp(const.editor,[const.editor, photo.getPath()]) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_change_description(obj): - myobj = obj.get_data(OBJECT) - photo = myobj.person.getPhotoList()[myobj.selected_icon] - window = libglade.GladeXML(const.imageselFile,"dialog1") - - text = window.get_widget("text") - text.set_text(photo.getDescription()) - - image2 = RelImage.scale_image(photo.getPath(),200.0) - window.get_widget("photo").load_imlib(image2) - window.get_widget("dialog1").set_data(PHOTO,photo) - window.get_widget("dialog1").set_data(TEXT,text) - window.get_widget("dialog1").set_data(OBJECT,obj.get_data(OBJECT)) - window.get_widget("dialog1").editable_enters(text) - window.signal_autoconnect({ - "on_cancel_clicked" : utils.destroy_passed_object, - "on_ok_clicked" : on_ok_clicked, - "on_apply_clicked" : on_apply_clicked - }) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_apply_clicked(obj): - photo = obj.get_data(PHOTO) - text = obj.get_data(TEXT).get_text() - if text != photo.getDescription(): - photo.setDescription(text) - obj.get_data(OBJECT).load_images() - utils.modified() - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_ok_clicked(obj): - on_apply_clicked(obj) - utils.destroy_passed_object(obj) - #------------------------------------------------------------------------- # # EventEditor class diff --git a/gramps/src/EditPlace.py b/gramps/src/EditPlace.py index 8f9617098..0ca60d654 100644 --- a/gramps/src/EditPlace.py +++ b/gramps/src/EditPlace.py @@ -74,9 +74,10 @@ class EditPlace: else: self.srcreflist = [] - self.selectedIcon = -1 - self.currentImages = [] self.top_window = libglade.GladeXML(const.placesFile,"placeEditor") + idval = "p%s" % place.getId() + plwidget = self.top_window.get_widget("photolist") + self.gallery = ImageSelect.Gallery(place, self.path, idval, plwidget, db) self.title = self.top_window.get_widget("place_title") self.city = self.top_window.get_widget("city") self.county = self.top_window.get_widget("county") @@ -114,16 +115,14 @@ class EditPlace: self.note.insert_defaults(place.getNote()) self.note.set_word_wrap(1) - self.photo_list = self.top_window.get_widget("photolist") - self.top_window.signal_autoconnect({ "destroy_passed_object" : utils.destroy_passed_object, "on_source_clicked" : on_source_clicked, - "on_photolist_select_icon" : on_photo_select_icon, - "on_photolist_button_press_event" : on_photolist_button_press_event, + "on_photolist_select_icon" : self.gallery.on_photo_select_icon, + "on_photolist_button_press_event" : self.gallery.on_photolist_button_press_event, "on_switch_page" : on_switch_page, - "on_addphoto_clicked" : on_add_photo_clicked, - "on_deletephoto_clicked" : on_delete_photo_clicked, + "on_addphoto_clicked" : self.gallery.on_add_photo_clicked, + "on_deletephoto_clicked" : self.gallery.on_delete_photo_clicked, "on_add_url_clicked" : on_add_url_clicked, "on_delete_url_clicked" : on_delete_url_clicked, "on_update_url_clicked" : on_update_url_clicked, @@ -191,62 +190,6 @@ class EditPlace: def redraw_location_list(self): utils.redraw_list(self.llist,self.loc_list,disp_loc) - #------------------------------------------------------------------------- - # - # add_thumbnail - Scale the image and add it to the IconList. - # - #------------------------------------------------------------------------- - def add_thumbnail(self,photo): - src = os.path.basename(photo.getPath()) - if photo.getPrivate(): - thumb = "%s%s.thumb%s%s" % (self.path,os.sep,os.sep,src) - else: - thumb = "%s%s.thumb%s%s.jpg" % (self.path,os.sep,os.sep,os.path.basename(src)) - RelImage.check_thumb(photo.getPath(),thumb,const.thumbScale) - self.photo_list.append(thumb,photo.getDescription()) - - #------------------------------------------------------------------------- - # - # load_images - 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. - # - #------------------------------------------------------------------------- - def load_images(self): - self.photo_list.freeze() - self.photo_list.clear() - for photo in self.place.getPhotoList(): - self.add_thumbnail(photo) - self.photo_list.thaw() - - -#------------------------------------------------------------------------- -# -# PlaceImageSelect class -# -#------------------------------------------------------------------------- -class PlaceImageSelect(ImageSelect.ImageSelect): - #--------------------------------------------------------------------- - # - # __init__ - Sub-class an ImageSelect window. The only differences - # between the various subclasses are the initializer arguments, and - # the type of object for which an image is being selected. - # - #--------------------------------------------------------------------- - def __init__(self, epo): - ImageSelect.ImageSelect.__init__(self, epo.path, "p%s" % epo.place.getId()) - self.epo = epo; - - #--------------------------------------------------------------------- - # - # savephoto - Override the savephoto method to store the selected - # photo in a place object - # - #--------------------------------------------------------------------- - def savephoto(self, photo): - self.epo.place.addPhoto(photo) - self.epo.add_thumbnail(photo) - def on_web_go_clicked(obj): import gnome.url @@ -323,148 +266,7 @@ def on_switch_page(obj,a,page): src = obj.get_data(_PLACE) if page == 3 and src.not_loaded: src.not_loaded = 0 - src.load_images() - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_photo_select_icon(obj,iconNumber,event): - obj.get_data(_PLACE).selectedIcon = iconNumber - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_delete_photo_clicked(obj): - epo = obj.get_data(_PLACE) - icon = epo.selectedIcon - - if icon != -1: - epo.photo_list.remove(icon) - del epo.place.getPhotoList()[icon] - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_add_photo_clicked(obj): - PlaceImageSelect(obj.get_data(_PLACE)) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_photolist_button_press_event(obj,event): - - myobj = obj.get_data(_PLACE) - icon = myobj.selectedIcon - if icon == -1: - return - - if event.button == 3: - photo = myobj.place.getPhotoList()[icon] - menu = GtkMenu() - item = GtkTearoffMenuItem() - item.show() - menu.append(item) - utils.add_menuitem(menu,_("View Image"),myobj,on_view_photo) - utils.add_menuitem(menu,_("Edit Image"),myobj,on_edit_photo) - utils.add_menuitem(menu,_("Edit Description"),myobj, - on_change_description) - if photo.getPrivate() == 0: - utils.add_menuitem(menu,_("Convert to private copy"),myobj, - on_convert_to_private) - menu.popup(None,None,None,0,0) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_convert_to_private(obj): - edit_place_obj = obj.get_data("m") - photo = edit_place_obj.place.getPhotoList()[edit_place_obj.selectedIcon] - - prefix = "p%s" % edit_place_obj.place.getId() - name = RelImage.import_photo(photo.getPath(),edit_place_obj.path,prefix) - - photo.setPath(name) - photo.setPrivate(1) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_view_photo(obj): - myobj = obj.get_data("m") - photo = myobj.place.getPhotoList()[myobj.selectedIcon] - - utils.view_photo(photo) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_edit_photo(obj): - myobj = obj.get_data("m") - photo = myobj.place.getPhotoList()[myobj.selectedIcon] - if os.fork() == 0: - os.execvp(const.editor,[const.editor, photo.getPath()]) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_change_description(obj): - myobj = obj.get_data("m") - photo = myobj.place.getPhotoList()[myobj.selectedIcon] - window = libglade.GladeXML(const.imageselFile,"dialog1") - - text = window.get_widget("text") - text.set_text(photo.getDescription()) - - image2 = RelImage.scale_image(photo.getPath(),200.0) - window.get_widget("photo").load_imlib(image2) - window.get_widget("dialog1").set_data("p",photo) - window.get_widget("dialog1").set_data("t",text) - window.get_widget("dialog1").set_data("m",obj.get_data("m")) - window.get_widget("dialog1").editable_enters(text) - window.signal_autoconnect({ - "on_cancel_clicked" : utils.destroy_passed_object, - "on_ok_clicked" : on_ok_clicked, - "on_apply_clicked" : on_apply_clicked - }) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_ok_clicked(obj): - on_apply_clicked(obj) - utils.destroy_passed_object(obj) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_apply_clicked(obj): - photo = obj.get_data("p") - text = obj.get_data("t").get_text() - if text != photo.getDescription(): - photo.setDescription(text) - edit_window = obj.get_data("m") - edit_window.load_images() - utils.modified() + src.gallery.load_images() #------------------------------------------------------------------------- # diff --git a/gramps/src/EditSource.py b/gramps/src/EditSource.py index a50032790..4399dd7f4 100644 --- a/gramps/src/EditSource.py +++ b/gramps/src/EditSource.py @@ -65,9 +65,10 @@ class EditSource: self.path = db.getSavePath() self.not_loaded = 1 - self.selectedIcon = -1 - self.currentImages = [] self.top_window = libglade.GladeXML(const.gladeFile,"sourceEditor") + sid = "s%s" % source.getId() + plwidget = self.top_window.get_widget("photolist") + self.gallery = ImageSelect.Gallery(source, self.path, sid, plwidget, db) self.title = self.top_window.get_widget("source_title") self.author = self.top_window.get_widget("author") self.pubinfo = self.top_window.get_widget("pubinfo") @@ -81,15 +82,13 @@ class EditSource: self.note.insert_defaults(source.getNote()) self.note.set_word_wrap(1) - self.photo_list = self.top_window.get_widget("photolist") - self.top_window.signal_autoconnect({ "destroy_passed_object" : utils.destroy_passed_object, - "on_photolist_select_icon" : on_photo_select_icon, - "on_photolist_button_press_event" : on_photolist_button_press_event, + "on_photolist_select_icon" : self.gallery.on_photo_select_icon, + "on_photolist_button_press_event" : self.gallery.on_photolist_button_press_event, "on_switch_page" : on_switch_page, - "on_addphoto_clicked" : on_add_photo_clicked, - "on_deletephoto_clicked" : on_delete_photo_clicked, + "on_addphoto_clicked" : self.gallery.on_add_photo_clicked, + "on_deletephoto_clicked" : self.gallery.on_delete_photo_clicked, "on_sourceapply_clicked" : on_source_apply_clicked }) @@ -104,62 +103,6 @@ class EditSource: self.top.editable_enters(self.author); self.top.editable_enters(self.pubinfo); - #------------------------------------------------------------------------- - # - # add_thumbnail - Scale the image and add it to the IconList. - # - #------------------------------------------------------------------------- - def add_thumbnail(self,photo): - src = os.path.basename(photo.getPath()) - if photo.getPrivate(): - thumb = "%s%s.thumb%s%s" % (self.path,os.sep,os.sep,src) - else: - thumb = "%s%s.thumb%s%s.jpg" % (self.path,os.sep,os.sep,os.path.basename(src)) - RelImage.check_thumb(src,thumb,const.thumbScale) - self.photo_list.append(thumb,photo.getDescription()) - - #------------------------------------------------------------------------- - # - # load_images - clears the currentImages list to free up any cached - # Imlibs. Then add each photo in the source's list of photos to the - # photolist window. - # - #------------------------------------------------------------------------- - def load_images(self): - self.photo_list.freeze() - self.photo_list.clear() - for photo in self.source.getPhotoList(): - self.add_thumbnail(photo) - self.photo_list.thaw() - - -#------------------------------------------------------------------------- -# -# SourceImageSelect class -# -#------------------------------------------------------------------------- -class SourceImageSelect(ImageSelect.ImageSelect): - #--------------------------------------------------------------------- - # - # __init__ - Sub-class an ImageSelect window. The only differences - # between the various subclasses are the initializer arguments, and - # the type of object for which an image is being selected. - # - #--------------------------------------------------------------------- - def __init__(self, eso): - ImageSelect.ImageSelect.__init__(self, eso.path, "s%s" % eso.source.getId()) - self.eso = eso; - - #--------------------------------------------------------------------- - # - # savephoto - Override the savephoto method to store the selected - # photo in a source object - # - #--------------------------------------------------------------------- - def savephoto(self, photo): - self.eso.source.addPhoto(photo) - self.eso.add_thumbnail(photo) - #----------------------------------------------------------------------------- # @@ -202,145 +145,5 @@ def on_switch_page(obj,a,page): src = obj.get_data(SOURCE) if page == 2 and src.not_loaded: src.not_loaded = 0 - src.load_images() + src.gallery.load_images() -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_photo_select_icon(obj,iconNumber,event): - obj.get_data(SOURCE).selectedIcon = iconNumber - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_delete_photo_clicked(obj): - eso = obj.get_data(SOURCE) - icon = eso.selectedIcon - - if icon != -1: - eso.photo_list.remove(icon) - del eso.source.getPhotoList()[icon] - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_add_photo_clicked(obj): - SourceImageSelect(obj.get_data(SOURCE)) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_photolist_button_press_event(obj,event): - - myobj = obj.get_data(SOURCE) - icon = myobj.selectedIcon - if icon == -1: - return - - if event.button == 3: - photo = myobj.source.getPhotoList()[icon] - menu = GtkMenu() - item = GtkTearoffMenuItem() - item.show() - menu.append(item) - utils.add_menuitem(menu,_("View Image"),myobj,on_view_photo) - utils.add_menuitem(menu,_("Edit Image"),myobj,on_edit_photo) - utils.add_menuitem(menu,_("Edit Description"),myobj, - on_change_description) - if photo.getPrivate() == 0: - utils.add_menuitem(menu,_("Convert to private copy"),myobj, - on_convert_to_private) - menu.popup(None,None,None,0,0) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_convert_to_private(obj): - eso = obj.get_data("m") - photo = eso.source.getPhotoList()[eso.selectedIcon] - - prefix = "s%s" % eso.source.getId() - name = RelImage.import_photo(photo.getPath(),eso.path,prefix) - - photo.setPath(name) - photo.setPrivate(1) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_view_photo(obj): - myobj = obj.get_data("m") - photo = myobj.source.getPhotoList()[myobj.selectedIcon] - - utils.view_photo(photo) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_edit_photo(obj): - myobj = obj.get_data("m") - photo = myobj.source.getPhotoList()[myobj.selectedIcon] - if os.fork() == 0: - os.execvp(const.editor,[const.editor, photo.getPath()]) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_change_description(obj): - myobj = obj.get_data("m") - photo = myobj.source.getPhotoList()[myobj.selectedIcon] - window = libglade.GladeXML(const.imageselFile,"dialog1") - - text = window.get_widget("text") - text.set_text(photo.getDescription()) - - image2 = RelImage.scale_image(photo.getPath(),200.0) - window.get_widget("photo").load_imlib(image2) - window.get_widget("dialog1").set_data("p",photo) - window.get_widget("dialog1").set_data("t",text) - window.get_widget("dialog1").set_data("m",obj.get_data("m")) - window.get_widget("dialog1").editable_enters(text) - window.signal_autoconnect({ - "on_cancel_clicked" : utils.destroy_passed_object, - "on_ok_clicked" : on_ok_clicked, - "on_apply_clicked" : on_apply_clicked - }) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_ok_clicked(obj): - on_apply_clicked(obj) - utils.destroy_passed_object(obj) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_apply_clicked(obj): - photo = obj.get_data("p") - text = obj.get_data("t").get_text() - if text != photo.getDescription(): - photo.setDescription(text) - edit_window = obj.get_data("m") - edit_window.load_images() - utils.modified() diff --git a/gramps/src/GrampsParser.py b/gramps/src/GrampsParser.py index ca2a0b08d..391242813 100644 --- a/gramps/src/GrampsParser.py +++ b/gramps/src/GrampsParser.py @@ -23,6 +23,7 @@ from RelLib import * import string import os import sys +import gnome.mime #------------------------------------------------------------------------- # @@ -79,6 +80,9 @@ class GrampsParser(handler.ContentHandler): self.tlist = [] self.conf = 2 + self.objref = None + self.object = None + self.pref = None self.use_p = 0 self.in_note = 0 self.in_old_attr = 0 @@ -233,6 +237,10 @@ class GrampsParser(handler.ContentHandler): self.in_old_attr = 0 if self.photo: self.photo.addAttribute(self.attribute) + elif self.object: + self.object.addAttribute(self.attribute) + elif self.objref: + self.objref.addAttribute(self.attribute) elif self.person: self.person.addAttribute(self.attribute) elif self.family: @@ -418,6 +426,8 @@ class GrampsParser(handler.ContentHandler): self.source_ref.setBase(source) if self.photo: self.photo.addSourceRef(self.source_ref) + elif self.object: + self.object.addSourceRef(self.source_ref) elif self.event: self.event.addSourceRef(self.source_ref) elif self.address: @@ -437,6 +447,36 @@ class GrampsParser(handler.ContentHandler): def start_source(self,attrs): self.source = self.db.findSourceNoMap(u2l(attrs["id"])) + def start_objref(self,attrs): + self.objref = ObjectRef() + self.objref.setReference(self.db.findObjectNoMap(u2l(attrs['ref']))) + if self.family: + self.family.addPhoto(self.objref) + elif self.source: + self.source.addPhoto(self.objref) + elif self.person: + self.person.addPhoto(self.objref) + elif self.placeobj: + self.placeobj.addPhoto(self.objref) + + def start_object(self,attrs): + self.object = self.db.findObjectNoMap(u2l(attrs['id'])) + self.object.setMimeType(u2l(attrs['mime'])) + self.object.setDescription(u2l(attrs['description'])) + src = u2l(attrs["src"]) + if src[0] != os.sep: + self.object.setPath("%s%s%s" % (self.base,os.sep,src)) + self.object.setLocal(1) + else: + self.object.setPath(src) + self.object.setLocal(0) + + def stop_object(self,tag): + self.object = None + + def stop_objref(self,tage): + self.objref = None + #--------------------------------------------------------------------- # # @@ -444,30 +484,37 @@ class GrampsParser(handler.ContentHandler): #--------------------------------------------------------------------- def start_photo(self,attrs): self.photo = Photo() + self.pref = ObjectRef() + self.pref.setReference(self.photo) + for key in attrs.keys(): if key == "descrip" or key == "description": self.photo.setDescription(u2l(attrs[key])) + elif key == "priv": + self.pref.setPrivacy(int(attrs[key])) elif key == "src": src = u2l(attrs["src"]) if src[0] != os.sep: self.photo.setPath("%s%s%s" % (self.base,os.sep,src)) - self.photo.setPrivate(1) + self.photo.setLocal(1) else: self.photo.setPath(src) - self.photo.setPrivate(0) - if self.family: - self.family.addPhoto(self.photo) - elif self.source: - self.source.addPhoto(self.photo) - elif self.person: - self.person.addPhoto(self.photo) - elif self.placeobj: - self.placeobj.addPhoto(self.photo) + self.photo.setLocal(0) else: a = Attribute() a.setType(key) a.setValue(u2l(attrs[key])) self.photo.addAttribute(a) + self.photo.setMimeType(gnome.mime.type_or_default(self.photo.getPath(),"unknown")) + self.db.addObject(self.photo) + if self.family: + self.family.addPhoto(self.pref) + elif self.source: + self.source.addPhoto(self.pref) + elif self.person: + self.person.addPhoto(self.pref) + elif self.placeobj: + self.placeobj.addPhoto(self.pref) #--------------------------------------------------------------------- # @@ -808,6 +855,10 @@ class GrampsParser(handler.ContentHandler): if self.address: self.address.setNote(note) + elif self.object: + self.object.setNote(note) + elif self.objref: + self.objref.setNote(note) elif self.photo: self.photo.setNote(note) elif self.attribute: @@ -958,6 +1009,8 @@ class GrampsParser(handler.ContentHandler): "people" : (start_people, stop_people), "person" : (start_person, None), "img" : (start_photo, stop_photo), + "objref" : (start_objref, stop_objref), + "object" : (start_object, stop_object), "place" : (start_place, stop_place), "places" : (None, stop_places), "placeobj" : (start_placeobj,stop_placeobj), diff --git a/gramps/src/ImageSelect.py b/gramps/src/ImageSelect.py index b8ae688ff..464a44b73 100644 --- a/gramps/src/ImageSelect.py +++ b/gramps/src/ImageSelect.py @@ -33,6 +33,7 @@ import string #------------------------------------------------------------------------- from gtk import * from gnome.ui import * +import gnome.mime import libglade import GdkImlib @@ -64,11 +65,20 @@ class ImageSelect: # window. # #--------------------------------------------------------------------- - def __init__(self, path, prefix): + def __init__(self, path, prefix, db): self.path = path; + self.db = db self.prefix = prefix; + + #------------------------------------------------------------------------- + # + # create_add_dialog - Create the gnome dialog for selecting a new + # photo and entering its description. + # + #------------------------------------------------------------------------- + def create_add_dialog(self): self.glade = libglade.GladeXML(const.imageselFile,"imageSelect") - self.window = self.glade.get_widget("imageSelect") + window = self.glade.get_widget("imageSelect") self.fname = self.glade.get_widget("fname") self.image = self.glade.get_widget("image") self.description = self.glade.get_widget("photoDescription") @@ -80,20 +90,32 @@ class ImageSelect: "destroy_passed_object" : utils.destroy_passed_object }) - self.window.editable_enters(self.description) - self.window.show() + window.editable_enters(self.description) + window.show() + #------------------------------------------------------------------------- + # + # on_name_changed - The filename has changed. Verify it and load + # the picture. + # + #------------------------------------------------------------------------- def on_name_changed(self, obj): filename = self.fname.get_text() if os.path.isfile(filename): image = RelImage.scale_image(filename,const.thumbScale) self.image.load_imlib(image) + #------------------------------------------------------------------------- + # + # savephoto - Save the photo in the dataobj object. (Required function) + # + #------------------------------------------------------------------------- def on_savephoto_clicked(self, obj): filename = self.glade.get_widget("photosel").get_full_path(0) description = self.glade.get_widget("photoDescription").get_text() if os.path.exists(filename) == 0: + GnomeErrorDialog(_("That is not a valid file name.")); return if self.external.get_active() == 1: @@ -111,12 +133,230 @@ class ImageSelect: photo = Photo() photo.setPath(name) photo.setDescription(description) + photo.setMimeType(gnome.mime.type_or_default(name,"unknown")) self.savephoto(photo) utils.modified() utils.destroy_passed_object(obj) + #------------------------------------------------------------------------- + # + # savephoto - Save the photo in the dataobj object. (Placeholder) + # + #------------------------------------------------------------------------- def savephoto(self, photo): assert 0, "The savephoto function must be subclassed" +#------------------------------------------------------------------------- +# +# 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, path, prefix, icon_list, db): + ImageSelect.__init__(self, path, prefix, db) + + # Be paranoid - development only error messages + assert dataobj.addPhoto, "Gallery data object must contain an addPhoto routine." + assert dataobj.getPhotoList, "Gallery data object must contain an getPhotoList routine." + + # Remember arguments + self.path = path; + self.prefix = prefix; + self.dataobj = dataobj; + self.icon_list = icon_list; + + # Local object variables + self.selectedIcon = -1 + self.currentImages = [] + + #------------------------------------------------------------------------- + # + # savephoto - Save the photo in the dataobj object. (Required function) + # + #------------------------------------------------------------------------- + def savephoto(self, photo): + + self.db.addObject(photo) + oref = ObjectRef() + oref.setReference(photo) + self.dataobj.addPhoto(oref) + self.add_thumbnail(oref) + + #------------------------------------------------------------------------- + # + # add_thumbnail - Scale the image and add it to the IconList. + # + #------------------------------------------------------------------------- + def add_thumbnail(self, photo): + object = photo.getReference() + path = object.getPath() + src = os.path.basename(path) + if object.getLocal(): + thumb = "%s%s.thumb%s%s" % (self.path,os.sep,os.sep,src) + else: + thumb = "%s%s.thumb%s%s.jpg" % (self.path,os.sep,os.sep,os.path.basename(src)) + RelImage.check_thumb(path,thumb,const.thumbScale) + self.icon_list.append(thumb,object.getDescription()) + + #------------------------------------------------------------------------- + # + # load_images - 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. + # + #------------------------------------------------------------------------- + def load_images(self): + self.icon_list.freeze() + self.icon_list.clear() + for photo in self.dataobj.getPhotoList(): + self.add_thumbnail(photo) + self.icon_list.thaw() + + + #------------------------------------------------------------------------- + # + # on_photo_select_icon - User clicked on a photo. Remember which one. + # + #------------------------------------------------------------------------- + def on_photo_select_icon(self, obj,iconNumber,event): + self.selectedIcon = iconNumber + + + #------------------------------------------------------------------------- + # + # on_add_photo_clicked - User wants to add a new photo. Create a + # dialog to find out which photo they want. + # + #------------------------------------------------------------------------- + def on_add_photo_clicked(self, obj): + self.create_add_dialog() + + #------------------------------------------------------------------------- + # + # on_delete_photo_clicked - User wants to delete a new photo. + # Remove it from the displayed thumbnails, and remove it from the + # dataobj photo list. + # + #------------------------------------------------------------------------- + def on_delete_photo_clicked(self, obj): + icon = self.selectedIcon + if icon != -1: + self.icon_list.remove(icon) + del self.dataobj.getPhotoList()[icon] + + #------------------------------------------------------------------------- + # + # on_photolist_button_press_event - Look for right-clicks on a + # picture and create a popup menu of the available actions. + # + #------------------------------------------------------------------------- + def on_photolist_button_press_event(self, obj, event): + icon = self.selectedIcon + if icon == -1: + return + + if event.button == 3: + photo = self.dataobj.getPhotoList()[icon] + menu = GtkMenu() + item = GtkTearoffMenuItem() + item.show() + menu.append(item) + utils.add_menuitem(menu,_("View Object"),None,self.popup_view_photo) + utils.add_menuitem(menu,_("Edit Object"),None,self.popup_edit_photo) + utils.add_menuitem(menu,_("Edit Description"),None, + self.popup_change_description) + object = photo.getReference() + if object.getLocal() == 0: + utils.add_menuitem(menu,_("Convert to local copy"),None, + self.popup_convert_to_private) + menu.popup(None,None,None,0,0) + + #------------------------------------------------------------------------- + # + # popup_view_photo - Open this picture in a picture viewer + # + #------------------------------------------------------------------------- + def popup_view_photo(self, obj): + photo = self.dataobj.getPhotoList()[self.selectedIcon] + utils.view_photo(photo.getReference()) + + #------------------------------------------------------------------------- + # + # popup_edit_photo - Open this picture in a picture editor + # + #------------------------------------------------------------------------- + def popup_edit_photo(self, obj): + photo = self.dataobj.getPhotoList()[self.selectedIcon] + if os.fork() == 0: + os.execvp(const.editor,[const.editor, photo.getReference().getPath()]) + + #------------------------------------------------------------------------- + # + # popup_convert_to_private - Copy this picture into gramps private + # database instead of leaving it as an external data object. + # + #------------------------------------------------------------------------- + def popup_convert_to_private(self, obj): + photo = self.dataobj.getPhotoList()[self.selectedIcon] + object = photo.getReference() + name = RelImage.import_photo(object.getPath(),self.path,self.prefix) + + object.setPath(name) + object.setLocal(1) + + #------------------------------------------------------------------------- + # + # popup_change_description - Bring up a window allowing the user + # to edit the description of a picture. + # + #------------------------------------------------------------------------- + def popup_change_description(self, obj): + photo = self.dataobj.getPhotoList()[self.selectedIcon] + object = photo.getReference() + self.change_dialog = libglade.GladeXML(const.imageselFile,"change_description") + + window = self.change_dialog.get_widget("change_description") + text = self.change_dialog.get_widget("text") + text.set_text(object.getDescription()) + + image2 = RelImage.scale_image(object.getPath(),200.0) + self.change_dialog.get_widget("photo").load_imlib(image2) + window.set_data("p",photo) + window.set_data("t",text) + window.editable_enters(text) + self.change_dialog.signal_autoconnect({ + "on_cancel_clicked" : utils.destroy_passed_object, + "on_ok_clicked" : self.new_desc_ok_clicked, + "on_apply_clicked" : self.new_desc_apply_clicked + }) + + #------------------------------------------------------------------------- + # + # new_desc_apply_clicked - Apply the new description. + # + #------------------------------------------------------------------------- + def new_desc_apply_clicked(self, obj): + photo = obj.get_data("p") + object = photo.getReference() + text = obj.get_data("t").get_text() + if text != object.getDescription(): + object.setDescription(text) + self.load_images() + utils.modified() + + #------------------------------------------------------------------------- + # + # new_desc_ok_clicked - Apply the new description and close the dialog. + # + #------------------------------------------------------------------------- + def new_desc_ok_clicked(self, obj): + self.new_desc_apply_clicked(obj) + utils.destroy_passed_object(obj) + + + + diff --git a/gramps/src/Marriage.py b/gramps/src/Marriage.py index e9847aa54..cdfaa1ef0 100644 --- a/gramps/src/Marriage.py +++ b/gramps/src/Marriage.py @@ -70,35 +70,35 @@ class Marriage: self.db = db self.path = db.getSavePath() - self.selectedIcon = 0 - self.top = libglade.GladeXML(const.marriageFile,"marriageEditor") + top_window = self.get_widget("marriageEditor") + fid = "f%s" % family.getId() + plwidget = self.top.get_widget("photolist") + self.gallery = ImageSelect.Gallery(family, self.path, fid, plwidget, db) self.top.signal_autoconnect({ "destroy_passed_object" : on_cancel_edit, "on_add_attr_clicked" : on_add_attr_clicked, - "on_addphoto_clicked" : on_add_photo_clicked, + "on_addphoto_clicked" : self.gallery.on_add_photo_clicked, "on_attr_list_select_row" : on_attr_list_select_row, "on_close_marriage_editor" : on_close_marriage_editor, "on_delete_attr_clicked" : on_delete_attr_clicked, "on_delete_event" : on_delete_event, - "on_deletephoto_clicked" : on_delete_photo_clicked, + "on_deletephoto_clicked" : self.gallery.on_delete_photo_clicked, "on_marriageAddBtn_clicked" : on_add_clicked, "on_marriageDeleteBtn_clicked" : on_delete_clicked, "on_marriageEventList_select_row" : on_select_row, "on_marriageUpdateBtn_clicked" : on_update_clicked, - "on_photolist_button_press_event" : on_photolist_button_press_event, - "on_photolist_select_icon" : on_photo_select_icon, + "on_photolist_button_press_event" : self.gallery.on_photolist_button_press_event, + "on_photolist_select_icon" : self.gallery.on_photo_select_icon, "on_update_attr_clicked" : on_update_attr_clicked, }) - top_window = self.get_widget("marriageEditor") text_win = self.get_widget("marriageTitle") title = _("%s and %s") % (Config.nameof(family.getFather()), Config.nameof(family.getMother())) text_win.set_text(title) self.event_list = self.get_widget("marriageEventList") - self.photo_list = self.get_widget("photolist") # widgets self.date_field = self.get_widget("marriageDate") @@ -123,7 +123,7 @@ class Marriage: self.lists_changed = 0 # set initial data - self.load_images() + self.gallery.load_images() self.type_field.set_popdown_strings(const.familyRelations) frel = const.display_frel(family.getRelationship()) @@ -166,37 +166,6 @@ class Marriage: def redraw_attr_list(self): utils.redraw_list(self.alist,self.attr_list,disp_attr) - #------------------------------------------------------------------------- - # - # add_thumbnail - Scale the image and add it to the IconList. Currently, - # there seems to be a problem with either GdkImlib. A reference has to be - # kept to the image, or it gets lost. This is supposed to be a known - # imlib problem - # - #------------------------------------------------------------------------- - def add_thumbnail(self,photo): - src = os.path.basename(photo.getPath()) - if photo.getPrivate(): - thumb = "%s%s.thumb%s%s" % (self.path,os.sep,os.sep,src) - else: - thumb = "%s%s.thumb%s%s.jpg" % (self.path,os.sep,os.sep,os.path.basename(src)) - RelImage.check_thumb(photo.getPath(),thumb,const.thumbScale) - self.photo_list.append(thumb,photo.getDescription()) - - #------------------------------------------------------------------------- - # - # load_images - clears the currentImages list to free up any cached - # Imlibs. Then add each photo in the person's list of photos to the - # photolist window. - # - #------------------------------------------------------------------------- - def load_images(self): - self.photo_list.freeze() - self.photo_list.clear() - for photo in self.family.getPhotoList(): - self.add_thumbnail(photo) - self.photo_list.thaw() - #------------------------------------------------------------------------- # # redraw_events - redraws the event list by deleting all the entries and @@ -215,34 +184,6 @@ class Marriage: return self.top.get_widget(name) -#------------------------------------------------------------------------- -# -# MarriageImageSelect class -# -#------------------------------------------------------------------------- -class MarriageImageSelect(ImageSelect.ImageSelect): - #--------------------------------------------------------------------- - # - # __init__ - Sub-class an ImageSelect window. The only differences - # between the various subclasses are the initializer arguments, and - # the type of object for which an image is being selected. - # - #--------------------------------------------------------------------- - def __init__(self, efo): - ImageSelect.ImageSelect.__init__(self, efo.path, "f%s" % efo.family.getId()) - self.efo = efo; - - #--------------------------------------------------------------------- - # - # savephoto - Override the savephoto method to store the selected - # photo in a family object - # - #--------------------------------------------------------------------- - def savephoto(self, photo): - self.efo.family.addPhoto(photo) - self.efo.add_thumbnail(photo) - - #------------------------------------------------------------------------- # # @@ -482,146 +423,6 @@ def update_event(event,name,date,place,desc,note,priv,cause): return changed -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_photolist_button_press_event(obj,event): - myobj = obj.get_data(MARRIAGE) - icon = myobj.selectedIcon - if icon == -1: - return - - if event.button == 3: - photo = myobj.family.getPhotoList()[icon] - menu = GtkMenu() - item = GtkTearoffMenuItem() - item.show() - menu.append(item) - utils.add_menuitem(menu,_("View Image"),myobj,on_view_photo) - utils.add_menuitem(menu,_("Edit Image"),myobj,on_edit_photo) - utils.add_menuitem(menu,_("Edit Description"),myobj, - on_change_description) - if photo.getPrivate() == 0: - utils.add_menuitem(menu,_("Convert to private copy"),myobj, - on_convert_to_private) - menu.popup(None,None,None,0,0) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_convert_to_private(obj): - epo = obj.get_data(OBJECT) - photo = epo.family.getPhotoList()[epo.selected_icon] - - prefix = "f%s" % epo.person.getId() - name = RelImage.import_photo(photo.getPath(),epo.path,prefix) - - photo.setPath(name) - photo.setPrivate(1) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_view_photo(obj): - myobj = obj.get_data("m") - photo = myobj.family.getPhotoList()[myobj.selectedIcon] - utils.view_photo(photo) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_edit_photo(obj): - myobj = obj.get_data("m") - photo = myobj.family.getPhotoList()[myobj.selectedIcon] - if os.fork() == 0: - os.execvp(const.editor,[const.editor, photo.getPath()]) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_photo_select_icon(obj,iconNumber,event): - obj.get_data(MARRIAGE).selectedIcon = iconNumber - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_delete_photo_clicked(obj): - marriage_obj = obj.get_data(MARRIAGE) - icon = marriage_obj.selectedIcon - - if icon != -1: - marriage_obj.photo_list.remove(icon) - del marriage_obj.family.getPhotoList()[icon] - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_add_photo_clicked(obj): - MarriageImageSelect(obj.get_data(MARRIAGE)) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_change_description(obj): - - myobj = obj.get_data("m") - photo = myobj.family.getPhotoList()[myobj.selectedIcon] - window = libglade.GladeXML(const.imageselFile,"dialog1") - text = window.get_widget("text") - text.set_text(photo.getDescription()) - - image2 = RelImage.scale_image(photo.getPath(),200.0) - - window.get_widget("photo").load_imlib(image2) - window.get_widget("dialog1").set_data("p",photo) - window.get_widget("dialog1").set_data("t",text) - window.get_widget("dialog1").set_data("m",obj.get_data("m")) - window.get_widget("dialog1").editable_enters(text) - window.signal_autoconnect({ - "on_cancel_clicked" : utils.destroy_passed_object, - "on_ok_clicked" : on_ok_clicked, - "on_apply_clicked" : on_apply_clicked - }) - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_apply_clicked(obj): - photo = obj.get_data("p") - text = obj.get_data("t").get_text() - if text != photo.getDescription(): - photo.setDescription(text) - edit_window = obj.get_data("m") - edit_window.load_images() - utils.modified() - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_ok_clicked(obj): - on_apply_clicked(obj) - utils.destroy_passed_object(obj) - #------------------------------------------------------------------------- # # on_attr_list_select_row - sets the row object attached to the passed diff --git a/gramps/src/ReadXML.py b/gramps/src/ReadXML.py index 157f9b59c..64a5a25ff 100644 --- a/gramps/src/ReadXML.py +++ b/gramps/src/ReadXML.py @@ -162,7 +162,7 @@ def loadData(database, filename, callback=None): except: GnomeErrorDialog(_("%s could not be opened\n") % filename) return 0 - + try: parser.parse(xml_file) except SAXParseException,msg: diff --git a/gramps/src/RelLib.py b/gramps/src/RelLib.py index c49d8a30b..750ed2d6d 100644 --- a/gramps/src/RelLib.py +++ b/gramps/src/RelLib.py @@ -129,7 +129,7 @@ class Place(SourceNote): self.urls.append(Url(u)) self.photoList = [] for photo in source.photoList: - self.photoList.append(Photo(photo)) + self.photoList.append(ObjectRef(photo)) else: self.long = "" self.lat = "" @@ -346,15 +346,41 @@ class Photo(SourceNote): self.attrlist = [] if source: self.path = source.path + self.mime = source.mime + self.local = source.local self.desc = source.desc - self.private = source.private + self.id = source.id for attr in source.attrlist: self.attrlist.append(Attribute(attr)) else: + self.id = "" + self.local = 0 self.path = "" + self.mime = "" self.desc = "" - self.private = 0 + def setLocal(self,val): + """set or clear the local flag""" + self.local = val + + def getLocal(self): + """return the local flag""" + return self.local + + def setId(self,id): + """Sets the gramps ID for the place object""" + self.id = id + + def getId(self): + """Returns the gramps ID for the place object""" + return self.id + + def setMimeType(self,type): + self.mime = type + + def getMimeType(self): + return self.mime + def setPath(self,path): """set the file path to the passed path""" self.path = path @@ -363,14 +389,6 @@ class Photo(SourceNote): """return the file path""" return self.path - def setPrivate(self,val): - """set or clear the privacy flag""" - self.private = val - - def getPrivate(self): - """return the privacy flag""" - return self.private - def setDescription(self,text): """sets the description of the image""" self.desc = text @@ -389,6 +407,66 @@ class Photo(SourceNote): """returns the property list associated with the image""" return self.attrlist +class ObjectRef: + + def __init__(self,source=None): + self.attrlist = [] + if source: + self.private = source.private + self.ref = source.ref + self.note = Note(source.note) + for attr in source.attrlist: + self.attrlist.append(Attribute(attr)) + else: + self.private = 0 + self.ref = None + self.note = None + + def setPrivacy(self,val): + """Sets or clears the privacy flag of the data""" + self.private = val + + def getPrivacy(self): + """Returns the privacy level of the data""" + return self.private + + def setReference(self,obj): + self.ref = obj + + def getReference(self): + return self.ref + + def setNote(self,text): + """Set the note to the given text""" + if self.note == None: + self.note = Note() + self.note.set(text) + + def getNote(self): + """Return the current note""" + if self.note == None: + return "" + else: + return self.note.get() + + def setNoteObj(self,obj): + """Change the note object instance to obj""" + self.note = obj + + def getNoteObj(self): + """Return in note instance, not just the text""" + return self.note + + def addAttribute(self,attr): + """Adds a propery to the Photo object. This is not used by gramps, + but provides a means for XML users to attach other properties to + the image""" + self.attrlist.append(attr) + + def getAttributeList(self): + """returns the property list associated with the image""" + return self.attrlist + class Attribute(DataObj): """Provides a simple key/value pair for describing properties. Used by the Person and Family objects to store descriptive information.""" @@ -1345,10 +1423,12 @@ class RelDataBase: self.familyMap = {} self.sourceMap = {} self.placeMap = {} + self.objectMap = {} self.smapIndex = 0 self.pmapIndex = 0 self.fmapIndex = 0 self.lmapIndex = 0 + self.omapIndex = 0 self.default = None self.owner = Researcher() self.bookmarks = [] @@ -1413,6 +1493,10 @@ class RelDataBase: """returns a map of gramps's IDs to Source instances""" return self.sourceMap + def getObjectMap(self): + """returns a map of gramps's IDs to Object instances""" + return self.objectMap + def getSavePath(self): """returns the save path of the file, or "" if one does not exist""" return self.path @@ -1568,6 +1652,56 @@ class RelDataBase: self.addSourceNoMap(source,val) return source + def addObject(self,object): + """adds an Object instance to the database, assigning it a gramps' + ID number""" + + index = "O%d" % self.omapIndex + while self.objectMap.has_key(index): + self.omapIndex = self.omapIndex + 1 + index = "O%d" % self.omapIndex + object.setId(index) + self.objectMap[index] = object + self.omapIndex = self.omapIndex + 1 + return index + + def findObject(self,idVal,map): + """finds an Object in the database using the idVal and map + variables to translate between the external ID and gramps' + internal ID. If no such Object exists, a new Object instance + is created. + + idVal - external ID number + map - map build by findObject of external to gramp's IDs""" + + idVal = str(idVal) + if map.has_key(idVal): + object = self.objectMap[map[idVal]] + else: + object = Photo() + map[idVal] = self.addObject(object) + return object + + def addObjectNoMap(self,object,index): + """adds an Object to the database if the gramps' ID is known""" + index = str(index) + object.setId(index) + self.objectMap[index] = object + self.omapIndex = self.omapIndex + 1 + return index + + def findObjectNoMap(self,idVal): + """finds an Object in the database from the passed gramps' ID. + If no such Source exists, a new Source is added to the database.""" + + val = str(idVal) + if self.objectMap.has_key(val): + object = self.objectMap[val] + else: + object = Photo() + self.addObjectNoMap(object,val) + return object + def addPlace(self,place): """adds a Place instance to the database, assigning it a gramps' ID number""" diff --git a/gramps/src/WriteXML.py b/gramps/src/WriteXML.py index a9f68b6ff..c9ee07a59 100644 --- a/gramps/src/WriteXML.py +++ b/gramps/src/WriteXML.py @@ -271,36 +271,22 @@ def dump_location(g,loc): def write_attribute_list(g, list, indent=3): sp = ' ' * indent for attr in list: - if len(attr.getSourceRefList()) > 0 or attr.getNote(): - g.write('%s\n' % (sp,conf_priv(attr))) - write_line(g,"attr_type",attr.getType(),4) - write_line(g,"attr_value",attr.getValue(),4) - for s in attr.getSourceRefList(): - dump_source_ref(g,s,index+1) - write_note(g,"note",attr.getNote(),4) - g.write('%s\n' % sp) - else: - g.write('%s' % (sp,attr.getType())) - g.write(fix(attr.getValue())) - g.write('\n') - + g.write('%s\n' % (sp,conf_priv(attr))) + write_line(g,"attr_type",attr.getType(),4) + write_line(g,"attr_value",attr.getValue(),4) + for s in attr.getSourceRefList(): + dump_source_ref(g,s,indent+1) + write_note(g,"note",attr.getNote(),4) + g.write('%s\n' % sp) def write_photo_list(g,list,indent=3): sp = ' '*indent for photo in list: - path = photo.getPath() - if strip_photo: - path = os.path.basename(path) - else: - l = len(fileroot) - if len(path) >= l: - if fileroot == path[0:l]: - path = path[l+1:] - g.write('%s\n") else: g.write(">\n") @@ -308,7 +294,7 @@ def write_photo_list(g,list,indent=3): write_note(g,"note",photo.getNote(),indent+1) for s in photo.getSourceRefList(): dump_source_ref(g,s,indent+1) - g.write('%s\n' % sp) + g.write('%s\n' % sp) def write_url_list(g, list): @@ -339,9 +325,33 @@ def write_place_obj(g,place): if place.getNote() != "": write_note(g,"note",place.getNote(),3) for s in place.getSourceRefList(): - dump_source_ref(g,s,index+1) + dump_source_ref(g,s,3) g.write(" \n") +def write_object(g,object): + id = object.getId() + type = object.getMimeType() + path = object.getPath() + l = len(fileroot) + if len(path) >= l: + if fileroot == path[0:l]: + path = path[l+1:] + g.write(' \n') + else: + g.write('>\n') + write_attribute_list(g,alist) + if note != "": + write_note(g,"note",note,3) + for s in slist: + dump_source_ref(g,s,3) + g.write(" \n") + #------------------------------------------------------------------------- # # @@ -381,6 +391,8 @@ def write_xml_data(database, g, callback, sp): sourceList = database.getSourceMap().values() placeList = database.getPlaceMap().values() placeList.sort(sortById) + objList = database.getObjectMap().values() + objList.sort(sortById) total = len(personList) + len(familyList) @@ -455,7 +467,7 @@ def write_xml_data(database, g, callback, sp): if address.getNote() != "": write_note(g,"note",address.getNote(),4) for s in address.getSourceRefList(): - dump_source_ref(g,s,index+1) + dump_source_ref(g,s,4) g.write(' \n') write_attribute_list(g,person.getAttributeList()) @@ -530,6 +542,12 @@ def write_xml_data(database, g, callback, sp): write_place_obj(g,place) g.write(" \n") + if len(objList) > 0: + g.write(" \n") + for object in objList: + write_object(g,object) + g.write(" \n") + if len(database.getBookmarks()) > 0: g.write(" \n") for person in database.getBookmarks(): diff --git a/gramps/src/gramps.glade b/gramps/src/gramps.glade index f1d620045..d2447c753 100644 --- a/gramps/src/gramps.glade +++ b/gramps/src/gramps.glade @@ -560,6 +560,19 @@ earth.xpm + + GtkButton + Toolbar:button + button145 + + clicked + on_media_activate + Tue, 09 Oct 2001 17:09:23 GMT + + + GNOME_STOCK_PIXMAP_CDROM + + GtkButton Toolbar:button @@ -2396,6 +2409,601 @@ 0 0 + + + GtkVBox + vbox48 + False + 0 + + + GtkHBox + hbox34 + False + 0 + + 5 + False + True + + + + GtkFrame + frame7 + + 0 + GTK_SHADOW_ETCHED_IN + + 5 + False + False + + + + GnomePixmap + preview + 100 + 100 + 96 + 96 + + + + + GtkFrame + frame8 + + 0 + GTK_SHADOW_ETCHED_IN + + 5 + True + True + + + + GtkTable + table27 + 4 + 6 + False + 0 + 0 + + + GtkLabel + label269 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 3 + 0 + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label271 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 1 + 2 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label272 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 1 + 2 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label273 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 1 + 2 + 3 + 4 + 0 + 0 + False + False + False + False + True + False + + + + + GtkEntry + mid + True + False + True + 0 + + + 2 + 3 + 0 + 1 + 0 + 0 + True + False + False + False + True + False + + + + + GtkLabel + label270 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 3 + 0 + + 4 + 5 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkEntry + mtype + True + False + True + 0 + + + 5 + 6 + 0 + 1 + 0 + 0 + True + False + False + False + True + False + + + + + GtkEntry + mdesc + True + False + True + 0 + + + 2 + 6 + 1 + 2 + 0 + 0 + True + False + False + False + True + False + + + + + GtkEntry + mpath + True + False + True + 0 + + + 2 + 6 + 2 + 3 + 0 + 0 + True + False + False + False + True + False + + + + + GtkEntry + mdetails + True + False + True + 0 + + + 2 + 6 + 3 + 4 + 0 + 0 + True + False + False + False + True + False + + + + + GtkLabel + label265 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 5 + + 3 + 4 + 0 + 1 + 5 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label264 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 5 + + 0 + 1 + 0 + 1 + 5 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label266 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 5 + + 0 + 1 + 1 + 2 + 5 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label267 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 5 + + 0 + 1 + 2 + 3 + 5 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label268 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 5 + + 0 + 1 + 3 + 4 + 5 + 0 + False + False + False + False + True + False + + + + + + + + GtkScrolledWindow + scrolledwindow31 + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_UPDATE_CONTINUOUS + GTK_UPDATE_CONTINUOUS + + 0 + True + True + + + + GtkCList + media_list + True + + select_row + on_media_list_select_row + Tue, 09 Oct 2001 17:22:54 GMT + + 5 + 33,331,104,168,80 + GTK_SELECTION_SINGLE + True + GTK_SHADOW_IN + + + GtkLabel + CList:title + label259 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + GtkLabel + CList:title + label260 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + GtkLabel + CList:title + label261 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + GtkLabel + CList:title + label262 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + GtkLabel + CList:title + label263 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + + + GtkHButtonBox + hbuttonbox27 + GTK_BUTTONBOX_SPREAD + 30 + 85 + 27 + 7 + 0 + + 0 + False + True + + + + GtkButton + button142 + True + True + + GTK_RELIEF_NORMAL + + + + GtkButton + button143 + True + True + + GTK_RELIEF_NORMAL + + + + GtkButton + button144 + True + True + + GTK_RELIEF_NORMAL + + + + + + GtkLabel + Notebook:tab + label256 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + diff --git a/gramps/src/gramps_main.py b/gramps/src/gramps_main.py index 23424cf88..518acd1e2 100755 --- a/gramps/src/gramps_main.py +++ b/gramps/src/gramps_main.py @@ -69,6 +69,8 @@ import EditPlace import Marriage import Find import VersionControl +import RelImage + #------------------------------------------------------------------------- # # Global variables. @@ -106,6 +108,13 @@ notebook = None person_list = None source_list = None place_list = None +media_list = None +mid = None +mtype = None +mdesc = None +mpath = None +mdetails = None +preview = None database = None family_window = None nameArrow = None @@ -805,6 +814,7 @@ def new_database_response(val): load_family() load_sources() load_places() + load_media() #------------------------------------------------------------------------- # @@ -837,6 +847,7 @@ def full_update(): load_sources() load_places() load_canvas() + load_media() #------------------------------------------------------------------------- # @@ -856,8 +867,10 @@ def update_display(changed): load_canvas() elif page == 3: load_sources() - else: + elif page == 4: load_places() + else: + load_media() #------------------------------------------------------------------------- # @@ -2031,6 +2044,10 @@ def on_places_activate(obj): """Switches to the places view""" notebook.set_page(4) +def on_media_activate(obj): + """Switches to the media view""" + notebook.set_page(5) + #------------------------------------------------------------------------- # # Load the appropriate page after a notebook switch @@ -2049,6 +2066,8 @@ def on_notebook1_switch_page(obj,junk,page): load_sources() elif page == 4: load_places() + elif page == 5: + load_media() #------------------------------------------------------------------------- # @@ -2091,6 +2110,69 @@ def load_places(): place_list.thaw() +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def on_media_list_select_row(obj,row,b,c): + mobj = obj.get_row_data(row) + type = mobj.getMimeType() + path = mobj.getPath() + if type[0:5] == "image": + dir = os.path.dirname(path) + src = os.path.basename(path) + thumb = "%s%s.thumb%s%s.jpg" % (dir,os.sep,os.sep,src) + RelImage.check_thumb(path,thumb,const.thumbScale) + preview.load_file(thumb) + else: + pass + mid.set_text(mobj.getId()) + mtype.set_text(type) + mdesc.set_text(mobj.getDescription()) + if path[0] == "/": + mpath.set_text(path) + else: + mpath.set_text("") + mdetails.set_text("") + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def load_media(): + media_list.freeze() + media_list.clear() + + if len(media_list.selection) == 0: + current_row = 0 + else: + current_row = media_list.selection[0] + + index = 0 + objects = database.getObjectMap().values() + + for src in objects: + title = src.getDescription() + id = src.getId() + type = src.getMimeType() + if src.getLocal(): + path = "" + else: + path = src.getPath() + media_list.append([id,title,type,path,""]) + media_list.set_row_data(index,src) + index = index + 1 + + media_list.sort() + + if index > 0: + media_list.select_row(current_row,0) + media_list.moveto(current_row) + + media_list.thaw() + #------------------------------------------------------------------------- # # @@ -3187,9 +3269,10 @@ def on_main_key_release_event(obj,event): def main(arg): global database, gtop global statusbar,notebook - global person_list, source_list, place_list, canvas - global topWindow + global person_list, source_list, place_list, canvas, media_list + global topWindow, preview global nameArrow, dateArrow, deathArrow + global mid, mtype, mdesc, mpath, mdetails rc_parse(const.gtkrcFile) @@ -3211,6 +3294,13 @@ def main(arg): canvas = gtop.get_widget("canvas1") source_list = gtop.get_widget("source_list") place_list = gtop.get_widget("place_list") + media_list = gtop.get_widget("media_list") + mid = gtop.get_widget("mid") + mtype = gtop.get_widget("mtype") + mdesc = gtop.get_widget("mdesc") + mpath = gtop.get_widget("mpath") + mdetails = gtop.get_widget("mdetails") + preview = gtop.get_widget("preview") filter_list = gtop.get_widget("filter_list") notebook = gtop.get_widget(NOTEBOOK) nameArrow = gtop.get_widget("nameSort") @@ -3283,6 +3373,8 @@ def main(arg): "on_person_list_select_row" : on_person_list_select_row, "on_place_list_button_press_event" : on_place_list_button_press_event, "on_main_key_release_event" : on_main_key_release_event, + "on_media_activate" : on_media_activate, + "on_media_list_select_row" : on_media_list_select_row, "on_places_activate" : on_places_activate, "on_preferences_activate" : on_preferences_activate, "on_remove_child_clicked" : on_remove_child_clicked, diff --git a/gramps/src/imagesel.glade b/gramps/src/imagesel.glade index f4009f960..f3720d192 100644 --- a/gramps/src/imagesel.glade +++ b/gramps/src/imagesel.glade @@ -344,7 +344,6 @@ - @@ -352,7 +351,7 @@ GnomeDialog - dialog1 + change_description Gramps - Change image description GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE @@ -401,7 +400,7 @@ clicked on_ok_clicked - dialog1 + change_description Thu, 19 Apr 2001 00:00:19 GMT GNOME_STOCK_BUTTON_OK @@ -415,7 +414,7 @@ clicked on_apply_clicked - dialog1 + change_description Thu, 19 Apr 2001 00:00:06 GMT GNOME_STOCK_BUTTON_APPLY @@ -429,7 +428,7 @@ clicked on_cancel_clicked - dialog1 + change_description Thu, 19 Apr 2001 00:00:43 GMT GNOME_STOCK_BUTTON_CANCEL