From eedbe0db67e17ec7801cbb7edcb8a4c00dddb751 Mon Sep 17 00:00:00 2001 From: prculley Date: Thu, 25 May 2017 17:36:13 -0500 Subject: [PATCH 01/23] Fix HandleError in Citation gramplet Fixes #10054. --- gramps/plugins/gramplet/citations.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gramps/plugins/gramplet/citations.py b/gramps/plugins/gramplet/citations.py index 5c5d168ed..80391efa0 100644 --- a/gramps/plugins/gramplet/citations.py +++ b/gramps/plugins/gramplet/citations.py @@ -133,9 +133,10 @@ class Citations(Gramplet, DbGUIElement): for lds in obj.get_lds_ord_list(): self.add_citations(lds) place_handle = lds.get_place_handle() - place = self.dbstate.db.get_place_from_handle(place_handle) - if place: - self.add_place_citations(place) + if place_handle: + place = self.dbstate.db.get_place_from_handle(place_handle) + if place: + self.add_place_citations(place) def add_association_citations(self, obj): for assoc in obj.get_person_ref_list(): From 5f93da13436ef2fe41bdc834e69b3c99b5122431 Mon Sep 17 00:00:00 2001 From: prculley Date: Sat, 27 May 2017 11:28:47 -0500 Subject: [PATCH 02/23] HandleError on Relationship view for add child with no father Fixes #10059. --- gramps/plugins/view/relview.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gramps/plugins/view/relview.py b/gramps/plugins/view/relview.py index fcd9d3423..6c3c365fe 100644 --- a/gramps/plugins/view/relview.py +++ b/gramps/plugins/view/relview.py @@ -1541,10 +1541,11 @@ class RelationshipView(NavigationView): name.add_surname(Surname()) name.set_primary_surname(0) family = self.dbstate.db.get_family_from_handle(handle) - father = self.dbstate.db.get_person_from_handle( - family.get_father_handle()) - if father: - preset_name(father, name) + father_h = family.get_father_handle() + if father_h: + father = self.dbstate.db.get_person_from_handle(father_h) + if father: + preset_name(father, name) person.set_primary_name(name) try: EditPerson(self.dbstate, self.uistate, [], person, From 676825cf52530db23e62bf6e2f726169dfea45fe Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Thu, 15 Jun 2017 19:55:31 -0400 Subject: [PATCH 03/23] Removes try/except and recursion in ancestor filters +/- N gens This fix rewrites the Ancestor-of +/- N filters to remove the try/except and removes the recursion. The recursion would only be a problem on very deep trees, but the try/except was hiding a variety of problems. Most directly, if a person did not have a main family then it would exit out of the loop. (I don't have a test database to break the code other than my real data, so you'll have to do that part.) I also made sure that the meaning of N is consistent in both filters: 1 - root person 2 - root person's parents 3 - root person's grandparents --- .../_islessthannthgenerationancestorof.py | 52 +++++++++---------- .../_ismorethannthgenerationancestorof.py | 50 +++++++++--------- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/gramps/gen/filters/rules/person/_islessthannthgenerationancestorof.py b/gramps/gen/filters/rules/person/_islessthannthgenerationancestorof.py index 48139b1cd..b95e330d1 100644 --- a/gramps/gen/filters/rules/person/_islessthannthgenerationancestorof.py +++ b/gramps/gen/filters/rules/person/_islessthannthgenerationancestorof.py @@ -51,36 +51,34 @@ class IsLessThanNthGenerationAncestorOf(Rule): def prepare(self, db, user): self.db = db self.map = set() - try: - root_handle = db.get_person_from_gramps_id(self.list[0]).get_handle() - self.init_ancestor_list(root_handle,0) - except: - pass + person = db.get_person_from_gramps_id(self.list[0]) + if person: + root_handle = person.get_handle() + if root_handle: + self.init_ancestor_list(root_handle) + + def init_ancestor_list(self, root_handle): + queue = [(root_handle, 1)] # generation 1 is root + while queue: + handle, gen = queue.pop(0) # pop off front of queue + self.map.add(handle) + gen += 1 + if gen <= int(self.list[1]): + p = self.db.get_person_from_handle(handle) + fam_id = p.get_main_parents_family_handle() + if fam_id: + fam = self.db.get_family_from_handle(fam_id) + if fam: + f_id = fam.get_father_handle() + m_id = fam.get_mother_handle() + # append to back of queue: + if f_id: + queue.append((f_id, gen)) + if m_id: + queue.append((m_id, gen)) def reset(self): self.map.clear() def apply(self,db,person): return person.handle in self.map - - def init_ancestor_list(self, handle,gen): -# if p.get_handle() in self.map: -# loop_error(self.orig,p) - if not handle: - return - if gen: - self.map.add(handle) - if gen >= int(self.list[1]): - return - - p = self.db.get_person_from_handle(handle) - fam_id = p.get_main_parents_family_handle() - fam = self.db.get_family_from_handle(fam_id) - if fam: - f_id = fam.get_father_handle() - m_id = fam.get_mother_handle() - - if f_id: - self.init_ancestor_list(f_id,gen+1) - if m_id: - self.init_ancestor_list(m_id,gen+1) diff --git a/gramps/gen/filters/rules/person/_ismorethannthgenerationancestorof.py b/gramps/gen/filters/rules/person/_ismorethannthgenerationancestorof.py index 11e9f6158..9ee74c59f 100644 --- a/gramps/gen/filters/rules/person/_ismorethannthgenerationancestorof.py +++ b/gramps/gen/filters/rules/person/_ismorethannthgenerationancestorof.py @@ -51,34 +51,34 @@ class IsMoreThanNthGenerationAncestorOf(Rule): def prepare(self, db, user): self.db = db self.map = set() - try: - root_handle = db.get_person_from_gramps_id(self.list[0]).get_handle() - self.init_ancestor_list(root_handle,0) - except: - pass + person = db.get_person_from_gramps_id(self.list[0]) + if person: + root_handle = person.get_handle() + if root_handle: + self.init_ancestor_list(root_handle) + + def init_ancestor_list(self, root_handle): + queue = [(root_handle, 1)] # generation 1 is root + while queue: + handle, gen = queue.pop(0) # pop off front of queue + if gen > int(self.list[1]): + self.map.add(handle) + gen += 1 + p = self.db.get_person_from_handle(handle) + fam_id = p.get_main_parents_family_handle() + if fam_id: + fam = self.db.get_family_from_handle(fam_id) + if fam: + f_id = fam.get_father_handle() + m_id = fam.get_mother_handle() + # append to back of queue: + if f_id: + queue.append((f_id, gen)) + if m_id: + queue.append((m_id, gen)) def reset(self): self.map.clear() def apply(self,db,person): return person.handle in self.map - - def init_ancestor_list(self, handle, gen): -# if p.get_handle() in self.map: -# loop_error(self.orig,p) - if not handle: - return - if gen >= int(self.list[1]): - self.map.add(handle) - - p = self.db.get_person_from_handle(handle) - fam_id = p.get_main_parents_family_handle() - fam = self.db.get_family_from_handle(fam_id) - if fam: - f_id = fam.get_father_handle() - m_id = fam.get_mother_handle() - - if f_id: - self.init_ancestor_list(f_id, gen+1) - if m_id: - self.init_ancestor_list(m_id, gen+1) From 1a4d43dbbf89fc8101cdec8dff6798bcc2f5a0d8 Mon Sep 17 00:00:00 2001 From: SNoiraud Date: Fri, 16 Jun 2017 14:54:04 +0200 Subject: [PATCH 04/23] 10088: Geography: try to link a map position if we have an active place. --- gramps/plugins/view/geoperson.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/gramps/plugins/view/geoperson.py b/gramps/plugins/view/geoperson.py index c9f4a8914..67f5fbae9 100644 --- a/gramps/plugins/view/geoperson.py +++ b/gramps/plugins/view/geoperson.py @@ -201,12 +201,7 @@ class GeoPerson(GeoGraphyView): Rebuild the tree with the given person handle as the root. """ active = self.get_active() - #if handle: - # self._createmap(handle) - #elif active: - # p1 = self.dbstate.db.get_person_from_handle(active) - # self._createmap(p1) - self._createmap() + self._createmap(None) self.uistate.modify_statusbar(self.dbstate) def build_tree(self): @@ -216,8 +211,7 @@ class GeoPerson(GeoGraphyView): information. """ active = self.get_active() - #self._createmap(active) - self._createmap() + self._createmap(None) self.uistate.modify_statusbar(self.dbstate) def animate(self, menu, marks, index, stepyear): @@ -288,10 +282,11 @@ class GeoPerson(GeoGraphyView): menu, marks, i, stepyear) return False - def _createmap(self): + def _createmap(self, active): """ Create all markers for each people's event in the database which has a lat/lon. + @param: active is mandatory but unused in this view. Fix : 10088 """ dbstate = self.dbstate self.cal = config.get('preferences.calendar-format-report') From bec8cea3e39642e146b85c94512d43eeef0d5e2d Mon Sep 17 00:00:00 2001 From: Josip Date: Fri, 16 Jun 2017 16:53:36 +0200 Subject: [PATCH 05/23] DBAPI: PostgreSQL crash (#421) Fixes #0010071. --- gramps/plugins/db/dbapi/postgresql.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gramps/plugins/db/dbapi/postgresql.py b/gramps/plugins/db/dbapi/postgresql.py index eca488584..95246e9eb 100644 --- a/gramps/plugins/db/dbapi/postgresql.py +++ b/gramps/plugins/db/dbapi/postgresql.py @@ -65,6 +65,7 @@ class Postgresql: query = query.replace("?", "%s") query = query.replace("REGEXP", "~") query = query.replace("desc", "desc_") + query = query.replace("BLOB", "bytea") ## LIMIT offset, count ## count can be -1, for all ## LIMIT -1 @@ -114,7 +115,7 @@ class Postgresql: def table_exists(self, table): self.__cursor.execute("SELECT COUNT(*) " "FROM information_schema.tables " - "WHERE table_name=?;", [table]) + "WHERE table_name=%s;", [table]) return self.fetchone()[0] != 0 def close(self): From 620845bc4f688853f578093ace773eff2f2967ce Mon Sep 17 00:00:00 2001 From: prculley Date: Wed, 7 Jun 2017 16:01:46 -0500 Subject: [PATCH 06/23] Top surnames Gramplet doesn't update when db is closed Fixes #10073. --- gramps/plugins/gramplet/topsurnamesgramplet.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gramps/plugins/gramplet/topsurnamesgramplet.py b/gramps/plugins/gramplet/topsurnamesgramplet.py index 591b6746a..e3bf54c97 100644 --- a/gramps/plugins/gramplet/topsurnamesgramplet.py +++ b/gramps/plugins/gramplet/topsurnamesgramplet.py @@ -57,6 +57,7 @@ class TopSurnamesGramplet(Gramplet): self.dbstate.db.connect('person-update', self.update) self.dbstate.db.connect('person-rebuild', self.update) self.dbstate.db.connect('family-rebuild', self.update) + self.set_text(_("No Family Tree loaded.")) def on_load(self): if len(self.gui.data) > 0: From 3150fae2b8e46ffa61f6170ffc72a7c56697cb7d Mon Sep 17 00:00:00 2001 From: prculley Date: Sun, 11 Jun 2017 11:30:10 -0500 Subject: [PATCH 07/23] Error on 'cancel' for db upgrade Fixes #10065. --- gramps/gui/viewmanager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gramps/gui/viewmanager.py b/gramps/gui/viewmanager.py index 494bae522..ab1177087 100644 --- a/gramps/gui/viewmanager.py +++ b/gramps/gui/viewmanager.py @@ -1178,7 +1178,8 @@ class ViewManager(CLIManager): self.dbstate.db.close(user=self.user) (filename, title) = value self.db_loader.read_file(filename) - self._post_load_newdb(filename, 'x-directory/normal', title) + if self.dbstate.db.is_open(): + self._post_load_newdb(filename, 'x-directory/normal', title) else: if dialog.after_change != "": # We change the title of the main window. From c1aeb6b203d2e3c6b9ef2a5f23ab5a59af34add6 Mon Sep 17 00:00:00 2001 From: prculley Date: Sun, 28 May 2017 13:44:01 -0500 Subject: [PATCH 08/23] Undo of delete doesn't update views Fixes #10056. --- gramps/gen/db/generic.py | 33 ++++++++++++++-------------- gramps/plugins/db/bsddb/undoredo.py | 34 +++++++++++++---------------- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/gramps/gen/db/generic.py b/gramps/gen/db/generic.py index 1d5332d28..9f958a0c9 100644 --- a/gramps/gen/db/generic.py +++ b/gramps/gen/db/generic.py @@ -44,7 +44,7 @@ import glob from . import (DbReadBase, DbWriteBase, DbUndo, DBLOGNAME, DBUNDOFN, KEY_TO_CLASS_MAP, REFERENCE_KEY, PERSON_KEY, FAMILY_KEY, CITATION_KEY, SOURCE_KEY, EVENT_KEY, MEDIA_KEY, PLACE_KEY, - REPOSITORY_KEY, NOTE_KEY, TAG_KEY) + REPOSITORY_KEY, NOTE_KEY, TAG_KEY, TXNADD, TXNDEL) from ..errors import HandleError from ..utils.callback import Callback from ..updatecallback import UpdateCallback @@ -147,11 +147,11 @@ class DbGenericUndo(DbUndo): # now emit the signals for record_id in subitems: (key, trans_type, handle, old_data, new_data) = \ - pickle.loads(self.undodb[record_id]) + pickle.loads(self.undodb[record_id]) if key != REFERENCE_KEY: - self.undo_signals(new_data, handle, key, - db.emit, SIGBASE[key]) + self.undo_signals(trans_type, handle, + db.emit, SIGBASE[key], False) self.db._txn_commit() except: self.db._txn_abort() @@ -201,8 +201,8 @@ class DbGenericUndo(DbUndo): pickle.loads(self.undodb[record_id]) if key != REFERENCE_KEY: - self.undo_signals(old_data, handle, key, - db.emit, SIGBASE[key]) + self.undo_signals(trans_type, handle, + db.emit, SIGBASE[key], True) self.db._txn_commit() except: self.db._txn_abort() @@ -257,20 +257,19 @@ class DbGenericUndo(DbUndo): obj = self.db._get_table_func(cls)["class_func"].create(data) self.db._update_secondary_values(obj) - def undo_signals(self, data, handle, obj_key, emit, signal_root): + def undo_signals(self, trans_type, handle, emit, signal_root, reverse): """ Helper method to undo/redo the changes made """ - cls = KEY_TO_CLASS_MAP[obj_key] - table = cls.lower() - if data is None: - emit(signal_root + '-delete', ([handle],)) - else: - if self.db.has_handle(obj_key, handle): - signal = signal_root + '-update' - else: - signal = signal_root + '-add' - emit(signal, ([handle],)) + if ((not reverse) and trans_type == TXNADD) \ + or (reverse and trans_type == TXNDEL): + typ = '-add' + elif not reverse and trans_type == TXNDEL \ + or reverse and trans_type == TXNADD: + typ = '-delete' + else: # TXNUPD + typ = '-update' + emit(signal_root + typ, ([handle],)) class Cursor: def __init__(self, iterator): diff --git a/gramps/plugins/db/bsddb/undoredo.py b/gramps/plugins/db/bsddb/undoredo.py index 21e1951e3..b69ac56a8 100644 --- a/gramps/plugins/db/bsddb/undoredo.py +++ b/gramps/plugins/db/bsddb/undoredo.py @@ -244,8 +244,9 @@ class DbUndo: pickle.loads(self.undodb[record_id]) if key != REFERENCE_KEY: - self.undo_signals(old_data, handle, self.mapbase[key], - db.emit, _SIGBASE[key]) + self.undo_signals(trans_type, handle, + db.emit, _SIGBASE[key], True) + # Notify listeners if db.undo_callback: if self.undo_count > 0: @@ -289,8 +290,8 @@ class DbUndo: pickle.loads(self.undodb[record_id]) if key != REFERENCE_KEY: - self.undo_signals(new_data, handle, self.mapbase[key], - db.emit, _SIGBASE[key]) + self.undo_signals(trans_type, handle, + db.emit, _SIGBASE[key], False) # Notify listeners if db.undo_callback: db.undo_callback(_("_Undo %s") @@ -336,24 +337,19 @@ class DbUndo: self.db._log_error() raise DbError(msg) - def undo_signals(self, data, handle, db_map, emit, signal_root): + def undo_signals(self, trans_type, handle, emit, signal_root, reverse): """ Helper method to undo/redo the changes made """ - try: - if data is None: - emit(signal_root + '-delete', ([handle.decode('utf-8')],)) - else: - ex_data = db_map.get(handle, txn=self.txn) - if ex_data: - signal = signal_root + '-update' - else: - signal = signal_root + '-add' - emit(signal, ([handle.decode('utf-8')],)) - - except DBERRS as msg: - self.db._log_error() - raise DbError(msg) + if ((not reverse) and trans_type == TXNADD) \ + or (reverse and trans_type == TXNDEL): + typ = '-add' + elif not reverse and trans_type == TXNDEL \ + or reverse and trans_type == TXNADD: + typ = '-delete' + else: # TXNUPD + typ = '-update' + emit(signal_root + typ, ([handle.decode('utf-8')],)) undo_count = property(lambda self:len(self.undoq)) redo_count = property(lambda self:len(self.redoq)) From 6ece4ce742ac364bcc04c988098cacfdee70a149 Mon Sep 17 00:00:00 2001 From: prculley Date: Mon, 12 Jun 2017 11:18:24 -0500 Subject: [PATCH 09/23] _errorview dialog mapped without transient parent Fixes #8128. --- gramps/gui/logger/_errorreportassistant.py | 2 +- gramps/gui/logger/_errorview.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gramps/gui/logger/_errorreportassistant.py b/gramps/gui/logger/_errorreportassistant.py index 97ccc8ebe..80a6d2a3a 100644 --- a/gramps/gui/logger/_errorreportassistant.py +++ b/gramps/gui/logger/_errorreportassistant.py @@ -119,7 +119,7 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant): if self.parent_window is not None: self._save_position(save_config=False) # the next line saves it self._save_size() - self.hide() + self.destroy() if self.ownthread: Gtk.main_quit() diff --git a/gramps/gui/logger/_errorview.py b/gramps/gui/logger/_errorview.py index ca878299d..84e07ab9c 100644 --- a/gramps/gui/logger/_errorview.py +++ b/gramps/gui/logger/_errorview.py @@ -106,8 +106,13 @@ class ErrorView(ManagedWindow): def draw_window(self): title = "%s - Gramps" % _("Error Report") self.top = Gtk.Dialog(title) + # look over the top level windows, it seems the oldest come first, so + # the most recent still visible window appears to be a good choice for + # a transient parent for win in self.top.list_toplevels(): - if win.is_active(): + if win == self.top: # not interested if this is us... + continue + if win.is_toplevel() and win.is_visible(): self.parent_window = win # for ManagedWindow if self.parent_window is None: # but it is on some screen self.parent_window = self.top.get_screen() From bdbecfa46c011dd3e6855c0c661f16abf22f9acb Mon Sep 17 00:00:00 2001 From: prculley Date: Sat, 20 May 2017 11:58:38 -0500 Subject: [PATCH 10/23] Fix media preview for preview size changes Bug #8429. --- gramps/gui/editors/editmediaref.py | 2 ++ gramps/gui/widgets/selectionwidget.py | 37 +++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/gramps/gui/editors/editmediaref.py b/gramps/gui/editors/editmediaref.py index 25f7970c4..bdaaf7ba2 100644 --- a/gramps/gui/editors/editmediaref.py +++ b/gramps/gui/editors/editmediaref.py @@ -100,6 +100,7 @@ class EditMediaRef(EditReference): tblref = self.top.get_object('table50') self.notebook_ref = self.top.get_object('notebook_ref') self.track_ref_for_deletion("notebook_ref") + self.expander = self.top.get_object('expander1') #recreate start page as GrampsTab self.notebook_ref.remove_page(0) self.reftab = RefTab(self.dbstate, self.uistate, self.track, @@ -187,6 +188,7 @@ class EditMediaRef(EditReference): self.selection.set_multiple_selection(False) self.selection.connect("region-modified", self.region_modified) self.selection.connect("region-created", self.region_modified) + self.expander.connect("activate", self.selection.expander) frame = self.top.get_object("frame9") frame.add(self.selection) self.track_ref_for_deletion("selection") diff --git a/gramps/gui/widgets/selectionwidget.py b/gramps/gui/widgets/selectionwidget.py index 9335e21e2..55c6bb08d 100644 --- a/gramps/gui/widgets/selectionwidget.py +++ b/gramps/gui/widgets/selectionwidget.py @@ -197,6 +197,7 @@ class SelectionWidget(Gtk.ScrolledWindow): self.pixbuf = None self.scaled_pixbuf = None self.scale = 1.0 + self.old_viewport_size = None Gtk.ScrolledWindow.__init__(self) self.add(self._build_gui()) @@ -227,6 +228,7 @@ class SelectionWidget(Gtk.ScrolledWindow): self.event_box.add(self.image) self.viewport = Gtk.Viewport() + self.connect("size-allocate", self._resize) self.viewport.add(self.event_box) return self.viewport @@ -296,6 +298,7 @@ class SelectionWidget(Gtk.ScrolledWindow): self.pixbuf.get_height()) viewport_size = self.viewport.get_allocation() + self.old_viewport_size = viewport_size self.scale = scale_to_fit(self.pixbuf.get_width(), self.pixbuf.get_height(), viewport_size.width, @@ -313,6 +316,32 @@ class SelectionWidget(Gtk.ScrolledWindow): self.image.set_from_icon_name('image-missing', Gtk.IconSize.DIALOG) self.image.queue_draw() + def _resize(self, *dummy): + """ + Handles size-allocate' events from Gtk. + """ + if self.pixbuf: + viewport_size = self.viewport.get_allocation() + if viewport_size.height != self.old_viewport_size.height or \ + viewport_size.width != self.old_viewport_size.width or \ + not self.image.get_pixbuf(): + self.scale = scale_to_fit(self.pixbuf.get_width(), + self.pixbuf.get_height(), + viewport_size.width, + viewport_size.height) + self._rescale() + self.old_viewport_size = viewport_size + return False + + def expander(self, *dummy): + """ Handler for expander in caller; needed because Gtk doesn't handle + verticle expansion right + """ + self.image.clear() + self.image.set_size_request(2, 2) + self.event_box.set_size_request(2, 2) + return False + # ====================================================== # coordinate transformations (public methods) # ====================================================== @@ -531,14 +560,14 @@ class SelectionWidget(Gtk.ScrolledWindow): # drawing and scaling the image # ====================================================== - def _expose_handler(self, widget, event): + def _expose_handler(self, widget, cr): """ Handles the expose-event signal of the underlying widget. """ if self.pixbuf: - self._draw_selection() + self._draw_selection(widget, cr) - def _draw_selection(self): + def _draw_selection(self, widget, cr): """ Draws the image, the selection boxes and does the necessary shading. @@ -551,8 +580,6 @@ class SelectionWidget(Gtk.ScrolledWindow): offset_x -= 1 offset_y -= 1 - cr = self.image.get_window().cairo_create() - if self.selection: x1, y1, x2, y2 = self._rect_image_to_screen(self.selection) From 007c1cb1d650a22b473386d4108d6ddd8df3302f Mon Sep 17 00:00:00 2001 From: prculley Date: Mon, 22 May 2017 17:39:52 -0500 Subject: [PATCH 11/23] Fix spin button updates in media reference editor Fix so spin button updates visible selection when it has already been clicked. Bug #8429. --- gramps/gui/editors/editmediaref.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gramps/gui/editors/editmediaref.py b/gramps/gui/editors/editmediaref.py index bdaaf7ba2..e746fa0bd 100644 --- a/gramps/gui/editors/editmediaref.py +++ b/gramps/gui/editors/editmediaref.py @@ -386,6 +386,7 @@ class EditMediaRef(EditReference): real = self.selection.proportional_to_real_rect(self.rectangle) region = Region(real[0], real[1], real[2], real[3]) self.selection.set_regions([region]) + self.selection.select(region) # update the selection box shown self.selection.refresh() def region_modified(self, widget): From f17892c411f21f8ad8283e146f30d4c3c0d69c91 Mon Sep 17 00:00:00 2001 From: prculley Date: Mon, 22 May 2017 17:41:27 -0500 Subject: [PATCH 12/23] Fix click/drag in media reference editor Fix so click/drag creates/updates selection using left mouse button. Fixes #8429. --- gramps/gui/widgets/selectionwidget.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/gramps/gui/widgets/selectionwidget.py b/gramps/gui/widgets/selectionwidget.py index 55c6bb08d..26e3e989d 100644 --- a/gramps/gui/widgets/selectionwidget.py +++ b/gramps/gui/widgets/selectionwidget.py @@ -694,7 +694,8 @@ class SelectionWidget(Gtk.ScrolledWindow): return if event.button == 1: # left button self.start_point_screen = (event.x, event.y) - if self.current is not None and self.grabber is None: + if self.current is not None and self.grabber is None and \ + self.multiple_selection: self.current = None self.selection = None self.refresh() @@ -724,18 +725,23 @@ class SelectionWidget(Gtk.ScrolledWindow): if self.start_point_screen: if self.current is not None: # a box is currently selected - if self.grabber is None: - # clicked outside of the grabbing area - self.current = None - self.selection = None - self.emit("selection-cleared") - elif self.grabber != INSIDE: + if self.grabber and self.grabber != INSIDE: # clicked on one of the grabbers dx, dy = (event.x - self.start_point_screen[0], event.y - self.start_point_screen[1]) self.grabber_to_draw = self._modify_selection(dx, dy) self.current.set_coords(*self.selection) self.emit("region-modified") + elif self.grabber is None and self.multiple_selection: + # clicked outside of the grabbing area + self.current = None + self.selection = None + self.emit("selection-cleared") + else: + # update current selection + self.current.set_coords(*self.selection) + self.region = self.current + self.emit("region-modified") else: # nothing is currently selected if (minimum_region(self.start_point_screen, @@ -774,10 +780,11 @@ class SelectionWidget(Gtk.ScrolledWindow): dx, dy = (event.x - self.start_point_screen[0], event.y - self.start_point_screen[1]) self.grabber_to_draw = self._modify_selection(dx, dy) - elif self._can_select(): + else: # making new selection start_point = self._screen_to_truncated(self.start_point_screen) self.selection = order_coordinates(start_point, end_point) + else: # motion (mouse button is not pressed) self.in_region = self._find_region(*end_point_orig) From d486052378dc3e24e808146dfd148a4c40d7a1d4 Mon Sep 17 00:00:00 2001 From: prculley Date: Mon, 29 May 2017 16:23:53 -0500 Subject: [PATCH 13/23] Gedcom import with OBJE/FORM URL on event Fixes #7593. --- data/tests/imp_MediaTest.ged | 9 ++ data/tests/imp_MediaTest.gramps | 169 ++++++++++++++++++-------------- gramps/plugins/lib/libgedcom.py | 21 +++- 3 files changed, 120 insertions(+), 79 deletions(-) diff --git a/data/tests/imp_MediaTest.ged b/data/tests/imp_MediaTest.ged index c2ce7029d..1bde200f5 100644 --- a/data/tests/imp_MediaTest.ged +++ b/data/tests/imp_MediaTest.ged @@ -43,6 +43,15 @@ 2 NOTE @N0018@ 1 OBJE @M7@ 1 OBJE @M8@ +1 OBJE +2 FORM URL +2 FILE http:\\obje.form.on_person.org +1 BIRT +2 TYPE Birth of the Tester +2 DATE 2 OCT 1864 +2 OBJE +3 FORM URL +3 FILE http:\\obje.form.on_event.org 0 @M1@ OBJE 1 FORM jpeg 1 TITL Multimedia link to linked form v5.5 blob diff --git a/data/tests/imp_MediaTest.gramps b/data/tests/imp_MediaTest.gramps index 2674b4e01..22b6f1083 100644 --- a/data/tests/imp_MediaTest.gramps +++ b/data/tests/imp_MediaTest.gramps @@ -3,17 +3,26 @@ "http://gramps-project.org/xml/1.7.1/grampsxml.dtd">
- +
+ + + Birth + + Birth of the Tester + + + - + U The Tester + @@ -25,106 +34,107 @@ - + + - + 0 - - + + - + 77, 78 discussion of multimedia link with two files 4 - - + + - + A Great Photographer - + The Testers personal files The Tester Name: Tester Publishing Operations, Inc.; Location: OSF world - + - + - - + + - - + + - + - - - + + + - + - + - - - + + + - + - - - + + + - + - + - + - + - + - + - + Media note test: Multimedia link embedded form v5.5 n OBJE {1:1} p.55 +1 FORM <MULTIMEDIA_FORMAT> {1:1} p.48 @@ -132,7 +142,7 @@ n OBJE {1:1} p.55 +1 FILE <MULTIMEDIA_FILE_REFERENCE> {1:1} p.47 +1 <<NOTE_STRUCTURE>> {0:M} p.33 - + Media note test: Multimedia link embedded form v5.5.1 This note is not in the 5.5.1 spec, but is an obvious extrapolation from 5.5. n OBJE @@ -141,23 +151,27 @@ n OBJE +3 MEDI <SOURCE_MEDIA_TYPE> {0:1} p.62 +1 TITL <DESCRIPTIVE_TITLE> {0:1} p.48 - + Multimedia embedded 2nd copy v5.5 - + + http:\\obje.form.on_event.org + + Records not imported into INDI (individual) Gramps ID I0001: Could not import test_emb_55.jpg Line 18: 1 OBJE Could not import test_emb_551.jpg Line 26: 1 OBJE -Could not import test_emb_55.jpg Line 34: 1 OBJE +Could not import test_emb_55.jpg Line 34: 1 OBJE + - + SOMETEXT - + Media note test: Multimedia link to linked form v5.5 blob n @XREF:OBJE@ OBJE {1:1} +1 FORM <MULTIMEDIA_FORMAT> {1:1} p.48 @@ -171,10 +185,10 @@ n @XREF:OBJE@ OBJE {1:1} +1 RIN <AUTOMATED_RECORD_ID> {0:1} p.38 +1 <<CHANGE_DATE>> {0:1} p.29 - + Records not imported into OBJE (multi-media object) Gramps ID M1: -Tag recognized but not supported Line 49: 1 BLOB +Tag recognized but not supported Line 58: 1 BLOB .HM.......k.1..F.jwA.Dzzzzw............A....1.........0U.66..E.8 .......A..k.a6.A.......A..k.........../6....G.......0../..U..... .w1/m........HC0..../...zzzzzzzz..5zzk..AnA..U..W6U....2rRrRrRrR @@ -182,23 +196,25 @@ Tag recognized but not supported Line 49: /Dw/.Tvz.E5zzUE9/kHz.Tw2/DzzzEEA.kE2zk5yzk2/zzs21.U2/Dw/.Tw/.Tzy /.fy/.HzzkHzzzo21Ds00.E2.UE2.U62/.k./Ds0.UE0/Do0..E8/UE2.U62.U9w /.Tx/.20.jg2/jo2..9u/.0U.6A.zk -Line ignored as not understood Line 57: 1 OBJE @M2@ -Filename omitted Line 46: 0 M1 OBJE +Line ignored as not understood Line 66: 1 OBJE @M2@ +Filename omitted Line 55: 0 M1 OBJE + - + Records not imported into OBJE (multi-media object) Gramps ID M2: -Tag recognized but not supported Line 68: 1 BLOB +Tag recognized but not supported Line 77: 1 BLOB 67890gramps doesn't do this anyway, so don't bother doing it right. -Filename omitted Line 65: 0 M2 OBJE +Filename omitted Line 74: 0 M2 OBJE + - + Media note test: Multimedia link to linked form Gramps style v5.5ish file n @XREF:OBJE@ OBJE {1:1} +1 FORM <MULTIMEDIA_FORMAT> {1:1} p.48 @@ -206,18 +222,19 @@ n @XREF:OBJE@ OBJE {1:1} +1 FILE <MULTIMEDIA_FILE_REFERENCE> {1:1} p.47 +1 <<NOTE_STRUCTURE>> {0:M} p.33 - + Records not imported into OBJE (multi-media object) Gramps ID M3: -Could not import test.jpg Line 73: 1 FILE test.jpg +Could not import test.jpg Line 82: 1 FILE test.jpg + - + SOMETEXT - + Media note test: Multimedia link to linked form v5.5.1 file n @XREF:OBJE@ OBJE {1:1} +1 FILE <MULTIMEDIA_FILE_REFN> {1:M} p.54 @@ -231,25 +248,26 @@ n @XREF:OBJE@ OBJE {1:1} +1 <<SOURCE_CITATION>> {0:M} p.39 +1 <<CHANGE_DATE>> {0:1} p.31 - + who shall remain un-named - + Records not imported into OBJE (multi-media object) Gramps ID M4: -Could not import test.jpg Line 79: 1 FILE test.jpg +Could not import test.jpg Line 88: 1 FILE test.jpg + - + A fine gentelman was he, upstanding in his community and a great believer in the testing of open source software. - + A note on the FTM media, to see how this integrates... The DATE line is bad; it doesnt follow Gedcom standard at all, and includes the time. The TEXT line comes from the FTM media description. This is the media Note. - + Multimedia link to linked form FTM style n @XREF:OBJE@ OBJE {1:1} +1 FILE <MULTIMEDIA_FILE_REFN> {1:M} p.54 @@ -258,39 +276,42 @@ n @XREF:OBJE@ OBJE {1:1} +2 TEXT text string from FTM media description sometimes populated from exif comments +1 <<NOTE_STRUCTURE>> {0:M} p.33 - + Records not imported into OBJE (multi-media object) Gramps ID M5: -Could not import test.jpg Line 94: 1 FILE test.jpg +Could not import test.jpg Line 103: 1 FILE test.jpg + - + SOMETEXT - + Multimedia link to linked form v5.5.1 with two files - + A source who shall remain un-named - + Records not imported into OBJE (multi-media object) Gramps ID M6: -Could not import test.jpg Line 102: 1 FILE test.jpg -Multiple FILE in a single OBJE ignored Line 106: 1 FILE test1.jpg -Skipped subordinate line Line 107: 2 FORM jpeg -Skipped subordinate line Line 108: 3 TYPE photo -Skipped subordinate line Line 109: 2 TITL Multimedia link to linked form v5.5.1 with two files(2) +Could not import test.jpg Line 111: 1 FILE test.jpg +Multiple FILE in a single OBJE ignored Line 115: 1 FILE test1.jpg +Skipped subordinate line Line 116: 2 FORM jpeg +Skipped subordinate line Line 117: 3 TYPE photo +Skipped subordinate line Line 118: 2 TITL Multimedia link to linked form v5.5.1 with two files(2) + - + Records not imported into OBJE (multi-media object) Gramps ID M8: -Could not import No_path_No_Title_NoForm.jpg Line 129: 1 FILE No_path_No_Title_NoForm.jpg +Could not import No_path_No_Title_NoForm.jpg Line 138: 1 FILE No_path_No_Title_NoForm.jpg + diff --git a/gramps/plugins/lib/libgedcom.py b/gramps/plugins/lib/libgedcom.py index d488f90ba..fa84585e4 100644 --- a/gramps/plugins/lib/libgedcom.py +++ b/gramps/plugins/lib/libgedcom.py @@ -133,6 +133,7 @@ from gramps.gen.db.dbconst import EVENT_KEY from gramps.gui.dialog import WarningDialog from gramps.gen.lib.const import IDENTICAL, DIFFERENT from gramps.gen.lib import (StyledText, StyledTextTag, StyledTextTagType) +from gramps.gen.lib.urlbase import UrlBase from gramps.plugins.lib.libplaceimport import PlaceImport from gramps.gen.display.place import displayer as _pd from gramps.gen.utils.grampslocale import GrampsLocale @@ -5181,11 +5182,21 @@ class GedcomParser(UpdateCallback): # The following code that detects URL is an older v5.5 usage; the # modern option is to use the EMAIL tag. if isinstance(sub_state.form, str) and sub_state.form == "url": - url = Url() - url.set_path(sub_state.filename) - url.set_description(sub_state.title) - url.set_type(UrlType.WEB_HOME) - pri_obj.add_url(url) + if isinstance(pri_obj, UrlBase): + url = Url() + url.set_path(sub_state.filename) + url.set_description(sub_state.title) + url.set_type(UrlType.WEB_HOME) + pri_obj.add_url(url) + else: # some primary objects (Event) son't have spot for URL + new_note = Note(sub_state.filename) + new_note.set_gramps_id(self.nid_map[""]) + new_note.set_handle(create_id()) + new_note.set_type(OBJ_NOTETYPE.get(type(pri_obj).__name__, + NoteType.GENERAL)) + self.dbase.commit_note(new_note, self.trans, new_note.change) + pri_obj.add_note(new_note.get_handle()) + else: # to allow import of references to URLs (especially for import from # geni.com), do not try to find the file if it is blatently a URL From 65b058ff753d9e6401b8e205520d11d2f0e29b59 Mon Sep 17 00:00:00 2001 From: SNoiraud Date: Fri, 2 Jun 2017 12:22:15 +0200 Subject: [PATCH 14/23] Dead people are shown as alive Fixes #6364. --- gramps/gen/utils/alive.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/gramps/gen/utils/alive.py b/gramps/gen/utils/alive.py index 8fcd5d0f9..99626eabc 100644 --- a/gramps/gen/utils/alive.py +++ b/gramps/gen/utils/alive.py @@ -108,11 +108,7 @@ class ProbablyAlive: if death_ref: death = self.db.get_event_from_handle(death_ref.ref) if death: - if death.get_date_object().is_valid(): - death_date = death.get_date_object() - else: # has a death event, but it is not valid: - death_date = Today() # before today - death_date.set_modifier(Date.MOD_BEFORE) + death_date = death.get_date_object() # Look for Cause Of Death, Burial or Cremation events. # These are fairly good indications that someone's not alive. @@ -144,7 +140,8 @@ class ProbablyAlive: if not birth_date and death_date: # person died more than MAX after current year - birth_date = death_date.copy_offset_ymd(year=-self.MAX_AGE_PROB_ALIVE) + if death_date.is_valid(): + birth_date = death_date.copy_offset_ymd(year=-self.MAX_AGE_PROB_ALIVE) explain = _("death date") if not death_date and birth_date: From 2f8bc559e8df356bc1ca8e9a08df12186d4e9edb Mon Sep 17 00:00:00 2001 From: John Ralls Date: Sat, 17 Jun 2017 14:50:11 -0700 Subject: [PATCH 15/23] Add a gir element, needed for scriptless bundles. --- mac/gramps.bundle | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mac/gramps.bundle b/mac/gramps.bundle index a92906f80..303775d8d 100644 --- a/mac/gramps.bundle +++ b/mac/gramps.bundle @@ -96,6 +96,10 @@ ${prefix}/lib/libgexiv2.dylib + + ${prefix}/share/gir-1.0/*.gir + + ${prefix}/share/glib-2.0/schemas + ${prefix}/lib/python3.6/*.py @@ -155,13 +159,10 @@ ${prefix}/include/python3.6m/pyconfig.h - - ${prefix}/lib/girepository-1.0/ - - + + ${prefix}/share/xml/iso-codes + ${prefix}/share/enchant/ @@ -204,7 +205,6 @@ ${prefix}/share/icons -