def load_images(self, obj): """ Load the primary image into the main form if it exists. """ media_list = obj.get_media_list() count = 0 for media_ref in media_list: media_handle = media_ref.get_reference_handle() media = self.dbstate.db.get_media_from_handle(media_handle) full_path = media_path_full(self.dbstate.db, media.get_path()) mime_type = media.get_mime_type() if mime_type and mime_type.startswith("image"): photo = Photo(self.uistate.screen_height() < 1000) photo.set_image(full_path, mime_type, media_ref.get_rectangle()) photo.set_uistate(self.uistate, media_handle) else: photo = Photo(self.uistate.screen_height() < 1000) photo.set_pixbuf(full_path, get_thumbnail_image(full_path, mime_type, media_ref.get_rectangle())) self.image_list.append(photo) self.top.pack_start(photo, False, False, 0) count += 1 self.top.show_all() self.set_has_data(count > 0)
def load_images(self, obj): """ Load the primary image into the main form if it exists. """ media_list = obj.get_media_list() count = 0 for media_ref in media_list: media_handle = media_ref.get_reference_handle() media = self.dbstate.db.get_media_from_handle(media_handle) full_path = media_path_full(self.dbstate.db, media.get_path()) mime_type = media.get_mime_type() if mime_type and mime_type.startswith("image"): photo = Photo(self.uistate.screen_height() < 1000) photo.set_image(full_path, mime_type, media_ref.get_rectangle()) photo.set_uistate(self.uistate, media_handle) else: photo = Photo(self.uistate.screen_height() < 1000) photo.set_pixbuf( full_path, get_thumbnail_image(full_path, mime_type, media_ref.get_rectangle())) self.image_list.append(photo) self.top.pack_start(photo, False, False, 0) count += 1 self.top.show_all() self.set_has_data(count > 0)
class MediaPreview(Gramplet): """ Displays a preview of the media object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.Box() self.photo = Photo(self.uistate.screen_height() < 1000) self.top.pack_start(self.photo, fill=True, expand=False, padding=5) self.top.show_all() return self.top def db_changed(self): self.connect(self.dbstate.db, 'media-update', self.update) self.connect_signal('Media', self.update) def update_has_data(self): active_handle = self.get_active('Media') if active_handle: active_media = self.dbstate.db.get_media_from_handle(active_handle) self.set_has_data(active_media is not None) else: self.set_has_data(False) def main(self): active_handle = self.get_active('Media') if active_handle: media = self.dbstate.db.get_media_from_handle(active_handle) self.top.hide() if media: self.load_image(media) self.set_has_data(True) else: self.photo.set_image(None) self.set_has_data(False) self.top.show() else: self.set_has_data(False) def load_image(self, media): """ Load the primary image if it exists. """ self.full_path = media_path_full(self.dbstate.db, media.get_path()) mime_type = media.get_mime_type() self.photo.set_image(self.full_path, mime_type) self.photo.set_uistate(self.uistate, None)
class MediaPreview(Gramplet): """ Displays a preview of the media object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.Box() self.photo = Photo(self.uistate.screen_height() < 1000) self.top.pack_start(self.photo, fill=True, expand=False, padding=5) self.top.show_all() return self.top def db_changed(self): self.connect(self.dbstate.db, 'media-update', self.update) self.connect_signal('Media', self.update) def update_has_data(self): active_handle = self.get_active('Media') if active_handle: active_media = self.dbstate.db.get_media_from_handle(active_handle) self.set_has_data(active_media is not None) else: self.set_has_data(False) def main(self): active_handle = self.get_active('Media') if active_handle: media = self.dbstate.db.get_media_from_handle(active_handle) self.top.hide() if media: self.load_image(media) self.set_has_data(True) else: self.photo.set_image(None) self.set_has_data(False) self.top.show() else: self.set_has_data(False) def load_image(self, media): """ Load the primary image if it exists. """ self.full_path = media_path_full(self.dbstate.db, media.get_path()) mime_type = media.get_mime_type() self.photo.set_image(self.full_path, mime_type) self.photo.set_uistate(self.uistate, None)
class MediaBrowser(Gramplet): """ Displays an object tree and a media preview for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ top = Gtk.HBox() self.photo = Photo() self.photo.show() view = Gtk.TreeView() titles = [(_('Object'), 1, 250)] self.model = ListModel(view, titles, list_mode="tree", select_func=self.row_selected) top.pack_start(view, True, True, 0) top.pack_start(self.photo, True, False, 5) top.show_all() return top def db_changed(self): self.dbstate.db.connect('person-update', self.update) self.update() def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) def main(self): active_handle = self.get_active('Person') active = self.dbstate.db.get_person_from_handle(active_handle) self.model.clear() self.photo.set_image(None) if active: self.display_data(active) else: self.set_has_data(False) def display_data(self, person): """ Display the object tree for the active person. """ self.add_media(person) self.add_events(person) self.add_sources(person) self.set_has_data(self.model.count > 0) def add_events(self, obj, parent_node=None): """ Add event nodes to the model. """ for event_ref in obj.get_event_ref_list(): handle = event_ref.ref name, event = navigation_label(self.dbstate.db, 'Event', handle) node = self.model.add([name], node=parent_node) self.add_sources(event, node) self.add_media(event, node) def add_sources(self, obj, parent_node=None): """ Add source nodes to the model. """ for citation_handle in obj.get_citation_list(): citation = self.dbstate.db.get_citation_from_handle(citation_handle) handle = citation.get_reference_handle() name, src = navigation_label(self.dbstate.db, 'Source', handle) node = self.model.add([name], node=parent_node) self.add_media(src, node) def add_media(self, obj, parent_node=None): """ Add media object nodes to the model. """ for media_ref in obj.get_media_list(): handle = media_ref.ref name, media = navigation_label(self.dbstate.db, 'Media', handle) full_path = media_path_full(self.dbstate.db, media.get_path()) rect = media_ref.get_rectangle() self.model.add([name], info=media_ref, node=parent_node) def row_selected(self, selection): """ Change the image when a row is selected. """ selected = self.model.get_selected_objects() if selected: if selected[0]: self.load_image(selected[0]) else: self.photo.set_image(None) else: self.photo.set_image(None) def load_image(self, media_ref): """ Display an image from the given media reference. """ media = self.dbstate.db.get_object_from_handle(media_ref.ref) full_path = media_path_full(self.dbstate.db, media.get_path()) mime_type = media.get_mime_type() rectangle = media_ref.get_rectangle() self.photo.set_image(full_path, mime_type, rectangle) def get_has_data(self, person): """ Return True if the gramplet has data, else return False. """ if person is None: return False elif person.get_event_ref_list(): return True elif person.get_citation_list(): return True elif person.get_media_list(): return True return False
class FaceDetection(Gramplet): """ Interface for detecting and assigning facial areas to a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.HBox() # first column: vbox = Gtk.VBox() self.top.pack_start(vbox, False, False, 0) self.photo = Photo() vbox.pack_start(self.photo, False, False, 5) self.detect_button = Gtk.Button(_("Detect New Faces")) self.detect_button.connect('button-press-event', self.detect) vbox.pack_start(self.detect_button, False, False, 0) # second column vbox = Gtk.VBox() vbox.pack_start(Gtk.Label("Image:"), False, False, 0) self.top.pack_start(vbox, False, False, 0) # show and return: self.top.show_all() return self.top def db_changed(self): self.dbstate.db.connect('media-update', self.update) self.connect_signal('Media', self.update) self.update() def update_has_data(self): active_handle = self.get_active('Media') active_media = self.dbstate.db.get_media_from_handle(active_handle) self.set_has_data(active_media is not None) def main(self): active_handle = self.get_active('Media') media = self.dbstate.db.get_media_from_handle(active_handle) self.top.hide() if media: self.detect_button.set_sensitive(True) self.load_image(media) self.set_has_data(True) else: self.detect_button.set_sensitive(False) self.photo.set_image(None) self.set_has_data(False) self.top.show() def load_image(self, media): """ Load the primary image if it exists. """ self.full_path = media_path_full(self.dbstate.db, media.get_path()) self.mime_type = media.get_mime_type() self.photo.set_image(self.full_path, self.mime_type) # show where image parts are used by people: rects = self.find_references() self.draw_rectangles([], rects) def find_references(self): """ Find backref people """ active_handle = self.get_active('Media') rects = [] for (classname, handle) in \ self.dbstate.db.find_backlink_handles(active_handle): if classname == "Person": person = self.dbstate.db.get_person_from_handle(handle) if person: media_list = person.get_media_list() for media_ref in media_list: # get the rect for this image: if media_ref.ref != active_handle: continue rect = media_ref.get_rectangle() if rect: x1, y1, x2, y2 = rect # make percentages rects.append((x1/100.0, y1/100.0, (x2 - x1)/100.0, (y2 - y1)/100.0)) return rects def detect(self, obj, event): # First, reset image, in case of previous detections: active_handle = self.get_active('Media') media = self.dbstate.db.get_media_from_handle(active_handle) self.load_image(media) min_face_size = (50,50) # FIXME: get from setting self.cv_image = cv.LoadImage(self.full_path, cv.CV_LOAD_IMAGE_GRAYSCALE) o_width, o_height = self.cv_image.width, self.cv_image.height cv.EqualizeHist(self.cv_image, self.cv_image) cascade = cv.Load(HAARCASCADE_PATH) faces = cv.HaarDetectObjects(self.cv_image, cascade, cv.CreateMemStorage(0), 1.2, 2, cv.CV_HAAR_DO_CANNY_PRUNING, min_face_size) references = self.find_references() rects = [] o_width, o_height = [float(t) for t in (self.cv_image.width, self.cv_image.height)] for ((x, y, width, height), neighbors) in faces: # percentages: rects.append((x/o_width, y/o_height, width/o_width, height/o_height)) self.draw_rectangles(rects, references) def draw_rectangles(self, faces, references): # reset image: self.photo.set_image(self.full_path, self.mime_type) # draw on it pixbuf = self.photo.photo.get_pixbuf() pixmap, mask = pixbuf.render_pixmap_and_mask() cm = pixmap.get_colormap() # the thumbnail's actual size: t_width, t_height = [float(t) for t in self.photo.photo.size_request()] # percents: for (x, y, width, height) in references: self.draw_rectangle(cm, pixmap, t_width, t_height, x, y, width, height, "blue") for (x, y, width, height) in faces: self.draw_rectangle(cm, pixmap, t_width, t_height, x, y, width, height, "red") self.photo.photo.set_from_pixmap(pixmap, mask) def draw_rectangle(self, cm, pixmap, t_width, t_height, x, y, width, height, color): cmcolor = cm.alloc_color("white") gc = pixmap.new_gc(foreground=cmcolor) pixmap.draw_rectangle(gc, False, # fill it? int(x * t_width) + 1, int(y * t_height) + 1, int(width * t_width), int(height * t_height)) cmcolor = cm.alloc_color(color) gc = pixmap.new_gc(foreground=cmcolor) pixmap.draw_rectangle(gc, False, # fill it? int(x * t_width), int(y * t_height), int(width * t_width), int(height * t_height))
class PersonDetails(Gramplet): """ Displays details for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.uistate.connect('nameformat-changed', self.update) self.uistate.connect('placeformat-changed', self.update) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.Box() vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.photo = Photo(self.uistate.screen_height() < 1000) self.photo.show() self.name = Gtk.Label(halign=Gtk.Align.START) self.name.override_font(Pango.FontDescription('sans bold 12')) vbox.pack_start(self.name, fill=True, expand=False, padding=7) self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self.grid.set_column_spacing(10) vbox.pack_start(self.grid, fill=True, expand=False, padding=5) vbox.show_all() self.top.pack_start(self.photo, fill=True, expand=False, padding=5) self.top.pack_start(vbox, fill=True, expand=True, padding=10) return self.top def add_row(self, title, value): """ Add a row to the table. """ label = Gtk.Label(label=title + COLON, halign=Gtk.Align.END, valign=Gtk.Align.START) label.show() value = Gtk.Label(label=value, halign=Gtk.Align.START) value.show() self.grid.add(label) self.grid.attach_next_to(value, label, Gtk.PositionType.RIGHT, 1, 1) def clear_grid(self): """ Remove all the rows from the grid. """ list(map(self.grid.remove, self.grid.get_children())) def db_changed(self): self.connect(self.dbstate.db, 'person-update', self.update) def active_changed(self, handle): self.update() def update_has_data(self): """ Determine if a person has_data by checking: 1. has a birth, baptism, death, or burial event; OR 2. has a father; OR 3. has a mother """ active_handle = self.get_active('Person') has_data = False if active_handle: active_person = self.dbstate.db.get_person_from_handle( active_handle) if active_person: for event_type in [ EventType(EventType.BIRTH), EventType(EventType.BAPTISM), EventType(EventType.DEATH), EventType(EventType.BURIAL) ]: event = self.get_event(active_person, event_type) if event: has_data = True break if not has_data: family_handle = active_person.get_main_parents_family_handle( ) if family_handle: family = self.dbstate.db.get_family_from_handle( family_handle) handle = family.get_father_handle() if handle: if self.dbstate.db.get_person_from_handle(handle): has_data = True else: handle = family.get_mother_handle() if handle: if self.dbstate.db.get_person_from_handle( handle): has_data = True self.set_has_data(has_data) def main(self): # return false finishes self.display_empty() active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle( active_handle) self.top.hide() if active_person: self.display_person(active_person) self.top.show() self.update_has_data() def display_person(self, active_person): """ Display details of the active person. """ self.load_person_image(active_person) self.name.set_text(name_displayer.display(active_person)) self.clear_grid() self.display_alternate_names(active_person) self.display_parents(active_person) self.display_separator() self.display_type(active_person, EventType(EventType.BIRTH)) self.display_type(active_person, EventType(EventType.BAPTISM)) self.display_type(active_person, EventType(EventType.DEATH)) self.display_type(active_person, EventType(EventType.BURIAL)) self.display_separator() self.display_attribute(active_person, _('Occupation')) self.display_attribute(active_person, _('Title')) self.display_attribute(active_person, _('Religion')) def display_empty(self): """ Display empty details when no person is selected. """ self.photo.set_image(None) self.photo.set_uistate(None, None) self.name.set_text(_('No active person')) self.clear_grid() def display_separator(self): """ Display an empty row to separate groupd of entries. """ label = Gtk.Label(label='') label.override_font(Pango.FontDescription('sans 4')) label.show() self.grid.add(label) def display_alternate_names(self, active_person): """ Display other names of the person """ try: nlist = active_person.get_alternate_names() if len(nlist) > 0: for altname in nlist: name_type = str(altname.get_type()) text = name_displayer.display_name(altname) self.add_row(name_type, text) self.display_separator() except: pass def display_parents(self, active_person): """ Display the parents of the active person. """ family_handle = active_person.get_main_parents_family_handle() if family_handle: family = self.dbstate.db.get_family_from_handle(family_handle) handle = family.get_father_handle() if handle: father = self.dbstate.db.get_person_from_handle(handle) father_name = name_displayer.display(father) else: father_name = _('Unknown') handle = family.get_mother_handle() if handle: mother = self.dbstate.db.get_person_from_handle(handle) mother_name = name_displayer.display(mother) else: mother_name = _('Unknown') else: father_name = _('Unknown') mother_name = _('Unknown') self.add_row(_('Father'), father_name) self.add_row(_('Mother'), mother_name) def display_attribute(self, active_person, attr_key): """ Display an attribute row. """ values = [] for attr in active_person.get_attribute_list(): if attr.get_type() == attr_key: values.append(attr.get_value()) if values: # translators: needed for Arabic, ignore otherwise self.add_row(attr_key, _(', ').join(values)) def display_type(self, active_person, event_type): """ Display an event type row. """ event = self.get_event(active_person, event_type) if event: self.add_row(str(event_type), self.format_event(event)) def get_event(self, person, event_type): """ Return an event of the given type. """ for event_ref in person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if event.get_type() == event_type: return event return None def format_event(self, event): """ Format the event for display. """ date = get_date(event) handle = event.get_place_handle() if handle: place = place_displayer.display_event(self.dbstate.db, event) retval = _('%(date)s - %(place)s.') % { 'date': date, 'place': place } else: retval = _('%(date)s.') % dict(date=date) return retval def load_person_image(self, person): """ Load the primary image if it exists. """ media_list = person.get_media_list() if media_list: media_ref = media_list[0] object_handle = media_ref.get_reference_handle() obj = self.dbstate.db.get_media_from_handle(object_handle) full_path = media_path_full(self.dbstate.db, obj.get_path()) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): self.photo.set_image(full_path, mime_type, media_ref.get_rectangle()) self.photo.set_uistate(self.uistate, object_handle) else: self.photo.set_image(None) self.photo.set_uistate(None, None) else: self.photo.set_image(None) self.photo.set_uistate(None, None)
class AddressPreview(Gramplet, DbGUIElement): """ Displays the participants of an event. """ def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'place-update': self.changed, 'event-update': self.changed}) self.callman.connect_all(keys=['place', 'event']) #self.dbstate.db.connect('person-update', self.update) self.connect_signal('Place', self.update) def changed(self, handle): """ Called when a registered person is updated. """ self.update() def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.HBox() vbox = Gtk.VBox() self.photo = Photo(self.uistate.screen_height() < 1000) self.title = Gtk.Label() self.title.set_alignment(0, 0) self.title.modify_font(Pango.FontDescription('sans bold 12')) vbox.pack_start(self.title, False, True, 7) self.table = Gtk.Table(n_rows=1, n_columns=2) vbox.pack_start(self.table, False, True, 0) self.top.pack_start(self.photo, False, True, 5) self.top.pack_start(vbox, False, True, 10) self.top.show_all() return self.top # ------------------------------------------------------------------------------------------ _address_format = ["street, custom, unknown, building, department, farm, neighborhood", "hamlet, village, borough, locality", "code[ town, city, municipality], parish", "district, region, province, county, state", "country", ""] _place_keys = ['street', 'department', 'building', 'farm', 'neighborhood', 'hamlet', 'village', 'borough', 'locality', 'town', 'city', 'municipality', 'parish', 'district', 'region', 'province', 'county', 'state', 'country', 'custom', 'unknown', 'code'] _place_types = dict(street=PlaceType.STREET, department=PlaceType.DEPARTMENT, building=PlaceType.BUILDING, farm=PlaceType.FARM, neighborhood=PlaceType.NEIGHBORHOOD, hamlet=PlaceType.HAMLET, village=PlaceType.VILLAGE, borough=PlaceType.BOROUGH, locality=PlaceType.LOCALITY, town=PlaceType.TOWN, city=PlaceType.CITY, municipality=PlaceType.MUNICIPALITY, parish=PlaceType.PARISH, district=PlaceType.DISTRICT, province=PlaceType.PROVINCE, region=PlaceType.REGION, county=PlaceType.COUNTY, state=PlaceType.STATE, country=PlaceType.COUNTRY, custom=PlaceType.CUSTOM, unknown=PlaceType.UNKNOWN) def add_row(self, title, value): """ Add a row to the table. """ label = Gtk.Label(label=title + ':') label.set_alignment(1, 0) label.show() value = Gtk.Label(label=value) value.set_alignment(0, 0) value.show() rows = self.table.get_property('n-rows') rows += 1 self.table.resize(rows, 2) self.table.attach(label, 0, 1, rows, rows + 1, xoptions=Gtk.AttachOptions.FILL, xpadding=10) self.table.attach(value, 1, 2, rows, rows + 1) def clear_table(self): """ Remove all the rows from the table. """ list(map(self.table.remove, self.table.get_children())) self.table.resize(1, 2) def db_changed(self): self.dbstate.db.connect('place-update', self.update) self.connect_signal('Place', self.update) def update_has_data(self): active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(active_person is not None) else: self.set_has_data(False) def main(self): self.display_empty() active_handle = self.get_active('Place') if active_handle: place = self.dbstate.db.get_place_from_handle(active_handle) self.top.hide() if place: self.display_place(place) self.set_has_data(True) else: self.set_has_data(False) self.top.show() else: self.set_has_data(False) def display_place(self, place): """ Display details of the active place. """ self.load_place_image(place) title = place_displayer.display(self.dbstate.db, place) self.title.set_text(title) self.clear_table() #parser = FormatStringParser(self._place_keys) place_dict = self.generate_place_dictionary(place) parser = FormatStringParser(place_dict) addr1 = parser.parse(place_dict, self._address_format[0]) addr2 = parser.parse(place_dict, self._address_format[1]) city = parser.parse(place_dict, self._address_format[2]) state = parser.parse(place_dict, self._address_format[3]) country = parser.parse(place_dict, self._address_format[4]) code = parser.parse(place_dict, self._address_format[5]) self.add_row(_("Address 1"), addr1) self.add_row(_("Address 2"), addr2) self.add_row(_("City"), city) self.add_row(_("State"), state) self.add_row(_("Country"), country) self.add_row(_("Postal Code"), code) self.add_row(_("Version"), "0.1") #self.add_row(_('Name'), place.get_name()) #self.add_row(_('Type'), place.get_type()) #self.display_separator() #self.display_alt_names(place) #self.display_separator() lat, lon = conv_lat_lon(place.get_latitude(), place.get_longitude(), format='DEG') #if lat: # self.add_row(_('Latitude'), lat) #if lon: # self.add_row(_('Longitude'), lon) def generate_place_dictionary(self, place): db = self.dbstate.get_database() location = get_main_location(db, place) place_dict = dict() for key in self._place_keys: place_type = self._place_types.get(key.lower()) if place_type: value = location.get(place_type) elif key == "code": value = place.get_code() else: value = "" if not value: value = "" place_dict[key] = value return place_dict def display_alt_names(self, place): """ Display alternative names for the place. """ alt_names = place .get_alternative_names() if len(alt_names) > 0: self.add_row(_('Alternative Names'), '\n'.join(alt_names)) def display_empty(self): """ Display empty details when no repository is selected. """ self.photo.set_image(None) self.photo.set_uistate(None, None) self.title.set_text('') self.clear_table() def display_separator(self): """ Display an empty row to separate groupd of entries. """ label = Gtk.Label(label='') label.modify_font(Pango.FontDescription('sans 4')) label.show() rows = self.table.get_property('n-rows') rows += 1 self.table.resize(rows, 2) self.table.attach(label, 0, 1, rows, rows + 1, xoptions=Gtk.AttachOptions.FILL) def load_place_image(self, place): """ Load the primary image if it exists. """ media_list = place.get_media_list() if media_list: media_ref = media_list[0] object_handle = media_ref.get_reference_handle() obj = self.dbstate.db.get_object_from_handle(object_handle) full_path = media_path_full(self.dbstate.db, obj.get_path()) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): self.photo.set_image(full_path, mime_type, media_ref.get_rectangle()) self.photo.set_uistate(self.uistate, object_handle) else: self.photo.set_image(None) self.photo.set_uistate(None, None) else: self.photo.set_image(None) self.photo.set_uistate(None, None)
class PlaceDetails(Gramplet): """ Displays details for a place. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.Box() vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.photo = Photo(self.uistate.screen_height() < 1000) self.title = Gtk.Label(halign=Gtk.Align.START) self.title.override_font(Pango.FontDescription('sans bold 12')) vbox.pack_start(self.title, False, True, 7) self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self.grid.set_column_spacing(10) vbox.pack_start(self.grid, False, True, 0) self.top.pack_start(self.photo, False, True, 5) self.top.pack_start(vbox, False, True, 10) self.top.show_all() return self.top def add_row(self, title, value): """ Add a row to the table. """ label = Gtk.Label(label=title + ':', halign=Gtk.Align.END, valign=Gtk.Align.START) label.show() value = Gtk.Label(label=value, halign=Gtk.Align.START) value.show() self.grid.add(label) self.grid.attach_next_to(value, label, Gtk.PositionType.RIGHT, 1, 1) def clear_grid(self): """ Remove all the rows from the grid. """ list(map(self.grid.remove, self.grid.get_children())) def db_changed(self): self.dbstate.db.connect('place-update', self.update) self.connect_signal('Place', self.update) def update_has_data(self): active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(active_person is not None) else: self.set_has_data(False) def main(self): self.display_empty() active_handle = self.get_active('Place') if active_handle: place = self.dbstate.db.get_place_from_handle(active_handle) self.top.hide() if place: self.display_place(place) self.set_has_data(True) else: self.set_has_data(False) self.top.show() else: self.set_has_data(False) def display_place(self, place): """ Display details of the active place. """ self.load_place_image(place) title = place_displayer.display(self.dbstate.db, place) self.title.set_text(title) self.clear_grid() self.add_row(_('Name'), place.get_name().get_value()) self.add_row(_('Type'), place.get_type()) self.display_separator() self.display_alt_names(place) self.display_separator() lat, lon = conv_lat_lon(place.get_latitude(), place.get_longitude(), format='DEG') if lat: self.add_row(_('Latitude'), lat) if lon: self.add_row(_('Longitude'), lon) def display_alt_names(self, place): """ Display alternative names for the place. """ alt_names = [name.get_value() for name in place.get_alternative_names()] if len(alt_names) > 0: self.add_row(_('Alternative Names'), '\n'.join(alt_names)) def display_empty(self): """ Display empty details when no repository is selected. """ self.photo.set_image(None) self.photo.set_uistate(None, None) self.title.set_text('') self.clear_grid() def display_separator(self): """ Display an empty row to separate groupd of entries. """ label = Gtk.Label(label='') label.override_font(Pango.FontDescription('sans 4')) label.show() self.grid.add(label) def load_place_image(self, place): """ Load the primary image if it exists. """ media_list = place.get_media_list() if media_list: media_ref = media_list[0] object_handle = media_ref.get_reference_handle() obj = self.dbstate.db.get_object_from_handle(object_handle) full_path = media_path_full(self.dbstate.db, obj.get_path()) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): self.photo.set_image(full_path, mime_type, media_ref.get_rectangle()) self.photo.set_uistate(self.uistate, object_handle) else: self.photo.set_image(None) self.photo.set_uistate(None, None) else: self.photo.set_image(None) self.photo.set_uistate(None, None)
class MediaBrowser(Gramplet): """ Displays an object tree and a media preview for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ top = Gtk.HBox() self.photo = Photo() self.photo.show() view = Gtk.TreeView() titles = [(_("Object"), 1, 250)] self.model = ListModel(view, titles, list_mode="tree", select_func=self.row_selected) top.pack_start(view, True, True, 0) top.pack_start(self.photo, True, False, 5) top.show_all() return top def db_changed(self): self.dbstate.db.connect("person-update", self.update) self.update() def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active("Person") active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) def main(self): active_handle = self.get_active("Person") active = self.dbstate.db.get_person_from_handle(active_handle) self.model.clear() self.photo.set_image(None) if active: self.display_data(active) else: self.set_has_data(False) def display_data(self, person): """ Display the object tree for the active person. """ self.add_media(person) self.add_events(person) self.add_sources(person) self.set_has_data(self.model.count > 0) def add_events(self, obj, parent_node=None): """ Add event nodes to the model. """ for event_ref in obj.get_event_ref_list(): handle = event_ref.ref name, event = navigation_label(self.dbstate.db, "Event", handle) node = self.model.add([name], node=parent_node) self.add_sources(event, node) self.add_media(event, node) def add_sources(self, obj, parent_node=None): """ Add source nodes to the model. """ for citation_handle in obj.get_citation_list(): citation = self.dbstate.db.get_citation_from_handle(citation_handle) handle = citation.get_reference_handle() name, src = navigation_label(self.dbstate.db, "Source", handle) node = self.model.add([name], node=parent_node) self.add_media(src, node) def add_media(self, obj, parent_node=None): """ Add media object nodes to the model. """ for media_ref in obj.get_media_list(): handle = media_ref.ref name, media = navigation_label(self.dbstate.db, "Media", handle) full_path = media_path_full(self.dbstate.db, media.get_path()) rect = media_ref.get_rectangle() self.model.add([name], info=media_ref, node=parent_node) def row_selected(self, selection): """ Change the image when a row is selected. """ selected = self.model.get_selected_objects() if selected: if selected[0]: self.load_image(selected[0]) else: self.photo.set_image(None) else: self.photo.set_image(None) def load_image(self, media_ref): """ Display an image from the given media reference. """ media = self.dbstate.db.get_object_from_handle(media_ref.ref) full_path = media_path_full(self.dbstate.db, media.get_path()) mime_type = media.get_mime_type() rectangle = media_ref.get_rectangle() self.photo.set_image(full_path, mime_type, rectangle) def get_has_data(self, person): """ Return True if the gramplet has data, else return False. """ if person is None: return False elif person.get_event_ref_list(): return True elif person.get_citation_list(): return True elif person.get_media_list(): return True return False
class PlaceDetails(Gramplet): """ Displays details for a place. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.Box() vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.photo = Photo(self.uistate.screen_height() < 1000) self.title = Gtk.Label() self.title.set_alignment(0, 0) self.title.override_font(Pango.FontDescription('sans bold 12')) vbox.pack_start(self.title, False, True, 7) self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self.grid.set_column_spacing(10) vbox.pack_start(self.grid, False, True, 0) self.top.pack_start(self.photo, False, True, 5) self.top.pack_start(vbox, False, True, 10) self.top.show_all() return self.top def add_row(self, title, value): """ Add a row to the table. """ label = Gtk.Label(label=title + ':') label.set_alignment(1, 0) label.show() value = Gtk.Label(label=value) value.set_alignment(0, 0) value.show() self.grid.add(label) self.grid.attach_next_to(value, label, Gtk.PositionType.RIGHT, 1, 1) def clear_grid(self): """ Remove all the rows from the grid. """ list(map(self.grid.remove, self.grid.get_children())) def db_changed(self): self.dbstate.db.connect('place-update', self.update) self.connect_signal('Place', self.update) def update_has_data(self): active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(active_person is not None) else: self.set_has_data(False) def main(self): self.display_empty() active_handle = self.get_active('Place') if active_handle: place = self.dbstate.db.get_place_from_handle(active_handle) self.top.hide() if place: self.display_place(place) self.set_has_data(True) else: self.set_has_data(False) self.top.show() else: self.set_has_data(False) def display_place(self, place): """ Display details of the active place. """ self.load_place_image(place) title = place_displayer.display(self.dbstate.db, place) self.title.set_text(title) self.clear_grid() self.add_row(_('Name'), place.get_name()) self.add_row(_('Type'), place.get_type()) self.display_separator() self.display_alt_names(place) self.display_separator() lat, lon = conv_lat_lon(place.get_latitude(), place.get_longitude(), format='DEG') if lat: self.add_row(_('Latitude'), lat) if lon: self.add_row(_('Longitude'), lon) def display_alt_names(self, place): """ Display alternative names for the place. """ alt_names = place .get_alternative_names() if len(alt_names) > 0: self.add_row(_('Alternative Names'), '\n'.join(alt_names)) def display_empty(self): """ Display empty details when no repository is selected. """ self.photo.set_image(None) self.photo.set_uistate(None, None) self.title.set_text('') self.clear_grid() def display_separator(self): """ Display an empty row to separate groupd of entries. """ label = Gtk.Label(label='') label.override_font(Pango.FontDescription('sans 4')) label.show() self.grid.add(label) def load_place_image(self, place): """ Load the primary image if it exists. """ media_list = place.get_media_list() if media_list: media_ref = media_list[0] object_handle = media_ref.get_reference_handle() obj = self.dbstate.db.get_object_from_handle(object_handle) full_path = media_path_full(self.dbstate.db, obj.get_path()) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): self.photo.set_image(full_path, mime_type, media_ref.get_rectangle()) self.photo.set_uistate(self.uistate, object_handle) else: self.photo.set_image(None) self.photo.set_uistate(None, None) else: self.photo.set_image(None) self.photo.set_uistate(None, None)
class PersonDetails(Gramplet): """ Displays details for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.uistate.connect('nameformat-changed', self.update) self.uistate.connect('placeformat-changed', self.update) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.Box() vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.photo = Photo(self.uistate.screen_height() < 1000) self.photo.show() self.name = Gtk.Label(halign=Gtk.Align.START) self.name.override_font(Pango.FontDescription('sans bold 12')) self.name.set_selectable(True) vbox.pack_start(self.name, fill=True, expand=False, padding=7) self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self.grid.set_column_spacing(10) vbox.pack_start(self.grid, fill=True, expand=False, padding=5) vbox.show_all() self.top.pack_start(self.photo, fill=True, expand=False, padding=5) self.top.pack_start(vbox, fill=True, expand=True, padding=10) return self.top def add_row(self, title, value): """ Add a row to the table. """ label = Gtk.Label(label=title + COLON, halign=Gtk.Align.END, valign=Gtk.Align.START) label.set_selectable(True) label.show() value = Gtk.Label(label=value, halign=Gtk.Align.START) value.set_selectable(True) value.show() self.grid.add(label) self.grid.attach_next_to(value, label, Gtk.PositionType.RIGHT, 1, 1) def clear_grid(self): """ Remove all the rows from the grid. """ list(map(self.grid.remove, self.grid.get_children())) def db_changed(self): self.connect(self.dbstate.db, 'person-update', self.update) def active_changed(self, handle): self.update() def update_has_data(self): """ Determine if a person has_data by checking: 1. has a birth, baptism, death, or burial event; OR 2. has a father; OR 3. has a mother """ active_handle = self.get_active('Person') has_data = False if active_handle: active_person = self.dbstate.db.get_person_from_handle(active_handle) if active_person: for event_type in [EventType(EventType.BIRTH), EventType(EventType.BAPTISM), EventType(EventType.DEATH), EventType(EventType.BURIAL)]: event = self.get_event(active_person, event_type) if event: has_data = True break if not has_data: family_handle = active_person.get_main_parents_family_handle() if family_handle: family = self.dbstate.db.get_family_from_handle(family_handle) handle = family.get_father_handle() if handle: if self.dbstate.db.get_person_from_handle(handle): has_data = True else: handle = family.get_mother_handle() if handle: if self.dbstate.db.get_person_from_handle(handle): has_data = True self.set_has_data(has_data) def main(self): # return false finishes self.display_empty() active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle(active_handle) self.top.hide() if active_person: self.display_person(active_person) self.top.show() self.update_has_data() def display_person(self, active_person): """ Display details of the active person. """ self.load_person_image(active_person) self.name.set_text(name_displayer.display(active_person)) self.clear_grid() self.display_alternate_names(active_person) self.display_parents(active_person) self.display_separator() self.display_type(active_person, EventType(EventType.BIRTH)) self.display_type(active_person, EventType(EventType.BAPTISM)) self.display_type(active_person, EventType(EventType.DEATH)) self.display_type(active_person, EventType(EventType.BURIAL)) self.display_separator() self.display_attribute(active_person, _('Occupation')) self.display_attribute(active_person, _('Title')) self.display_attribute(active_person, _('Religion')) def display_empty(self): """ Display empty details when no person is selected. """ self.photo.set_image(None) self.photo.set_uistate(None, None) self.name.set_text(_('No active person')) self.clear_grid() def display_separator(self): """ Display an empty row to separate groupd of entries. """ label = Gtk.Label(label='') label.override_font(Pango.FontDescription('sans 4')) label.set_selectable(True) label.show() self.grid.add(label) def display_alternate_names(self, active_person): """ Display other names of the person """ try: nlist = active_person.get_alternate_names() if len(nlist) > 0: for altname in nlist: name_type = str(altname.get_type()) text = name_displayer.display_name(altname) self.add_row(name_type, text) self.display_separator() except: pass def display_parents(self, active_person): """ Display the parents of the active person. """ family_handle = active_person.get_main_parents_family_handle() if family_handle: family = self.dbstate.db.get_family_from_handle(family_handle) handle = family.get_father_handle() if handle: father = self.dbstate.db.get_person_from_handle(handle) father_name = name_displayer.display(father) else: father_name = _('Unknown') handle = family.get_mother_handle() if handle: mother = self.dbstate.db.get_person_from_handle(handle) mother_name = name_displayer.display(mother) else: mother_name = _('Unknown') else: father_name = _('Unknown') mother_name = _('Unknown') self.add_row(_('Father'), father_name) self.add_row(_('Mother'), mother_name) def display_attribute(self, active_person, attr_key): """ Display an attribute row. """ values = [] for attr in active_person.get_attribute_list(): if attr.get_type() == attr_key: values.append(attr.get_value()) if values: # translators: needed for Arabic, ignore otherwise self.add_row(attr_key, _(', ').join(values)) def display_type(self, active_person, event_type): """ Display an event type row. """ event = self.get_event(active_person, event_type) if event: self.add_row(str(event_type), self.format_event(event)) def get_event(self, person, event_type): """ Return an event of the given type. """ for event_ref in person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if event.get_type() == event_type: return event return None def format_event(self, event): """ Format the event for display. """ date = get_date(event) handle = event.get_place_handle() if handle: place = place_displayer.display_event(self.dbstate.db, event) retval = _('%(date)s - %(place)s.') % {'date' : date, 'place' : place} else: retval = _('%(date)s.') % dict(date=date) return retval def load_person_image(self, person): """ Load the primary image if it exists. """ media_list = person.get_media_list() if media_list: media_ref = media_list[0] object_handle = media_ref.get_reference_handle() obj = self.dbstate.db.get_media_from_handle(object_handle) full_path = media_path_full(self.dbstate.db, obj.get_path()) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): self.photo.set_image(full_path, mime_type, media_ref.get_rectangle()) self.photo.set_uistate(self.uistate, object_handle) else: self.photo.set_image(None) self.photo.set_uistate(None, None) else: self.photo.set_image(None) self.photo.set_uistate(None, None)
class PersonDetails(Gramplet): """ Displays details for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.uistate.connect('nameformat-changed', self.update) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.HBox() vbox = Gtk.VBox() self.photo = Photo(self.uistate.screen_height() < 1000) self.photo.show() self.name = Gtk.Label() self.name.set_alignment(0, 0) self.name.modify_font(Pango.FontDescription('sans bold 12')) vbox.pack_start(self.name, fill=True, expand=False, padding=7) self.table = Gtk.Table(n_rows=1, n_columns=2) vbox.pack_start(self.table, fill=True, expand=False, padding=5) vbox.show_all() self.top.pack_start(self.photo, fill=True, expand=False, padding=5) self.top.pack_start(vbox, fill=True, expand=True, padding=10) return self.top def add_row(self, title, value): """ Add a row to the table. """ label = Gtk.Label(label=title + ':') label.set_alignment(1, 0) label.show() value = Gtk.Label(label=value) value.set_alignment(0, 0) value.show() rows = self.table.get_property('n-rows') rows += 1 self.table.resize(rows, 2) self.table.attach(label, 0, 1, rows, rows + 1, xoptions=Gtk.AttachOptions.FILL, xpadding=10) self.table.attach(value, 1, 2, rows, rows + 1) def clear_table(self): """ Remove all the rows from the table. """ list(map(self.table.remove, self.table.get_children())) self.table.resize(1, 2) def db_changed(self): self.dbstate.db.connect('person-update', self.update) def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle( active_handle) self.set_has_data(active_person is not None) else: self.set_has_data(False) def main(self): # return false finishes self.display_empty() active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle( active_handle) self.top.hide() if active_person: self.display_person(active_person) self.set_has_data(True) else: self.set_has_data(False) self.top.show() else: self.set_has_data(False) def display_person(self, active_person): """ Display details of the active person. """ self.load_person_image(active_person) self.name.set_text(name_displayer.display(active_person)) self.clear_table() self.display_alternate_names(active_person) self.display_parents(active_person) self.display_separator() self.display_type(active_person, EventType(EventType.BIRTH)) self.display_type(active_person, EventType(EventType.BAPTISM)) self.display_type(active_person, EventType(EventType.DEATH)) self.display_type(active_person, EventType(EventType.BURIAL)) self.display_separator() self.display_attribute(active_person, _('Occupation')) self.display_attribute(active_person, _('Title')) self.display_attribute(active_person, _('Religion')) def display_empty(self): """ Display empty details when no person is selected. """ self.photo.set_image(None) self.photo.set_uistate(None, None) self.name.set_text(_('No active person')) self.clear_table() def display_separator(self): """ Display an empty row to separate groupd of entries. """ label = Gtk.Label(label='') label.modify_font(Pango.FontDescription('sans 4')) label.show() rows = self.table.get_property('n-rows') rows += 1 self.table.resize(rows, 2) self.table.attach(label, 0, 1, rows, rows + 1, xoptions=Gtk.AttachOptions.FILL) def display_alternate_names(self, active_person): """ Display other names of the person """ try: nlist = active_person.get_alternate_names() if len(nlist) > 0: for altname in nlist: name_type = str(altname.get_type()) text = name_displayer.display_name(altname) self.add_row(name_type, text) self.display_separator() except: pass def display_parents(self, active_person): """ Display the parents of the active person. """ family_handle = active_person.get_main_parents_family_handle() if family_handle: family = self.dbstate.db.get_family_from_handle(family_handle) handle = family.get_father_handle() if handle: father = self.dbstate.db.get_person_from_handle(handle) father_name = name_displayer.display(father) else: father_name = _('Unknown') handle = family.get_mother_handle() if handle: mother = self.dbstate.db.get_person_from_handle(handle) mother_name = name_displayer.display(mother) else: mother_name = _('Unknown') else: father_name = _('Unknown') mother_name = _('Unknown') self.add_row(_('Father'), father_name) self.add_row(_('Mother'), mother_name) def display_attribute(self, active_person, attr_key): """ Display an attribute row. """ values = [] for attr in active_person.get_attribute_list(): if attr.get_type() == attr_key: values.append(attr.get_value()) if values: self.add_row(attr_key, _(', ').join(values)) def display_type(self, active_person, event_type): """ Display an event type row. """ event = self.get_event(active_person, event_type) if event: self.add_row(str(event_type), self.format_event(event)) def get_event(self, person, event_type): """ Return an event of the given type. """ for event_ref in person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if event.get_type() == event_type: return event return None def format_event(self, event): """ Format the event for display. """ date = get_date(event) handle = event.get_place_handle() if handle: place = place_displayer.display_event(self.dbstate.db, event) retval = _('%(date)s - %(place)s.') % { 'date': date, 'place': place } else: retval = _('%(date)s.') % dict(date=date) return retval def load_person_image(self, person): """ Load the primary image if it exists. """ media_list = person.get_media_list() if media_list: media_ref = media_list[0] object_handle = media_ref.get_reference_handle() obj = self.dbstate.db.get_object_from_handle(object_handle) full_path = media_path_full(self.dbstate.db, obj.get_path()) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): self.photo.set_image(full_path, mime_type, media_ref.get_rectangle()) self.photo.set_uistate(self.uistate, object_handle) else: self.photo.set_image(None) self.photo.set_uistate(None, None) else: self.photo.set_image(None) self.photo.set_uistate(None, None)
class PlaceDetails(Gramplet): """ Displays details for a place. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) def build_gui(self): """ Build the GUI interface. """ self.top = Gtk.HBox() vbox = Gtk.VBox() self.photo = Photo(self.uistate.screen_height() < 1000) self.title = Gtk.Label() self.title.set_alignment(0, 0) self.title.modify_font(Pango.FontDescription('sans bold 12')) vbox.pack_start(self.title, False, True, 7) self.table = Gtk.Table(n_rows=1, n_columns=2) vbox.pack_start(self.table, False, True, 0) self.top.pack_start(self.photo, False, True, 5) self.top.pack_start(vbox, False, True, 10) self.top.show_all() return self.top def add_row(self, title, value): """ Add a row to the table. """ label = Gtk.Label(label=title + ':') label.set_alignment(1, 0) label.show() value = Gtk.Label(label=value) value.set_alignment(0, 0) value.show() rows = self.table.get_property('n-rows') rows += 1 self.table.resize(rows, 2) self.table.attach(label, 0, 1, rows, rows + 1, xoptions=Gtk.AttachOptions.FILL, xpadding=10) self.table.attach(value, 1, 2, rows, rows + 1) def clear_table(self): """ Remove all the rows from the table. """ list(map(self.table.remove, self.table.get_children())) self.table.resize(1, 2) def db_changed(self): self.dbstate.db.connect('place-update', self.update) self.connect_signal('Place', self.update) def update_has_data(self): active_handle = self.get_active('Person') if active_handle: active_person = self.dbstate.db.get_person_from_handle( active_handle) self.set_has_data(active_person is not None) else: self.set_has_data(False) def main(self): self.display_empty() active_handle = self.get_active('Place') if active_handle: place = self.dbstate.db.get_place_from_handle(active_handle) self.top.hide() if place: self.display_place(place) self.set_has_data(True) else: self.set_has_data(False) self.top.show() else: self.set_has_data(False) def display_place(self, place): """ Display details of the active place. """ self.load_place_image(place) self.title.set_text(place.get_title()) self.clear_table() self.display_location(place) self.display_separator() lat, lon = conv_lat_lon(place.get_latitude(), place.get_longitude(), format='DEG') if lat: self.add_row(_('Latitude'), lat) if lon: self.add_row(_('Longitude'), lon) def display_location(self, place): """ Display a location. """ lines = get_location_list(self.dbstate.db, place) self.add_row(_('Location'), '\n'.join(lines)) def display_empty(self): """ Display empty details when no repository is selected. """ self.photo.set_image(None) self.photo.set_uistate(None, None) self.title.set_text('') self.clear_table() def display_separator(self): """ Display an empty row to separate groupd of entries. """ label = Gtk.Label(label='') label.modify_font(Pango.FontDescription('sans 4')) label.show() rows = self.table.get_property('n-rows') rows += 1 self.table.resize(rows, 2) self.table.attach(label, 0, 1, rows, rows + 1, xoptions=Gtk.AttachOptions.FILL) def load_place_image(self, place): """ Load the primary image if it exists. """ media_list = place.get_media_list() if media_list: media_ref = media_list[0] object_handle = media_ref.get_reference_handle() obj = self.dbstate.db.get_object_from_handle(object_handle) full_path = media_path_full(self.dbstate.db, obj.get_path()) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): self.photo.set_image(full_path, mime_type, media_ref.get_rectangle()) self.photo.set_uistate(self.uistate, object_handle) else: self.photo.set_image(None) self.photo.set_uistate(None, None) else: self.photo.set_image(None) self.photo.set_uistate(None, None)