FamilySearch tools window: layout, editor context, and link button UX improvements#1
Closed
dsblank wants to merge 171 commits into
Closed
FamilySearch tools window: layout, editor context, and link button UX improvements#1dsblank wants to merge 171 commits into
dsblank wants to merge 171 commits into
Conversation
MSYS2 is deprecating the MINGW64 build environment, so we are moving to UCRT64 for the Windows AIO build. This commit includes changes already made in the aio-6.0.7 branch with regards to pinning certain package versions, as well as switching to UCRT64. db and bsddb3 packages have been removed for now. Decision pending on whether to remove this from future builds, or to find a way to build older versions of db-6.0.30 pygraphviz is failing in the build and the error needs to be resolved. gspell and enchant have been rolled back in order for spell check to work. Need to investigate why it doesn't work with the latest version of those packages. Bump minimum OS required to Windows 10. Fixes #14149.
Escape appversion and appbuild before passing to sed as replacement text. Sanitize OutFile, replacing any illegal characters with '_'.
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/
Now that we have switched to ucrt64 this is no longer required.
These issues were identified in comments by our Weblate translators.
…users configuration. Previously the user config settings were used to set db prefixes which could cause tests to fail. For example an iprefix of "I%05d" would cause the imported gramps_id to be I00044 rather than the default of I0044
…ase closure On Windows, if the db is not closed, an exception is generated when trying to remove the temporary directory "PermissionError: [WinError 32] The process cannot access the file because it is being used by another process"
On Windows, warnings such as <sys>:0: ResourceWarning: unclosed database in <sqlite3.Connection object at 0x000002b2d36131f0> are generated
bsddb is no longer supported by MSYS2 UCRT64 builds
When no build artifact is generated the upload component defaults to a warning which still marks the build as passed (green). This change marks this as a failure so the build should go red and catch someone's attention. Also updated the upload component in both AIO builds to v6.
Co-authored-by: stevenyoungs <steve@youngs.cc>
The Addon Manager on the Windows AIO installer invokes the frozen pip.exe to install each addon's Python dependencies. pip and its vendored libraries (truststore, rich, urllib3, distlib) import a number of stdlib submodules conditionally or lazily, and cx_Freeze's static scan misses them. The result was that installing any addon with pypi dependencies crashed with an ImportError before pip could do useful work. The original report surfaced via the S3 Media Uploader addon complaining that ctypes.wintypes was missing, but the class of bug applies to any stdlib submodule pulled in on a dynamic code path. Bundle the affected stdlib packages (ctypes, encodings, email, http, urllib, importlib) in full via cx_Freeze's packages list so every submodule is included, and include the single-file module getpass via the includes list. This removes the failure mode where each new addon could trip a fresh ModuleNotFoundError. Also add a smoke test to aio/build.sh that runs the frozen pip.exe after cx_Freeze finishes and aborts before NSIS packaging if pip raises ImportError, ModuleNotFoundError, or any traceback. Future coverage gaps are now caught on the build host rather than by end users running the Addon Manager. Fixes #13921.
Currently translated at 95.3% (7202 of 7557 strings) Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/pl/
Currently translated at 96.2% (7270 of 7557 strings) Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/sv/
Currently translated at 95.4% (7215 of 7557 strings) Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/es/
Currently translated at 95.4% (7210 of 7557 strings) Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/sk/
Currently translated at 96.3% (7282 of 7557 strings) Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/nl/
Currently translated at 97.3% (7360 of 7557 strings) Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/pt_PT/
Currently translated at 95.9% (7251 of 7557 strings) Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/fr/
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: Gramps/Program Translate-URL: https://hosted.weblate.org/projects/gramps-project/gramps/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The original report noted that date columns sort without grouping dates with qualifiers like about, after, before so they appear in an arbitrary order. This happens because get_sort_value() returns only the Julian Day Number with no modifier or quality information. This change adds Date.get_sort_key() which creates a sort key based on the JDN adjusted with scores for modifiers and quality It also updates date sort columns in the list view treemodels (peoplemodel, familymodel, eventmodel, mediamodel, citationbasemodel) to call get_sort_key() instead of get_sort_value(). The key is 'JDN * 12 + modifier_score * 3 + quality_score' Modifier scores: 0 - MOD_BEFORE 1 - MOD_NONE, MOD_FROM, MOD_TO, MOD_SPAN, MOD_RANGE 2 - MOD_ABOUT 3 - MOD_AFTER Quality scores: 0 - QUAL_NONE 1 - QUAL_ESTIMATED 2 - QUAL_CALCULATED For year-only after-dates the position advances to the first JDN of the following year, which is correct for all supported calendars. This ensures 'after 1823' sorts after '1823-12-31'. The max sort key for 31 Dec 9999 is 64481819 (JDN 5373484 * 12) which fits in the format string "%09d" used by treemodels. get_sort_value() is unchanged and continues to be used for date arithmetic, calendar conversion and span calculations throughout the rest of the codebase. Fixes #7761.
Restores support for a user-supplied tile URL in the embedded geography view. The custom URL is entered in Geography preferences using #Z/#X/#Y as coordinate placeholders. Example providers include MapTiler NLS historical Ordnance Survey maps (uk-osgb1888, uk-osgb63k1885, etc.). OsmGpsMap requires a non-null map-source enum value to honour a custom repo_uri; using map_source=0 (NULL) causes it to render gray tiles and ignore the URL entirely. Fix this by passing OPENSTREETMAP_RENDERER, whose built-in URI is NULL (service defunct), so OsmGpsMap keeps the supplied repo_uri and fetches tiles from it. Also fixes the image-format lookup for custom URLs, debounces the url entry field so it only fires on Enter or focus-out rather than on every keystroke, and widens the URL input field to span the full grid width.
…'t seem like its frozen for Persons with lots of sources on FS
…es correctly for compare
… FS integration (hide it)
… will prompt you to bulk import.
…the compare window
…es panel & goes straight to the integrations section if/when the gramps foundation key isn't present
Fix remaining seven issues from dsblank's review: - Issue 4: Log and surface per-row exceptions in _apply_selected_merge_rows rather than silently swallowing them; adjusted success/failure dialogs to report how many rows could not be applied. - Issue 5: Restore _SESSION-first priority in get_session() so a cached authenticated session is not replaced by a freshly-constructed but not-yet-authenticated one. - Issue 6: Replace sequential add_persons() with a ThreadPoolExecutor that fetches HTTP responses concurrently, then deserializes sequentially to avoid shared-state races; replaces removed asyncio parallelism. - Issue 7: Do not cache None in _FS_PHOTO_CACHE on portrait fetch failure so transient errors (HTTP 503, timeout) do not permanently suppress photos for the process lifetime. - Issue 8: Replace all print() calls in cache.py with LOG.warning() via a module-level logger, making errors visible from desktop launchers. - Issue 9: Guard both the familysearchgroup visibility calls and update_menu() under a single hasattr(self, "uimanager") check to prevent crashes and silent skips before the UI manager is ready. - Issue 10: Move the blocking HTTP search in _empty_tree_start_person_dialog onto a daemon thread with GLib.idle_add callback, eliminating the Gtk.main_iteration() flush loop that could fire window-manager close events and crash with GObject-already-destroyed errors. Also address emyoulation's CSS segregation suggestion by splitting all FamilySearch-specific CSS rules out of gramps.css into a new familysearch.css file that is loaded alongside gramps.css. All three CSS loading sites (viewmanager, compare window, tools window) updated. Additionally convert all FS source files from CRLF to LF line endings to match the rest of the Gramps codebase. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each test module covers a specific issue from PR gramps-project#2333: comparators_test.py – issues 1 & 2: compare_spouses argument order and ChildAndParentsRelationship field access fixes. importer_test.py – issue 3: add_child/add_family duplicate-family guard. tree_test.py – issue 6: _fetch_raw and ThreadPoolExecutor behaviour. cache_test.py – issue 8: print() replaced by LOG.warning(). manager_test.py – issue 5: _SESSION vs get_active_session() priority. compare_gtk_test.py – issues 4 & 7: _apply_selected_merge_rows exception tracking and _FS_PHOTO_CACHE no-None fix. viewmanager_fs_test.py – issue 9: uimanager guard in _update_familysearch_ui. GUI tests use sys.modules stubs (gi.repository mocks with GLib integer version attributes) so they run headless without a display server. viewmanager_fs_test avoids the GTK-heavy module chain entirely by loading _update_familysearch_ui via AST extraction from viewmanager.py. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. comparators.py: replace garbled Python import statement used as a
display separator ("from deserialize.xml import parse_xml") with
" @ ".join(filter(None, [desc, place])) in all 6 affected sites.
2. manager.py: clear _SESSION when FamilySearch is disabled so that
re-enabling constructs a fresh session from current config rather
than returning a stale cached reference.
3. compare_gtk.py: guard db.commit_person() so it only fires when at
least one merge row succeeded, preventing a no-op write transaction
from appearing in the undo history when all rows fail.
4. viewmanager.py: reset _fs_empty_tree_import_prompted in
post_close_db() so the empty-tree import offer can appear again
when the user opens a second empty tree in the same session.
5. manager.py / viewmanager.py: extract auth-provider resolution into
needs_access_code() in manager.py and call it from viewmanager.py,
eliminating the duplicated ~30-line block that could silently drift.
6. comparators.py: introduce CompareRow(NamedTuple) with 13 named
fields and update all 22 tuple construction sites to use keyword
arguments; update _merge_row_from_compare to use named attribute
access instead of positional data[n] indexing with padding.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add _last_modified and _etag typed attributes to the deserializer Person class so mypy accepts the transport metadata assignments in tree.py. Add an explicit union type annotation for the outcome variable in actions.py to allow it to hold either a result list or an Exception. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move LOG initializer after all imports in tree.py. - Replace six print() calls in deserializer.py with logger.debug(). - Import FS_ATTR_CANON from actions.py in importer.py instead of using the hardcoded string "_FSFTID". - Replace bare except/pass in importer.add_person() with LOG.debug() so scan failures are visible at debug level. - Default familysearch.enable to False so the integration is opt-in for users who have never configured FamilySearch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Restore child handles in Family.get_referenced_handles() — they were accidentally dropped, breaking callman.py UI tracking for child changes. - Replace time.mktime(parsedate(…)) with calendar.timegm(parsedate(…)) in tree.py and cache.py so that HTTP Last-Modified timestamps are treated as UTC rather than local time; also guard against parsedate() returning None on a malformed header. - Fix _datemod → _datmod typo in gui/fs/compare/window.py so the early-return optimisation in compare_fs_to_gramps actually fires. - Stop add_persons() from overwriting already-present _etag/_last_modified values in Tree._persons when iterating the global deserialize.Person.index. - In _find_best_fs_fact_match, prefer a fact that has a date over a dateless one as the type-only fallback when the Gramps event has a date. - Fix the couple loop in compare_spouse_notes / compare_spouses to skip couples where neither member is fsid instead of emitting spurious rows. - Log (not swallow) network and auth exceptions from concurrent FS fetches in Tree.add_persons(). - Fix tags.py attribute lookup: replace the ad-hoc alias set with the canonical FS_ATTR_CANON/FS_ATTR_OLD/FS_ATTR_HUMAN constants from actions.py, and fix get_string() → str() which was silently catching AttributeError and skipping every attribute. - Add regression tests for all nine fixes (75 tests, all passing). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Importing tree at module level in actions.py caused a cycle: actions -> tree -> fs_import/importer -> actions. Deferred the import of tree into _bind_global_session, the only function that uses it, to break the cycle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
87ca5a4 to
e1d2754
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three improvements to the FamilySearch Tools window, built on the existing
pr-2147-fs-loginintegration.1. Reorganize FamilySearch tools window layout
Before:
After:
Moves the FS connection status widget from the top of the window to a
bottom status bar, giving the active person name full-width prominence.
Places the Link FamilySearch ID button directly below the person name,
above the notebook tabs. Replaces the Person actions FlowBox with three
explicit rows: Compare on its own row, Sync from/Sync to on one row, and
Export to FamilySearch on its own row. This gives each action a clear
visual hierarchy and avoids buttons wrapping unpredictably at narrow widths.
2. Clear editor context when Edit Person window is closed
The tools window previously kept the person name and all action buttons
active after the Edit Person dialog was closed, because the window-destroy
signal was never handled. This change connects to
destroyon the editorwindow and clears
_LAST_EDITORwhen the tracked editor closes, triggeringan immediate UI refresh so the name resets to "(none)" and all
person-specific buttons are disabled.
3. Change Link button label and sensitivity based on FSFTID state
When an Edit Person window is open:
_FSFTIDattribute, the button reads"Edit FamilySearch ID" and all other action buttons remain enabled.
_FSFTIDattribute, the button reads"Add FamilySearch ID" and all other action buttons are disabled
until an ID is linked.
The FSFTID check reads from the live in-memory editor object (not the
database copy), so a freshly typed ID is detected immediately — even before
the person is saved.
Test plan
_FSFTIDattribute → Link button shows "Add FamilySearch ID", all other action buttons are disabled_FSFTID→ Link button shows "Edit FamilySearch ID", all other buttons enabled🤖 Generated with Claude Code