diff --git a/gramps/gui/editors/displaytabs/placerefembedlist.py b/gramps/gui/editors/displaytabs/placerefembedlist.py index 441929f79..39dfb4216 100644 --- a/gramps/gui/editors/displaytabs/placerefembedlist.py +++ b/gramps/gui/editors/displaytabs/placerefembedlist.py @@ -33,12 +33,13 @@ from gi.repository import GLib # GRAMPS classes # #------------------------------------------------------------------------- -from gramps.gen.lib import PlaceRef +from gramps.gen.lib import Place, PlaceRef from gramps.gen.errors import WindowActiveError from ...dialog import ErrorDialog from ...ddtargets import DdTargets from .placerefmodel import PlaceRefModel from .embeddedlist import EmbeddedList, TEXT_COL +from ...selectors import SelectorFactory #------------------------------------------------------------------------- # @@ -65,7 +66,7 @@ class PlaceRefEmbedList(EmbeddedList): self.handle = handle EmbeddedList.__init__(self, dbstate, uistate, track, _('Enclosed By'), PlaceRefModel, - move_buttons=True) + share_button=True, move_buttons=True) def get_data(self): return self.data @@ -86,31 +87,49 @@ class PlaceRefEmbedList(EmbeddedList): return skip def add_button_clicked(self, obj): - placeref = PlaceRef() + ref = PlaceRef() + place = Place() try: from .. import EditPlaceRef EditPlaceRef(self.dbstate, self.uistate, self.track, - placeref, self.handle, self.add_callback) + place, ref, self.add_callback) except WindowActiveError: pass - def add_callback(self, name): + def add_callback(self, ref, place): + ref.ref = place.handle data = self.get_data() - data.append(name) + data.append(ref) self.rebuild() GLib.idle_add(self.tree.scroll_to_cell, len(data) - 1) - def edit_button_clicked(self, obj): - placeref = self.get_selected() - if placeref: + def share_button_clicked(self, obj): + SelectPlace = SelectorFactory('Place') + + sel = SelectPlace(self.dbstate, self.uistate, self.track, + skip=self.get_skip_list(self.handle)) + place = sel.run() + if place: + ref = PlaceRef() try: from .. import EditPlaceRef - EditPlaceRef(self.dbstate, self.uistate, self.track, - placeref, self.handle, self.edit_callback) + EditPlaceRef(self.dbstate, self.uistate, self.track, + place, ref, self.add_callback) except WindowActiveError: pass - def edit_callback(self, name): + def edit_button_clicked(self, obj): + ref = self.get_selected() + if ref: + place = self.dbstate.db.get_place_from_handle(ref.ref) + try: + from .. import EditPlaceRef + EditPlaceRef(self.dbstate, self.uistate, self.track, + place, ref, self.edit_callback) + except WindowActiveError: + pass + + def edit_callback(self, ref, place): self.rebuild() def handle_extra_type(self, objtype, obj): @@ -119,11 +138,11 @@ class PlaceRefEmbedList(EmbeddedList): _("The place you are adding is already enclosed by " "this place")) return + place = self.dbstate.db.get_place_from_handle(obj) placeref = PlaceRef() - placeref.ref = obj try: from .. import EditPlaceRef EditPlaceRef(self.dbstate, self.uistate, self.track, - placeref, self.handle, self.add_callback) + place, placeref, self.add_callback) except WindowActiveError: pass diff --git a/gramps/gui/editors/editplaceref.py b/gramps/gui/editors/editplaceref.py index 83911be33..6bd1dfd5c 100644 --- a/gramps/gui/editors/editplaceref.py +++ b/gramps/gui/editors/editplaceref.py @@ -2,7 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2006 Donald N. Allingham -# Copyright (C) 2013 Nick Hall +# Copyright (C) 2015 Nick Hall # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -24,11 +24,17 @@ # Gramps modules # #------------------------------------------------------------------------- -from .editsecondary import EditSecondary +from .editreference import RefTab, EditReference from ..glade import Glade -from ..widgets import MonitoredDate -from .objectentries import PlaceEntry -from ..dialog import ErrorDialog +from ..widgets import (MonitoredDate, MonitoredEntry, MonitoredDataType, + PrivacyButton, MonitoredTagList) +from .displaytabs import (PlaceRefEmbedList, AltNameEmbedList, + LocationEmbedList, CitationEmbedList, + GalleryTab, NoteTab, WebEmbedList, PlaceBackRefList) +from gramps.gen.lib import NoteType +from gramps.gen.db import DbTxn +from gramps.gen.errors import ValidationError +from gramps.gen.utils.place import conv_lat_lon from gramps.gen.const import GRAMPS_LOCALE as glocale _ = glocale.translation.gettext @@ -37,63 +43,212 @@ _ = glocale.translation.gettext # EditPlaceRef class # #------------------------------------------------------------------------- -class EditPlaceRef(EditSecondary): +class EditPlaceRef(EditReference): - def __init__(self, dbstate, uistate, track, placeref, handle, callback): - self.handle = handle - EditSecondary.__init__(self, dbstate, uistate, track, - placeref, callback) + def __init__(self, state, uistate, track, place, place_ref, update): + EditReference.__init__(self, state, uistate, track, place, place_ref, + update) def _local_init(self): self.width_key = 'interface.place-ref-width' self.height_key = 'interface.place-ref-height' self.top = Glade() self.set_window(self.top.toplevel, None, _('Place Reference Editor')) + self.define_warn_box(self.top.get_object("warning")) + self.define_expander(self.top.get_object("expander")) + #self.place_name_label = self.top.get_object('place_name_label') + #self.place_name_label.set_text(_('place|Name:')) - self.share_btn = self.top.get_object('select_place') - self.add_del_btn = self.top.get_object('add_del_place') + tblref = self.top.get_object('table64') + notebook = self.top.get_object('notebook_ref') + #recreate start page as GrampsTab + notebook.remove_page(0) + self.reftab = RefTab(self.dbstate, self.uistate, self.track, + _('General'), tblref) + tblref = self.top.get_object('table62') + notebook = self.top.get_object('notebook') + #recreate start page as GrampsTab + notebook.remove_page(0) + self.primtab = RefTab(self.dbstate, self.uistate, self.track, + _('_General'), tblref) + + def _connect_signals(self): + self.define_cancel_button(self.top.get_object('cancel')) + self.ok_button = self.top.get_object('ok') + self.define_ok_button(self.ok_button, self.save) + self.define_help_button(self.top.get_object('help')) + + def _connect_db_signals(self): + """ + Connect any signals that need to be connected. + Called by the init routine of the base class (_EditPrimary). + """ + self._add_db_signal('place-rebuild', self.close) + self._add_db_signal('place-delete', self.check_for_close) + + def build_menu_names(self, placeref): + if self.source and self.source.get_handle(): + title = self.source.get_title() + submenu_label = _('Place: %s') % title + else: + submenu_label = _('New Place') + return (_('Place Reference Editor'), submenu_label) def _setup_fields(self): self.date_field = MonitoredDate(self.top.get_object("date_entry"), self.top.get_object("date_stat"), - self.obj.get_date_object(), + self.source_ref.get_date_object(), self.uistate, self.track, self.db.readonly) - self.place_field = PlaceEntry(self.dbstate, self.uistate, self.track, - self.top.get_object("place"), - self.obj.set_reference_handle, - self.obj.get_reference_handle, - self.add_del_btn, self.share_btn, - skip=self.get_skip_list(self.handle)) + self.title = MonitoredEntry(self.top.get_object("place_title"), + self.source.set_title, self.source.get_title, + self.db.readonly) + + self.name = MonitoredEntry(self.top.get_object("name_entry"), + self.source.set_name, self.source.get_name, + self.db.readonly) + + self.gid = MonitoredEntry(self.top.get_object("gid"), + self.source.set_gramps_id, + self.source.get_gramps_id, self.db.readonly) + + self.tags = MonitoredTagList(self.top.get_object("tag_label"), + self.top.get_object("tag_button"), + self.source.set_tag_list, + self.source.get_tag_list, + self.db, + self.uistate, self.track, + self.db.readonly) - def get_skip_list(self, handle): - todo = [handle] - skip = [handle] - while todo: - handle = todo.pop() - for child in self.db.find_backlink_handles(handle, ['Place']): - if child[1] not in skip: - todo.append(child[1]) - skip.append(child[1]) - return skip + self.privacy = PrivacyButton(self.top.get_object("private"), self.source, + self.db.readonly) - def _connect_signals(self): - self.define_cancel_button(self.top.get_object('cancel_button')) - self.ok_button = self.top.get_object('ok_button') - self.define_ok_button(self.ok_button, self.save) - self.define_help_button(self.top.get_object('help_button')) + self.place_type = MonitoredDataType(self.top.get_object("place_type"), + self.source.set_type, + self.source.get_type, + self.db.readonly, + self.db.get_place_types()) + + self.code = MonitoredEntry( + self.top.get_object("code_entry"), + self.source.set_code, self.source.get_code, + self.db.readonly) + + self.longitude = MonitoredEntry( + self.top.get_object("lon_entry"), + self.source.set_longitude, self.source.get_longitude, + self.db.readonly) + self.longitude.connect("validate", self._validate_coordinate, "lon") + #force validation now with initial entry + self.top.get_object("lon_entry").validate(force=True) + + self.latitude = MonitoredEntry( + self.top.get_object("lat_entry"), + self.source.set_latitude, self.source.get_latitude, + self.db.readonly) + self.latitude.connect("validate", self._validate_coordinate, "lat") + #force validation now with initial entry + self.top.get_object("lat_entry").validate(force=True) + + def _validate_coordinate(self, widget, text, typedeg): + if (typedeg == 'lat') and not conv_lat_lon(text, "0", "ISO-D"): + return ValidationError(_("Invalid latitude (syntax: 18\u00b09'") + + _('48.21"S, -18.2412 or -18:9:48.21)')) + elif (typedeg == 'lon') and not conv_lat_lon("0", text, "ISO-D"): + return ValidationError(_("Invalid longitude (syntax: 18\u00b09'") + + _('48.21"E, -18.2412 or -18:9:48.21)')) + + def _create_tabbed_pages(self): + """ + Create the notebook tabs and inserts them into the main + window. + + """ + notebook = self.top.get_object('notebook') + notebook_ref = self.top.get_object('notebook_ref') + + self._add_tab(notebook, self.primtab) + self._add_tab(notebook_ref, self.reftab) + self.track_ref_for_deletion("primtab") + self.track_ref_for_deletion("reftab") + + self.placeref_list = PlaceRefEmbedList(self.dbstate, + self.uistate, + self.track, + self.source.get_placeref_list(), + self.source.handle) + self._add_tab(notebook, self.placeref_list) + self.track_ref_for_deletion("placeref_list") + + self.alt_name_list = AltNameEmbedList(self.dbstate, + self.uistate, + self.track, + self.source.alt_names) + self._add_tab(notebook, self.alt_name_list) + self.track_ref_for_deletion("alt_name_list") + + if len(self.source.alt_loc) > 0: + self.loc_list = LocationEmbedList(self.dbstate, + self.uistate, + self.track, + self.source.alt_loc) + self._add_tab(notebook, self.loc_list) + self.track_ref_for_deletion("loc_list") + + self.citation_list = CitationEmbedList(self.dbstate, + self.uistate, + self.track, + self.source.get_citation_list()) + self._add_tab(notebook, self.citation_list) + self.track_ref_for_deletion("citation_list") + + self.note_tab = NoteTab(self.dbstate, + self.uistate, + self.track, + self.source.get_note_list(), + notetype=NoteType.PLACE) + self._add_tab(notebook, self.note_tab) + self.track_ref_for_deletion("note_tab") + + self.gallery_tab = GalleryTab(self.dbstate, + self.uistate, + self.track, + self.source.get_media_list()) + self._add_tab(notebook, self.gallery_tab) + self.track_ref_for_deletion("gallery_tab") + + self.web_list = WebEmbedList(self.dbstate, + self.uistate, + self.track, + self.source.get_url_list()) + self._add_tab(notebook, self.web_list) + self.track_ref_for_deletion("web_list") + + self.backref_list = PlaceBackRefList(self.dbstate, + self.uistate, + self.track, + self.db.find_backlink_handles(self.source.handle)) + self.backref_tab = self._add_tab(notebook, self.backref_list) + self.track_ref_for_deletion("backref_list") + self.track_ref_for_deletion("backref_tab") + + self._setup_notebook_tabs(notebook) def save(self, *obj): - self.ok_button.set_sensitive(False) - if not self.obj.ref: - ErrorDialog(_("Cannot save place reference"), - _("No place selected. Please select a place " - " or cancel the edit.")) - self.ok_button.set_sensitive(True) - return - if self.callback: - self.callback(self.obj) + if self.source.handle: + with DbTxn(_("Modify Place"), self.db) as trans: + self.db.commit_place(self.source, trans) + else: + if self.check_for_duplicate_id('Place'): + return + with DbTxn(_("Add Place"), self.db) as trans: + self.db.add_place(self.source, trans) + self.source_ref.ref = self.source.handle + + if self.update: + self.update(self.source_ref, self.source) + self.close() diff --git a/gramps/gui/glade/editplaceref.glade b/gramps/gui/glade/editplaceref.glade index 2e9edf324..4f44ee397 100644 --- a/gramps/gui/glade/editplaceref.glade +++ b/gramps/gui/glade/editplaceref.glade @@ -5,20 +5,21 @@ False - 550 + 600 dialog - + True False - + True False end - - gtk-cancel + + gtk-help + False True True True @@ -32,12 +33,12 @@ - - gtk-ok + + gtk-cancel + False True True True - True True True @@ -48,8 +49,9 @@ - - gtk-help + + gtk-ok + False True True True @@ -71,26 +73,47 @@ - + True False + 0 + 6 + 3 + Reference information + True + center + + + + + + False + False + 1 + + + + + True + True + 6 - + True False 12 - 2 4 12 6 - + True False - 1 - Place: + 0 + 3 + _Date: True - right + center GTK_FILL @@ -98,29 +121,12 @@ - + True - False - 1 - Date: - True + True - 1 - 2 - GTK_FILL - - - - - - True - False - True - none - - - 2 + 1 3 GTK_FILL @@ -131,73 +137,13 @@ True True True - True - Invoke date editor - none True False - True - Show Date Editor gramps-date - - - Date - - - - - Date - - - - - - 3 - 4 - 1 - 2 - GTK_FILL - - - - - - True - False - 1 - - - 1 - 2 - - - - - - 27 - True - True - Date range for which the link is valid. - - - - 1 - 3 - 1 - 2 - - - - - - True - True - True - none 3 @@ -207,25 +153,493 @@ + + + + True + False + General + + + + - True - True - 0 + False - False + True True - 1 + 2 + + + + + True + True + 6 + True + 6 + + + True + True + False + + + True + False + 12 + 5 + 5 + 12 + 6 + + + + + + + + + + + + True + False + 0 + Title: + True + center + + + GTK_FILL + + + + + + True + False + 0 + Name: + True + center + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + 3 + ID: + True + center + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Latitude: + True + + + 2 + 3 + GTK_FILL + + + + + + False + 6 + 12 + + + True + False + 0 + gtk-dialog-warning + 6 + + + False + False + 0 + + + + + 500 + True + False + 0 + 4 + <b>Note:</b> Any changes in the enclosing place information will be reflected in the place itself, for places that it encloses. + True + fill + True + + + True + True + 1 + + + + + 4 + 4 + 5 + GTK_SHRINK + + + + + True + False + 0 + Type: + True + center + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Longitude: + True + center + + + 2 + 3 + 2 + 3 + GTK_FILL + + + + + + True + False + True + + + False + + + + + 3 + 4 + 1 + 2 + + + + + + True + True + True + none + + + True + False + gtk-dialog-authentication + + + Privacy + + + + + + + Private + + + + + + 4 + 5 + 2 + 3 + + + + + + + True + True + Full title of this place. + + + + 1 + 4 + + + + + + True + True + The name of this place. + + + + 1 + 2 + 1 + 2 + + + + + + True + True + Latitude (position above the Equator) of the place in decimal or degree notation. +Eg, valid values are 12.0154, 50°52′21.92″N, N50°52′21.92″ or 50:52:21.92 +You can set these values via the Geography View by searching the place, or via a map service in the place view. + + + + 1 + 2 + 2 + 3 + + + + + + True + True + Longitude (position relative to the Prime, or Greenwich, Meridian) of the place in decimal or degree notation. +Eg, valid values are -124.3647, 124°52′21.92″E, E124°52′21.92″ or 124:52:21.92 +You can set these values via the Geography View by searching the place, or via a map service in the place view. + + + + 3 + 4 + 2 + 3 + + + + + + True + False + 6 + + + 75 + True + True + A unique ID to identify the place + + 6 + + + False + True + 0 + + + + + True + False + 0 + Code: + True + + + False + True + 1 + + + + + True + True + Code associated with this place. Eg Country Code or Postal Code. + + 8 + + + True + True + 2 + + + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + False + 0 + Tags: + + + 2 + 3 + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + + + 3 + 4 + 3 + 4 + + + + + + True + True + True + True + + + 4 + 5 + 3 + 4 + + + + + + + False + + + + + True + False + 6 + + + True + False + gtk-file + 1 + + + True + True + 0 + + + + + True + False + General + center + + + + + + False + False + 1 + + + + + False + + + + + + + + + + + + + True + False + Shared information + + + + + + + + True + True + 3 - cancel_button - ok_button - help_button + help + cancel + ok