diff --git a/gramps2/ChangeLog b/gramps2/ChangeLog index 9dd1f803d..0c5b751cc 100644 --- a/gramps2/ChangeLog +++ b/gramps2/ChangeLog @@ -1,3 +1,12 @@ +2005-04-04 Richard Taylor + * src/plugins/ScratchPad.py: made clear buttons sensitive to contents of + list and current selection. Added support for PERSON_LINK dnd. + * src/DdTargets.py: added PERSON_LINK target and simplified generation of + targets lists. + * src/FamilyView.py: added dnd of person handles to and from the child list. + * src/PeopleView.py: added dnd of person handles from the person list. + + 2005-04-05 Alex Roitman * src/GrampsBSDDB.py (upgrade_5): Make work with half-upgraded data. @@ -13,7 +22,7 @@ patch from Jim Smart. * src/PeopleView.py: Enable makup that PeopleModel can render fallback data in italics. -2005-04-01 Richard Taylor +2005-04-04 Richard Taylor * src/GrampsDBCallback.py: added support for disconnecting callbacks, better test code and lots of logging. Improved the comments. diff --git a/gramps2/src/DdTargets.py b/gramps2/src/DdTargets.py index 1522f0a34..1ba7cfdc5 100644 --- a/gramps2/src/DdTargets.py +++ b/gramps2/src/DdTargets.py @@ -105,8 +105,22 @@ class _DdTargets(object): self.NAME = _DdType(self,'name') self.MEDIAOBJ = _DdType(self,'mediaobj') + self.PERSON_LINK = _DdType(self,'person-link') + self.FAMILY_EVENT = _DdType(self,'fevent') self.FAMILY_ATTRIBUTE = _DdType(self,'fattr') + + # List of all types that are used between + # gramps widgets but should not be exported + # to non gramps widgets. + self._all_gramps_types = [self.URL, + self.EVENT, + self.ATTRIBUTE, + self.ADDRESS, + self.SOURCEREF, + self.NAME, + self.MEDIAOBJ, + self.PERSON_LINK] self.CHILD = _DdType(self,'child') self.SPOUSE = _DdType(self,'spouce') @@ -117,6 +131,14 @@ class _DdTargets(object): self.COMPOUND_TEXT = _DdType(self,'COMPOUND_TEXT', 0, 3) self.UTF8_STRING = _DdType(self,'UTF8_STRING', 0, 4) + # List of all the test types. These are types + # that can be interpreted as text. + self._all_text_types = (self.TEXT, + self.TEXT_MIME, + self.STRING, + self.COMPOUND_TEXT, + self.UTF8_STRING) + def insert(self,dd_type): """Add a target to the lookup lists. These lists are used purely for performance reasons.""" @@ -134,21 +156,13 @@ class _DdTargets(object): return type_name in self.all_text_types() def all_text(self): - return (self.TEXT, - self.TEXT_MIME, - self.STRING, - self.COMPOUND_TEXT, - self.UTF8_STRING) + return self._all_text_types def all_text_types(self): """return a list of all the type names that could be used as the type of a string.""" - return (self.TEXT.drag_type, - self.TEXT_MIME.drag_type, - self.STRING.drag_type, - self.COMPOUND_TEXT.drag_type, - self.UTF8_STRING.drag_type) + return tuple([t.drag_type for t in self._all_text_types]) def is_gramps_type(self,type_name): return type_name in self.all_gramps_types() @@ -156,40 +170,20 @@ class _DdTargets(object): def all_gramps_types(self): """return a list of all the type names that are internal to gramps.""" - - return (self.MEDIAOBJ.drag_type, - self.URL.drag_type, - self.EVENT.drag_type, - self.ATTRIBUTE.drag_type, - self.ADDRESS.drag_type, - self.SOURCEREF.drag_type, - self.NAME.drag_type, - self.FAMILY_EVENT.drag_type, - self.FAMILY_ATTRIBUTE.drag_type) + + return tuple([t.drag_type for t in self._all_gramps_types]) def all_text_targets(self): """return a list of all the targets that could be used for text.""" - return (self.TEXT.target(), - self.TEXT_MIME.target(), - self.STRING.target(), - self.COMPOUND_TEXT.target(), - self.UTF8_STRING.target()) + return tuple([t.target() for t in self._all_text_types]) def all_gramps_targets(self): """return a list off the internal gramps targets.""" - - return (self.MEDIAOBJ.target(), - self.URL.target(), - self.EVENT.target(), - self.ATTRIBUTE.target(), - self.ADDRESS.target(), - self.SOURCEREF.target(), - self.NAME.target(), - self.FAMILY_EVENT.target(), - self.FAMILY_ATTRIBUTE.target()) + + return tuple([t.target() for t in self._all_gramps_types]) def all_targets(self): """return a list of all the known targets.""" diff --git a/gramps2/src/FamilyView.py b/gramps2/src/FamilyView.py index aa85e96b4..fb9f8f50f 100644 --- a/gramps2/src/FamilyView.py +++ b/gramps2/src/FamilyView.py @@ -255,10 +255,12 @@ class FamilyView: self.selected_spouse = None self.child_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, - [DdTargets.CHILD.target()], + [DdTargets.CHILD.target(), + DdTargets.PERSON_LINK.target()], ACTION_COPY) self.child_list.drag_source_set(BUTTON1_MASK, - [DdTargets.CHILD.target()], + [DdTargets.CHILD.target(), + DdTargets.PERSON_LINK.target()], ACTION_COPY) self.child_list.connect('drag_data_get', self.drag_data_get) self.child_list.connect('drag_data_received',self.drag_data_received) @@ -1392,8 +1394,41 @@ class FamilyView: row = len(self.family.get_child_handle_list()) else: row = path[0][0] -1 + + if DdTargets.PERSON_LINK.drag_type in context.targets: + drop_person_handle = sel_data.data + + # Check child is not already in the family + if drop_person_handle in self.family.get_child_handle_list(): + return + + family = self.family + person = self.person + new_person = self.parent.db.get_person_from_handle(drop_person_handle) + trans = self.parent.db.transaction_begin() + if not family: + # Add family to active person, + # if it does not exist yet (child with no spouse) + family = RelLib.Family() + self.parent.db.add_family(family,trans) + person.add_family_handle(family.get_handle()) + if person.get_gender() == RelLib.Person.MALE: + family.set_father_handle(person.get_handle()) + else: + family.set_mother_handle(person.get_handle()) + self.parent.db.commit_family(family,trans) + self.parent.db.commit_person(person,trans) + + family.add_child_handle(new_person.get_handle()) + new_person.add_parent_family_handle(family.get_handle(), + RelLib.Person.CHILD_REL_BIRTH, + RelLib.Person.CHILD_REL_BIRTH) + self.parent.db.commit_person(new_person,trans) + self.parent.db.commit_family(family,trans) + self.parent.db.transaction_commit(trans,_("Add Child to Family")) + self.display_marriage(family) - if sel_data and sel_data.data: + elif sel_data and sel_data.data: exec 'data = %s' % sel_data.data exec 'mytype = "%s"' % data[0] exec 'person = "%s"' % data[1] @@ -1465,8 +1500,12 @@ class FamilyView: return handle = self.child_model.get_value(node,_HANDLE_COL) bits_per = 8; # we're going to pass a string - data = str(('child',handle)); - sel_data.set(sel_data.target, bits_per, data) + + if sel_data.target == DdTargets.PERSON_LINK.drag_type: + sel_data.set(sel_data.target, bits_per, handle) + else: + data = str(('child',handle)); + sel_data.set(sel_data.target, bits_per, data) def sp_drag_data_get(self,widget, context, sel_data, info, time): store,node = self.spouse_selection.get_selected() diff --git a/gramps2/src/PeopleView.py b/gramps2/src/PeopleView.py index b4cd30eeb..4ad605deb 100644 --- a/gramps2/src/PeopleView.py +++ b/gramps2/src/PeopleView.py @@ -45,6 +45,7 @@ from gtk.gdk import ACTION_COPY, BUTTON1_MASK #------------------------------------------------------------------------- import PeopleModel import GenericFilter +from DdTargets import DdTargets column_names = [ _('Name'), @@ -95,6 +96,24 @@ class PeopleView: self.parent.db.connect('person-delete', self.person_removed) self.parent.db.connect('person-rebuild', self.redisplay_person_list) + # + # DnD support + # + self.person_tree.drag_source_set(BUTTON1_MASK, + [DdTargets.PERSON_LINK.target()], + ACTION_COPY) + self.person_tree.connect('drag_data_get', self.person_drag_data_get) + + def person_drag_data_get(self, widget, context, sel_data, info, time): + selected_ids = self.get_selected_objects() + + if len(selected_ids) == 1: + sel_data.set(sel_data.target, 8, selected_ids[0]) + elif len(selected_ids) > 1: + # TBD + pass + + def sort_clicked(self,obj): for col in self.columns: if obj == col: diff --git a/gramps2/src/plugins/ScratchPad.py b/gramps2/src/plugins/ScratchPad.py index 6872de3bd..f24abda0d 100644 --- a/gramps2/src/plugins/ScratchPad.py +++ b/gramps2/src/plugins/ScratchPad.py @@ -425,6 +425,49 @@ class ScratchMediaObj(ScratchPadWrapper): "%s" % (_("Media Object"), escape(self._obj)) +class ScratchPersonLink(ScratchPadWrapper): + + DROP_TARGETS = [DdTargets.PERSON_LINK] + DRAG_TARGET = DdTargets.PERSON_LINK + ICON = LINK_PIC + + def __init__(self,db,obj): + ScratchPadWrapper.__init__(self,db,obj) + self._type = _("Person Link") + + person = self._db.get_person_from_handle(self._obj) + self._title = person.get_primary_name().get_name() + birth_handle = person.get_birth_handle() + if birth_handle: + birth = self._db.get_event_from_handle(birth_handle) + if birth.get_date() and birth.get_date() != "": + self._value = escape(birth.get_date()) + + + def tooltip(self): + global escape + + person = self._db.get_person_from_handle(self._obj) + + s = "%s\n\n"\ + "\t%s:\t%s\n"\ + "\t%s:\t%s\n" % ( + _("Person Link"), + _("Name"),escape(self._title), + _("Birth"),escape(self._value)) + + if len(person.get_source_references()) > 0: + psrc_ref = person.get_source_references()[0] + psrc_id = psrc_ref.get_base_handle() + psrc = self._db.get_source_from_handle(psrc_id) + + s += "\n%s\n\n"\ + "\t%s:\t%s\n" % ( + _("Primary source"), + _("Name"), + escape(short(psrc.get_title()))) + + return s #------------------------------------------------------------------------- # @@ -518,6 +561,7 @@ class ScratchPadListView: self.register_wrapper_class(ScratchPadName) self.register_wrapper_class(ScratchPadText) self.register_wrapper_class(ScratchMediaObj) + self.register_wrapper_class(ScratchPersonLink) def register_wrapper_class(self,wrapper_class): @@ -676,12 +720,20 @@ class ScratchPadWindow: self.window = self.top.get_widget("scratch_pad") self.window.set_icon(self.parent.topWindow.get_icon()) self.clear_all_btn = self.top.get_widget("btn_clear_all") + self.clear_btn = self.top.get_widget("btn_clear") self.object_list = ScratchPadListView(self.db,self.top.get_widget('objectlist')) - + self.object_list.get_selection().connect('changed',self.set_clear_btn_sensitivity) + self.set_clear_btn_sensitivity(sel=self.object_list.get_selection()) + if not ScratchPadWindow.otree: ScratchPadWindow.otree = ScratchPadListModel() + self.set_clear_all_btn_sensitivity(treemodel=ScratchPadWindow.otree) + ScratchPadWindow.otree.connect('row-deleted',self.set_clear_all_btn_sensitivity) + ScratchPadWindow.otree.connect('row-inserted',self.set_clear_all_btn_sensitivity) + + self.object_list.set_model(ScratchPadWindow.otree) self.top.signal_autoconnect({ @@ -697,6 +749,19 @@ class ScratchPadWindow: self.add_itself_to_menu() self.window.show() + def set_clear_all_btn_sensitivity(self, treemodel=None, path=None, iter=None, user_param1=None): + if len(treemodel) == 0: + self.clear_all_btn.set_sensitive(False) + else: + self.clear_all_btn.set_sensitive(True) + + def set_clear_btn_sensitivity(self, sel=None, user_param1=None): + if sel.count_selected_rows() == 0: + self.clear_btn.set_sensitive(False) + else: + self.clear_btn.set_sensitive(True) + + def on_delete_event(self,obj,b): self.remove_itself_from_menu()