diff options
Diffstat (limited to 'activity.py')
-rw-r--r-- | activity.py | 266 |
1 files changed, 192 insertions, 74 deletions
diff --git a/activity.py b/activity.py index 5573f58..91d2e24 100644 --- a/activity.py +++ b/activity.py @@ -5,8 +5,9 @@ from gettext import gettext as _ # Local import from src.person import Person -from src.person import persons from src.union import Union +from src.tree import Tree +from src.tree import sample_family1, sample_family2 import src.const as const @@ -49,15 +50,10 @@ class RootsActivity(activity.Activity): self.set_toolbox(toolbox) toolbox.show() - # Create sample data - (self.initx, self.inity, self.initzoom) = (500, 50, 0) - self.tree = self.init_family() - self.tree.compute_draw(self.initx, self.inity) - # Create drawing area - self.zoomlevel = 1 + self.zoomlevel = 0 self.area = gtk.DrawingArea() - self.area.set_size_request(600, 300) + self.area.set_size_request(750, 600) self.area.set_events(gtk.gdk.BUTTON_PRESS_MASK|gtk.gdk.BUTTON_RELEASE_MASK|gtk.gdk.BUTTON_MOTION_MASK|gtk.gdk.POINTER_MOTION_MASK) self.area.connect("expose_event", self.area_expose_cb) self.area.connect("button_press_event", self.press_button) @@ -65,104 +61,162 @@ class RootsActivity(activity.Activity): self.area.connect("motion_notify_event", self.mouse_move) self.moving = False - # Draw - self.box = gtk.VBox(False) + # Create detail view + self.fixed = gtk.VBox() + self.fixed.set_size_request(200, 300) + self.fixed.pack_start(gtk.Label("Name:"), False, False, 0) + self.detail_name = gtk.TextView() + self.detail_name.set_cursor_visible(True) + self.detail_name.get_buffer().connect("changed", self.detail_changed) + self.fixed.pack_start(self.detail_name, False, False, 0) + self.detail_chkmale = gtk.RadioButton(None, "Male") + self.detail_chkmale.connect("toggled", self.sexradio_checked, 'M') + self.fixed.pack_start(self.detail_chkmale, False, False, 0) + self.detail_chkfemale = gtk.RadioButton(self.detail_chkmale, "Female") + self.detail_chkfemale.connect("toggled", self.sexradio_checked, 'F') + self.fixed.pack_start(self.detail_chkfemale, False, False, 0) + self.detail_btnaddunion = gtk.Button("Add union") + self.detail_btnaddunion.connect("clicked", self.addunion_clicked) + self.detail_btnaddchild = gtk.Button("Add child") + self.detail_btnaddchild.connect("clicked", self.addchild_clicked) + self.detail_btndelete = gtk.Button("Delete") + self.detail_btndelete.connect("clicked", self.delete_clicked) + self.fixed.pack_start(self.detail_btnaddunion, False, False, 0) + self.fixed.pack_start(self.detail_btnaddchild, False, False, 0) + self.fixed.pack_start(self.detail_btndelete, False, False, 0) + self.box = gtk.HBox(False) + self.box.pack_start(self.fixed, True, True, 0) self.box.pack_start(self.area, True, True, 0) self.set_canvas(self.box) + + # Create sample data + (self.initx, self.inity) = (500, 50) + self.tree = sample_family2() + self.tree.root.compute_draw(self.initx, self.inity) + self.show_detail(None) + + # Show all self.show_all() self.area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW)) - - def init_family(self): - "Init a sample tree" - l = Person("Lucien", "M") - a = Person("Annick", "F") - u = Union(l, a) - - d = Person("Dominique", "M") - u.append_child(d) - au = Person("Anne", "F") - u.append_child(au) - m = Person("Madeleine", "F") - u.append_child(m) - - jp = Person("Jean-Pierre", "M") - j = Person("Julie", "F") - up = Union(jp, j) - up.append_child(l) - c = Person("Christian", "M") - up.append_child(c) - - ub = Union(Person("Jonathan", "M"), j) - ub.append_child(Person("Charlie", "F")) - - rs = Person("Renee", "F") - vm = Person("Vivien", "M") - urv = Union(vm, rs) - urv.append_child(j) - - jr = Person("Jean-Rene", "M") - ua = Union(jr, Person("Micheline", "F")) - ua.append_child(a) - i = Person("Irene", "F") - ua.append_child(i) - ui = Union(Person("Nathan", "M"), i) - ui.append_child(Person("Marie", "F")) - ui.append_child(Person("Noel", "M")) - ui.append_child(Person("Thierry", "M")) - - uc = Union(c, Person("Clarah", "F")) - uc.append_child(Person("Sandrine", "F")) - uc2 = Union(c, Person("Vivianne", "F")) - uc2.append_child(Person("Pierre", "M")) - uc2.append_child(Person("Camille", "F")) - - return vm - + + def set_center(self, person): + "Set the center of the draw on a person" + rect = self.area.allocation + dx = (rect.width/2) - self.tree.root.x0 - (person.x0 - self.tree.root.x0) - (person.x1 - person.x0)/2 + dy = (rect.height/2) - self.tree.root.y0 - (person.y0 - self.tree.root.y0) - (person.y1 - person.y0)/2 + self.translate(dx, dy) + + + def show_detail(self, person): + "Show detail information for a person" + + # Change selection + self.selected = person + + # No selection + if person == None: + self.detail_name.set_sensitive(False) + self.detail_name.get_buffer().set_text("Click one a node to select it") + self.detail_chkmale.set_active(True) + self.detail_chkmale.set_sensitive(False) + self.detail_chkfemale.set_sensitive(False) + self.detail_btnaddunion.set_sensitive(False) + self.detail_btnaddchild.set_sensitive(False) + self.detail_btndelete.set_sensitive(False) + return + + # A node is selected + self.detail_name.set_sensitive(True) + self.detail_name.grab_focus() + self.detail_name.get_buffer().set_text(person.name) + if person.sex == 'M': + self.detail_chkmale.set_active(True) + else: + self.detail_chkfemale.set_active(True) + + # Compute button status + checkable = (len(person.unions) == 0) + self.detail_chkmale.set_sensitive(checkable) + self.detail_chkfemale.set_sensitive(checkable) + self.detail_btnaddchild.set_sensitive(len(person.unions) > 0) + unionscount = len(person.unions) + childcount = person.child_count() + isdescendant = self.tree.is_descendant(person) + if person == self.tree.root: + deletable = False + elif unionscount == 0: + deletable = True + elif unionscount > 1: + deletable = False + elif unionscount == 1 and isdescendant: + deletable = False + elif childcount > 0: + deletable = False + else: + deletable = True + self.detail_btndelete.set_sensitive(deletable) + self.detail_btnaddunion.set_sensitive(isdescendant) + def area_expose_cb(self, area, event): "Draw tree event" + + # Create context then draw tree inside gc = self.area.window.cairo_create() pc = self.create_pango_context() - self.tree.draw(gc, pc) + self.tree.root.draw(gc, pc) gc.stroke() + + # Draw cross in middle to debug position + rect = self.area.allocation + gc.move_to((rect.width/2)-10, (rect.height/2)) + gc.line_to((rect.width/2)+10, (rect.height/2)) + gc.move_to((rect.width/2), (rect.height/2)-10) + gc.line_to((rect.width/2), (rect.height/2)+10) + gc.set_source_rgb(255, 255, 255) + gc.stroke() def press_button(self, widget, event): "Mouse button clicked, detail a person or start the moving mode" # Look if click in a person - for p in persons: + for p in self.tree.persons: # Found one, show detail if p.point_inside(event.x, event.y): - print p.name + self.set_center(p) + self.show_detail(p) self.moving = False return # Not found, pass in moving mode + self.show_detail(None) self.movingStart = (event.x, event.y) self.moving = True self.area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR)) - + + def translate(self, dx, dy): + # Translate all the tree from deltax, deltay + (self.initx, self.inity) = (self.initx+dx, self.inity+dy) + for p in self.tree.persons: + p.translate(dx, dy) + self.redraw() + + def mouse_move(self, widget, event): "Mouse move event, in moving mode translate draw if in moving mode else change cursor on person" # In moving mode ? if self.moving: # Compute translation - (dx, dy) = (event.x-self.movingStart[0], event.y-self.movingStart[1]) - (self.initx, self.inity) = (self.initx+dx, self.inity+dy) - for p in persons: - p.translate(dx, dy) + self.translate(event.x-self.movingStart[0], event.y-self.movingStart[1]) self.movingStart = (event.x, event.y) - - # Redraw - self.redraw() else: # Look if a person is under the cursor - for p in persons: + for p in self.tree.persons: # Found one, change cursor if p.point_inside(event.x, event.y): self.area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND1)) @@ -181,21 +235,85 @@ class RootsActivity(activity.Activity): def zoom_in(self, event): "ToolBar button zoom in clicked" - self.initzoom = self.initzoom + 20 + self.zoomlevel = self.zoomlevel + 1 + for p in self.tree.persons: + p.scale(20) self.redraw() def zoom_out(self, event): "ToolBar button zoom out clicked" - self.initzoom = self.initzoom - 20 + if self.zoomlevel == -3: + return + self.zoomlevel = self.zoomlevel - 1 + for p in self.tree.persons: + p.scale(-20) + self.redraw() + + + def detail_changed(self, event): + "Textfield for the detail has changed, change the matching person name" + if self.selected == None: + self.redraw() + return + buffer = self.detail_name.get_buffer() + self.selected.name = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter()) + self.redraw() + + + def sexradio_checked(self, widget, data): + "Radio button for sex checked, change sex for the selected person" + if self.selected is not None: + self.selected.sex = data self.redraw() + + def addchild_clicked(self, event): + "Add child clicked" + # TODO: Child add to the first union + newchild = self.tree.Person("", "M") + self.selected.unions[0].append_child(newchild) + self.tree.root.compute_draw(self.tree.root.x0, self.tree.root.y0) + self.show_detail(newchild) + + + def addunion_clicked(self, event): + "Add union clicked" + if self.selected.sex == "M": + male = self.selected + female = newunion = self.tree.Person("", "F") + else: + male = newunion = self.tree.Person("", "M") + female = self.selected + self.tree.Union(male, female) + self.tree.root.compute_draw(self.tree.root.x0, self.tree.root.y0) + self.show_detail(newunion) + + + def delete_clicked(self, event): + "Delete button clicked" + # Remove from union + for u in self.selected.unions: + self.tree.unions.remove(u) + if u.dad == self.selected: + u.mum.unions.remove(u) + else: + u.dad.unions.remove(u) + + # Remove from parent child + if self.selected.parents is not None: + self.selected.parents.childs.remove(self.selected) + # Remove from tree + self.tree.persons.remove(self.selected) + + # Recompute and redraw + self.tree.root.compute_draw(self.tree.root.x0, self.tree.root.y0) + self.show_detail(None) + + def redraw(self): "Redraw area" - self.tree.compute_draw(self.initx, self.inity) - for p in persons: - p.scale(self.initzoom) self.area.queue_draw_area(0, 0, self.area.allocation.width, self.area.allocation.height) |