Add multi-person event selection
- Add _get_all_persons_for_event helper to get all persons for an event (e.g., both spouses for marriage events) - Add _format_color_for_display helper to format colors for display - Modify event click handler to select all persons involved in an event - When clicking a marriage event, both spouses are now selected together - Event lines are shown for all selected persons
This commit is contained in:
parent
cdba794cda
commit
137de07052
140
MyTimeline.py
140
MyTimeline.py
@ -2759,6 +2759,111 @@ class MyTimelineView(NavigationView):
|
||||
self.person_colors[person_handle] = color
|
||||
return color
|
||||
|
||||
def _format_color_for_display(self, color: Tuple[float, float, float, float]) -> str:
|
||||
"""
|
||||
Format color tuple for display in tooltips.
|
||||
|
||||
Args:
|
||||
color: RGBA color tuple (values 0-1).
|
||||
|
||||
Returns:
|
||||
str: Formatted color string like "RGB(255, 128, 64)".
|
||||
"""
|
||||
r, g, b = color[0], color[1], color[2] # Ignore alpha for display
|
||||
r_int = int(r * 255)
|
||||
g_int = int(g * 255)
|
||||
b_int = int(b * 255)
|
||||
return f"RGB({r_int}, {g_int}, {b_int})"
|
||||
|
||||
def _get_all_persons_for_event(self, event: 'Event', event_data: 'TimelineEvent') -> List['Person']:
|
||||
"""
|
||||
Get all persons associated with an event.
|
||||
For marriage events, returns both spouses.
|
||||
For other events, returns the associated person (if any).
|
||||
|
||||
Args:
|
||||
event: The event object.
|
||||
event_data: The TimelineEvent object containing event data.
|
||||
|
||||
Returns:
|
||||
List[Person]: List of all persons associated with the event.
|
||||
"""
|
||||
persons: List['Person'] = []
|
||||
|
||||
if not event or not self.dbstate.is_open():
|
||||
return persons
|
||||
|
||||
# Check if this is a marriage event
|
||||
try:
|
||||
actual_event_type = event.get_type()
|
||||
event_type_val = int(actual_event_type) if hasattr(actual_event_type, '__int__') else None
|
||||
marriage_type_val = int(EventType.MARRIAGE) if hasattr(EventType.MARRIAGE, '__int__') else None
|
||||
|
||||
is_marriage = False
|
||||
if event_type_val is not None and marriage_type_val is not None:
|
||||
is_marriage = (event_type_val == marriage_type_val)
|
||||
elif actual_event_type == EventType.MARRIAGE:
|
||||
is_marriage = True
|
||||
elif "Marriage" in str(actual_event_type) or "MARRIAGE" in str(actual_event_type):
|
||||
is_marriage = True
|
||||
except (ValueError, TypeError, AttributeError):
|
||||
is_marriage = False
|
||||
|
||||
# For marriage events, get both spouses from the family
|
||||
if is_marriage:
|
||||
try:
|
||||
event_handle = event.get_handle()
|
||||
# Use cached family lookup
|
||||
family = self._event_to_family_cache.get(event_handle)
|
||||
|
||||
# If not in cache, try to find the family by searching
|
||||
if not family:
|
||||
for family_handle in self.dbstate.db.get_family_handles():
|
||||
try:
|
||||
test_family = self.dbstate.db.get_family_from_handle(family_handle)
|
||||
if not test_family:
|
||||
continue
|
||||
family_event_refs = test_family.get_event_ref_list()
|
||||
for event_ref in family_event_refs:
|
||||
if event_ref.ref == event_handle:
|
||||
family = test_family
|
||||
# Cache it for next time
|
||||
self._event_to_family_cache[event_handle] = family
|
||||
break
|
||||
if family:
|
||||
break
|
||||
except (AttributeError, KeyError):
|
||||
continue
|
||||
|
||||
# If we found a family, get both spouses
|
||||
if family:
|
||||
father_handle = family.get_father_handle()
|
||||
mother_handle = family.get_mother_handle()
|
||||
|
||||
if father_handle:
|
||||
try:
|
||||
father = self.dbstate.db.get_person_from_handle(father_handle)
|
||||
if father:
|
||||
persons.append(father)
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
|
||||
if mother_handle:
|
||||
try:
|
||||
mother = self.dbstate.db.get_person_from_handle(mother_handle)
|
||||
if mother:
|
||||
persons.append(mother)
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
|
||||
# For other events, add the associated person if available
|
||||
if not persons and event_data.person:
|
||||
persons.append(event_data.person)
|
||||
|
||||
return persons
|
||||
|
||||
def _get_person_vertical_line_x(self, person_index: int) -> float:
|
||||
"""
|
||||
Calculate the X position for a person's vertical connection line.
|
||||
@ -3126,19 +3231,30 @@ class MyTimelineView(NavigationView):
|
||||
# Navigate to this event in the view
|
||||
self.uistate.set_active(event_handle, "Event")
|
||||
|
||||
# Toggle person selection (always toggle, even if event is same)
|
||||
if clicked_event_data.person:
|
||||
person_handle = clicked_event_data.person.get_handle()
|
||||
if person_handle in self.selected_person_handles:
|
||||
# Remove from selection
|
||||
self.selected_person_handles.remove(person_handle)
|
||||
# Clean up color if no longer selected
|
||||
if person_handle in self.person_colors:
|
||||
del self.person_colors[person_handle]
|
||||
# Get all persons for this event (e.g., both spouses for marriage)
|
||||
all_persons = self._get_all_persons_for_event(clicked_event_data.event, clicked_event_data)
|
||||
|
||||
# Toggle selection for all persons involved in the event
|
||||
if all_persons:
|
||||
# Check if all persons are already selected
|
||||
all_selected = all(person.get_handle() in self.selected_person_handles for person in all_persons)
|
||||
|
||||
if all_selected:
|
||||
# Remove all persons from selection
|
||||
for person in all_persons:
|
||||
person_handle = person.get_handle()
|
||||
if person_handle in self.selected_person_handles:
|
||||
self.selected_person_handles.remove(person_handle)
|
||||
# Clean up color if no longer selected
|
||||
if person_handle in self.person_colors:
|
||||
del self.person_colors[person_handle]
|
||||
else:
|
||||
# Add to selection
|
||||
self.selected_person_handles.add(person_handle)
|
||||
# Color will be assigned when drawing
|
||||
# Add all persons to selection
|
||||
for person in all_persons:
|
||||
person_handle = person.get_handle()
|
||||
if person_handle not in self.selected_person_handles:
|
||||
self.selected_person_handles.add(person_handle)
|
||||
# Color will be assigned when drawing
|
||||
|
||||
self._queue_draw()
|
||||
return False
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user