1# 2# Gramps - a GTK+/GNOME based genealogy program 3# 4# Copyright (C) 2000-2007 Donald N. Allingham 5# Copyright (C) 2010 Nick Hall 6# Copyright (C) 2011 Tim G L Lyons 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; either version 2 of the License, or 11# (at your option) any later version. 12# 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this program; if not, write to the Free Software 20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21# 22 23""" 24Base class for the Gramps databases. All database interfaces should inherit 25from this class. 26""" 27 28#------------------------------------------------------------------------- 29# 30# Python libraries 31# 32#------------------------------------------------------------------------- 33import re 34import time 35from operator import itemgetter 36import logging 37 38#------------------------------------------------------------------------- 39# 40# Gramps libraries 41# 42#------------------------------------------------------------------------- 43from ..db.dbconst import DBLOGNAME 44from ..const import GRAMPS_LOCALE as glocale 45_ = glocale.translation.gettext 46from ..lib.childreftype import ChildRefType 47from ..lib.childref import ChildRef 48from .txn import DbTxn 49from .exceptions import DbTransactionCancel, DbException 50 51_LOG = logging.getLogger(DBLOGNAME) 52 53#------------------------------------------------------------------------- 54# 55# Gramps libraries 56# 57#------------------------------------------------------------------------- 58 59 60class DbReadBase: 61 """ 62 Gramps database object. This object is a base class for all 63 database interfaces. All methods raise NotImplementedError 64 and must be implemented in the derived class as required. 65 """ 66 67 def __init__(self): 68 """ 69 Create a new DbReadBase instance. 70 71 A new DbReadBase class should never be directly created. Only classes 72 derived from this class should be created. 73 """ 74 self.basedb = self 75 self.__feature = {} # {"feature": VALUE, ...} 76 77 def get_feature(self, feature): 78 """ 79 Databases can implement certain features or not. The default is 80 None, unless otherwise explicitly stated. 81 """ 82 return self.__feature.get(feature, None) # can also be explicitly None 83 84 def set_feature(self, feature, value): 85 """ 86 Databases can implement certain features. 87 """ 88 self.__feature[feature] = value 89 90 def close(self): 91 """ 92 Close the specified database. 93 """ 94 raise NotImplementedError 95 96 def db_has_bm_changes(self): 97 """ 98 Return whethere there were bookmark changes during the session. 99 """ 100 raise NotImplementedError 101 102 def find_backlink_handles(self, handle, include_classes=None): 103 """ 104 Find all objects that hold a reference to the object handle. 105 106 Returns an iterator over a list of (class_name, handle) tuples. 107 108 :param handle: handle of the object to search for. 109 :type handle: str database handle 110 :param include_classes: list of class names to include in the results. 111 Default is None which includes all classes. 112 :type include_classes: list of class names 113 114 This default implementation does a sequential scan through all 115 the primary object databases and is very slow. Backends can 116 override this method to provide much faster implementations that 117 make use of additional capabilities of the backend. 118 119 Note that this is a generator function, it returns a iterator for 120 use in loops. If you want a list of the results use:: 121 122 result_list = list(find_backlink_handles(handle)) 123 """ 124 raise NotImplementedError 125 126 def find_initial_person(self): 127 """ 128 Returns first person in the database 129 """ 130 raise NotImplementedError 131 132 def get_child_reference_types(self): 133 """ 134 Return a list of all child reference types associated with Family 135 instances in the database. 136 """ 137 raise NotImplementedError 138 139 def get_default_handle(self): 140 """ 141 Return the default Person of the database. 142 """ 143 raise NotImplementedError 144 145 def get_default_person(self): 146 """ 147 Return the default Person of the database. 148 """ 149 raise NotImplementedError 150 151 def find_next_citation_gramps_id(self): 152 """ 153 Return the next available Gramps ID for a Event object based off the 154 event ID prefix. 155 """ 156 raise NotImplementedError 157 158 def find_next_event_gramps_id(self): 159 """ 160 Return the next available Gramps ID for a Event object based off the 161 event ID prefix. 162 """ 163 raise NotImplementedError 164 165 def find_next_family_gramps_id(self): 166 """ 167 Return the next available Gramps ID for a Family object based off the 168 family ID prefix. 169 """ 170 raise NotImplementedError 171 172 def find_next_media_gramps_id(self): 173 """ 174 Return the next available Gramps ID for a Media object based 175 off the media object ID prefix. 176 """ 177 raise NotImplementedError 178 179 def find_next_note_gramps_id(self): 180 """ 181 Return the next available Gramps ID for a Note object based off the 182 note ID prefix. 183 """ 184 raise NotImplementedError 185 186 def find_next_person_gramps_id(self): 187 """ 188 Return the next available Gramps ID for a Person object based off the 189 person ID prefix. 190 """ 191 raise NotImplementedError 192 193 def find_next_place_gramps_id(self): 194 """ 195 Return the next available Gramps ID for a Place object based off the 196 place ID prefix. 197 """ 198 raise NotImplementedError 199 200 def find_next_repository_gramps_id(self): 201 """ 202 Return the next available Gramps ID for a Repository object based 203 off the repository ID prefix. 204 """ 205 raise NotImplementedError 206 207 def find_next_source_gramps_id(self): 208 """ 209 Return the next available Gramps ID for a Source object based off the 210 source ID prefix. 211 """ 212 raise NotImplementedError 213 214 def get_bookmarks(self): 215 """ 216 Return the list of Person handles in the bookmarks. 217 """ 218 raise NotImplementedError 219 220 def get_citation_bookmarks(self): 221 """ 222 Return the list of Citation handles in the bookmarks. 223 """ 224 raise NotImplementedError 225 226 def get_event_bookmarks(self): 227 """ 228 Return the list of Event handles in the bookmarks. 229 """ 230 raise NotImplementedError 231 232 def get_family_bookmarks(self): 233 """ 234 Return the list of Family handles in the bookmarks. 235 """ 236 raise NotImplementedError 237 238 def get_media_bookmarks(self): 239 """ 240 Return the list of Media handles in the bookmarks. 241 """ 242 raise NotImplementedError 243 244 def get_note_bookmarks(self): 245 """ 246 Return the list of Note handles in the bookmarks. 247 """ 248 raise NotImplementedError 249 250 def get_place_bookmarks(self): 251 """ 252 Return the list of Place handles in the bookmarks. 253 """ 254 raise NotImplementedError 255 256 def get_repo_bookmarks(self): 257 """ 258 Return the list of Repository handles in the bookmarks. 259 """ 260 raise NotImplementedError 261 262 def get_source_bookmarks(self): 263 """ 264 Return the list of Source handles in the bookmarks. 265 """ 266 raise NotImplementedError 267 268 def get_citation_cursor(self): 269 """ 270 Return a reference to a cursor over Citation objects. Example use:: 271 272 with get_citation_cursor() as cursor: 273 for handle, citation in cursor: 274 # process citation object pointed to by the handle 275 """ 276 raise NotImplementedError 277 278 def get_event_cursor(self): 279 """ 280 Return a reference to a cursor over Family objects. Example use:: 281 282 with get_event_cursor() as cursor: 283 for handle, event in cursor: 284 # process event object pointed to by the handle 285 """ 286 raise NotImplementedError 287 288 def get_family_cursor(self): 289 """ 290 Return a reference to a cursor over Family objects. Example use:: 291 292 with get_family_cursor() as cursor: 293 for handle, family in cursor: 294 # process family object pointed to by the handle 295 """ 296 raise NotImplementedError 297 298 def get_media_cursor(self): 299 """ 300 Return a reference to a cursor over Media objects. Example use:: 301 302 with get_media_cursor() as cursor: 303 for handle, media in cursor: 304 # process media object pointed to by the handle 305 """ 306 raise NotImplementedError 307 308 def get_note_cursor(self): 309 """ 310 Return a reference to a cursor over Note objects. Example use:: 311 312 with get_note_cursor() as cursor: 313 for handle, note in cursor: 314 # process note object pointed to by the handle 315 """ 316 raise NotImplementedError 317 318 def get_person_cursor(self): 319 """ 320 Return a reference to a cursor over Person objects. Example use:: 321 322 with get_person_cursor() as cursor: 323 for handle, person in cursor: 324 # process person object pointed to by the handle 325 """ 326 raise NotImplementedError 327 328 def get_place_cursor(self): 329 """ 330 Return a reference to a cursor over Place objects. Example use:: 331 332 with get_place_cursor() as cursor: 333 for handle, place in cursor: 334 # process place object pointed to by the handle 335 """ 336 raise NotImplementedError 337 338 def get_place_tree_cursor(self): 339 """ 340 Return a reference to a cursor that iterates over Place objects in the 341 order they appear in the place hierarchy. Example use:: 342 343 with get_place_tree_cursor() as cursor: 344 for handle, place in cursor: 345 # process place object pointed to by the handle 346 """ 347 raise NotImplementedError 348 349 def get_repository_cursor(self): 350 """ 351 Return a reference to a cursor over Repository objects. Example use:: 352 353 with get_repository_cursor() as cursor: 354 for handle, repository in cursor: 355 # process repository object pointed to by the handle 356 """ 357 raise NotImplementedError 358 359 def get_source_cursor(self): 360 """ 361 Return a reference to a cursor over Source objects. Example use:: 362 363 with get_source_cursor() as cursor: 364 for handle, source in cursor: 365 # process source object pointed to by the handle 366 """ 367 raise NotImplementedError 368 369 def get_tag_cursor(self): 370 """ 371 Return a reference to a cursor over Tag objects. Example use:: 372 373 with get_tag_cursor() as cursor: 374 for handle, tag in cursor: 375 # process tag object pointed to by the handle 376 """ 377 raise NotImplementedError 378 379 def get_citation_from_gramps_id(self, val): 380 """ 381 Find a Citation in the database from the passed Gramps ID. 382 383 :param val: gramps_id of the object to search for. 384 :type val: str or bytes 385 386 If no such Citation exists, None is returned. 387 """ 388 raise NotImplementedError 389 390 def get_event_from_gramps_id(self, val): 391 """ 392 Find an Event in the database from the passed Gramps ID. 393 394 :param val: gramps_id of the object to search for. 395 :type val: str or bytes 396 397 If no such Event exists, None is returned. 398 """ 399 raise NotImplementedError 400 401 def get_family_from_gramps_id(self, val): 402 """ 403 Find a Family in the database from the passed Gramps ID. 404 405 :param val: gramps_id of the object to search for. 406 :type val: str or bytes 407 408 If no such Family exists, None is returned. 409 """ 410 raise NotImplementedError 411 412 def get_media_from_gramps_id(self, val): 413 """ 414 Find a Media in the database from the passed Gramps ID. 415 416 :param val: gramps_id of the object to search for. 417 :type val: str or bytes 418 419 If no such Media exists, None is returned. 420 """ 421 raise NotImplementedError 422 423 def get_note_from_gramps_id(self, val): 424 """ 425 Find a Note in the database from the passed Gramps ID. 426 427 :param val: gramps_id of the object to search for. 428 :type val: str or bytes 429 430 If no such Note exists, None is returned. 431 """ 432 raise NotImplementedError 433 434 def get_person_from_gramps_id(self, val): 435 """ 436 Find a Person in the database from the passed Gramps ID. 437 438 :param val: gramps_id of the object to search for. 439 :type val: str or bytes 440 441 If no such Person exists, None is returned. 442 """ 443 raise NotImplementedError 444 445 def get_place_from_gramps_id(self, val): 446 """ 447 Find a Place in the database from the passed Gramps ID. 448 449 :param val: gramps_id of the object to search for. 450 :type val: str or bytes 451 452 If no such Place exists, None is returned. 453 """ 454 raise NotImplementedError 455 456 def get_repository_from_gramps_id(self, val): 457 """ 458 Find a Repository in the database from the passed Gramps ID. 459 460 :param val: gramps_id of the object to search for. 461 :type val: str or bytes 462 463 If no such Repository exists, None is returned. 464 """ 465 raise NotImplementedError 466 467 def get_source_from_gramps_id(self, val): 468 """ 469 Find a Source in the database from the passed Gramps ID. 470 471 :param val: gramps_id of the object to search for. 472 :type val: str or bytes 473 474 If no such Source exists, None is returned. 475 """ 476 raise NotImplementedError 477 478 def get_citation_from_handle(self, handle): 479 """ 480 Return a Citation in the database from the passed handle. 481 482 :param handle: handle of the object to search for. 483 :type handle: str or bytes 484 485 If no such Citation exists, a HandleError is raised. 486 Note: if used through a proxy (Filter for reports etc.) a 'None' is 487 returned in cases where the Citation is filtered out. 488 """ 489 raise NotImplementedError 490 491 def get_event_from_handle(self, handle): 492 """ 493 Return an Event in the database from the passed handle. 494 495 :param handle: handle of the object to search for. 496 :type handle: str or bytes 497 498 If no such Event exists, a HandleError is raised. 499 Note: if used through a proxy (Filter for reports etc.) a 'None' is 500 returned in cases where the Event is filtered out. 501 """ 502 raise NotImplementedError 503 504 def get_family_from_handle(self, handle): 505 """ 506 Return a Family in the database from the passed handle. 507 508 :param handle: handle of the object to search for. 509 :type handle: str or bytes 510 511 If no such Family exists, a HandleError is raised. 512 Note: if used through a proxy (Filter for reports etc.) a 'None' is 513 returned in cases where the Family is filtered out. 514 """ 515 raise NotImplementedError 516 517 def get_media_from_handle(self, handle): 518 """ 519 Return a Media in the database from the passed handle. 520 521 :param handle: handle of the object to search for. 522 :type handle: str or bytes 523 524 If no such Object exists, a HandleError is raised. 525 Note: if used through a proxy (Filter for reports etc.) a 'None' is 526 returned in cases where the Media is filtered out. 527 """ 528 raise NotImplementedError 529 530 def get_note_from_handle(self, handle): 531 """ 532 Return a Note in the database from the passed handle. 533 534 :param handle: handle of the object to search for. 535 :type handle: str or bytes 536 537 If no such Note exists, a HandleError is raised. 538 Note: if used through a proxy (Filter for reports etc.) a 'None' is 539 returned in cases where the Note is filtered out. 540 """ 541 raise NotImplementedError 542 543 def get_person_from_handle(self, handle): 544 """ 545 Return a Person in the database from the passed handle. 546 547 :param handle: handle of the object to search for. 548 :type handle: str or bytes 549 550 If no such Person exists, a HandleError is raised. 551 Note: if used through a proxy (Filter for reports etc.) a 'None' is 552 returned in cases where the Person is filtered out. 553 """ 554 raise NotImplementedError 555 556 def get_place_from_handle(self, handle): 557 """ 558 Return a Place in the database from the passed handle. 559 560 :param handle: handle of the object to search for. 561 :type handle: str or bytes 562 563 If no such Place exists, a HandleError is raised. 564 Note: if used through a proxy (Filter for reports etc.) a 'None' is 565 returned in cases where the Place is filtered out. 566 """ 567 raise NotImplementedError 568 569 def get_repository_from_handle(self, handle): 570 """ 571 Return a Repository in the database from the passed handle. 572 573 :param handle: handle of the object to search for. 574 :type handle: str or bytes 575 576 If no such Repository exists, a HandleError is raised. 577 Note: if used through a proxy (Filter for reports etc.) a 'None' is 578 returned in cases where the Repository is filtered out. 579 """ 580 raise NotImplementedError 581 582 def get_source_from_handle(self, handle): 583 """ 584 Return a Source in the database from the passed handle. 585 586 :param handle: handle of the object to search for. 587 :type handle: str or bytes 588 589 If no such Source exists, a HandleError is raised. 590 Note: if used through a proxy (Filter for reports etc.) a 'None' is 591 returned in cases where the Source is filtered out. 592 """ 593 raise NotImplementedError 594 595 def get_tag_from_handle(self, handle): 596 """ 597 Return a Tag in the database from the passed handle. 598 599 :param handle: handle of the object to search for. 600 :type handle: str or bytes 601 602 If no such Tag exists, a HandleError is raised. 603 Note: if used through a proxy (Filter for reports etc.) a 'None' is 604 returned in cases where the Tag is filtered out. 605 """ 606 raise NotImplementedError 607 608 def get_citation_handles(self, sort_handles=False, locale=glocale): 609 """ 610 Return a list of database handles, one handle for each Citation in 611 the database. 612 613 :param sort_handles: If True, the list is sorted by Citation title. 614 :type sort_handles: bool 615 :param locale: The locale to use for collation. 616 :type locale: A GrampsLocale object. 617 """ 618 raise NotImplementedError 619 620 def get_event_handles(self): 621 """ 622 Return a list of database handles, one handle for each Event in the 623 database. 624 625 .. warning:: For speed the keys are directly returned, so handles are 626 bytes type 627 """ 628 raise NotImplementedError 629 630 def get_family_handles(self, sort_handles=False, locale=glocale): 631 """ 632 Return a list of database handles, one handle for each Family in 633 the database. 634 635 :param sort_handles: If True, the list is sorted by surnames. 636 :type sort_handles: bool 637 :param locale: The locale to use for collation. 638 :type locale: A GrampsLocale object. 639 640 .. warning:: For speed the keys are directly returned, so handles are 641 bytes type 642 """ 643 raise NotImplementedError 644 645 def get_media_handles(self, sort_handles=False, locale=glocale): 646 """ 647 Return a list of database handles, one handle for each Media in 648 the database. 649 650 :param sort_handles: If True, the list is sorted by title. 651 :type sort_handles: bool 652 :param locale: The locale to use for collation. 653 :type locale: A GrampsLocale object. 654 655 .. warning:: For speed the keys are directly returned, so handles are 656 bytes type 657 """ 658 raise NotImplementedError 659 660 def get_note_handles(self): 661 """ 662 Return a list of database handles, one handle for each Note in the 663 database. 664 665 .. warning:: For speed the keys are directly returned, so handles are 666 bytes type 667 """ 668 raise NotImplementedError 669 670 def get_person_handles(self, sort_handles=False, locale=glocale): 671 """ 672 Return a list of database handles, one handle for each Person in 673 the database. 674 675 :param sort_handles: If True, the list is sorted by surnames. 676 :type sort_handles: bool 677 :param locale: The locale to use for collation. 678 :type locale: A GrampsLocale object. 679 680 .. warning:: For speed the keys are directly returned, so handles are 681 bytes type 682 """ 683 raise NotImplementedError 684 685 def get_place_handles(self, sort_handles=False, locale=glocale): 686 """ 687 Return a list of database handles, one handle for each Place in 688 the database. 689 690 :param sort_handles: If True, the list is sorted by Place title. 691 :type sort_handles: bool 692 :param locale: The locale to use for collation. 693 :type locale: A GrampsLocale object. 694 695 .. warning:: For speed the keys are directly returned, so handles are 696 bytes type 697 """ 698 raise NotImplementedError 699 700 def get_repository_handles(self): 701 """ 702 Return a list of database handles, one handle for each Repository in 703 the database. 704 705 .. warning:: For speed the keys are directly returned, so handles are 706 bytes type 707 """ 708 raise NotImplementedError 709 710 def get_source_handles(self, sort_handles=False, locale=glocale): 711 """ 712 Return a list of database handles, one handle for each Source in 713 the database. 714 715 :param sort_handles: If True, the list is sorted by Source title. 716 :type sort_handles: bool 717 :param locale: The locale to use for collation. 718 :type locale: A GrampsLocale object. 719 720 .. warning:: For speed the keys are directly returned, so handles are 721 bytes type 722 """ 723 raise NotImplementedError 724 725 def get_tag_handles(self, sort_handles=False, locale=glocale): 726 """ 727 Return a list of database handles, one handle for each Tag in 728 the database. 729 730 :param sort_handles: If True, the list is sorted by Tag name. 731 :type sort_handles: bool 732 :param locale: The locale to use for collation. 733 :type locale: A GrampsLocale object. 734 735 .. warning:: For speed the keys are directly returned, so handles are 736 bytes type 737 """ 738 raise NotImplementedError 739 740 def get_event_roles(self): 741 """ 742 Return a list of all custom event role names associated with Event 743 instances in the database. 744 """ 745 raise NotImplementedError 746 747 def get_event_attribute_types(self): 748 """ 749 Return a list of all Attribute types assocated with Event instances 750 in the database. 751 """ 752 raise NotImplementedError 753 754 def get_family_attribute_types(self): 755 """ 756 Return a list of all Attribute types associated with Family instances 757 in the database. 758 """ 759 raise NotImplementedError 760 761 def get_media_attribute_types(self): 762 """ 763 Return a list of all Attribute types associated with Media and MediaRef 764 instances in the database. 765 """ 766 raise NotImplementedError 767 768 def get_person_attribute_types(self): 769 """ 770 Return a list of all Attribute types associated with Person instances 771 in the database. 772 """ 773 raise NotImplementedError 774 775 def get_source_attribute_types(self): 776 """ 777 Return a list of all Attribute types associated with Source/Citation 778 instances in the database. 779 """ 780 raise NotImplementedError 781 782 def get_event_types(self): 783 """ 784 Return a list of all event types in the database. 785 """ 786 raise NotImplementedError 787 788 def get_family_event_types(self): 789 """ 790 Deprecated: Use get_event_types 791 """ 792 raise NotImplementedError 793 794 def get_family_relation_types(self): 795 """ 796 Return a list of all relationship types associated with Family 797 instances in the database. 798 """ 799 raise NotImplementedError 800 801 def get_name_types(self): 802 """ 803 Return a list of all custom names types associated with Person 804 instances in the database. 805 """ 806 raise NotImplementedError 807 808 def get_note_types(self): 809 """ 810 Return a list of all custom note types associated with Note instances 811 in the database. 812 """ 813 raise NotImplementedError 814 815 def get_origin_types(self): 816 """ 817 Return a list of all custom origin types associated with Person/Surname 818 instances in the database. 819 """ 820 raise NotImplementedError 821 822 def get_place_types(self): 823 """ 824 Return a list of all custom place types assocated with Place instances 825 in the database. 826 """ 827 raise NotImplementedError 828 829 def get_repository_types(self): 830 """ 831 Return a list of all custom repository types associated with Repository 832 instances in the database. 833 """ 834 raise NotImplementedError 835 836 def get_source_media_types(self): 837 """ 838 Return a list of all custom source media types associated with Source 839 instances in the database. 840 """ 841 raise NotImplementedError 842 843 def get_url_types(self): 844 """ 845 Return a list of all custom names types associated with Url instances 846 in the database. 847 """ 848 raise NotImplementedError 849 850 def get_mediapath(self): 851 """ 852 Return the default media path of the database. 853 """ 854 raise NotImplementedError 855 856 def get_name_group_keys(self): 857 """ 858 Return the defined names that have been assigned to a default grouping. 859 """ 860 raise NotImplementedError 861 862 def get_name_group_mapping(self, surname): 863 """ 864 Return the default grouping name for a surname. 865 """ 866 raise NotImplementedError 867 868 def get_number_of_citations(self): 869 """ 870 Return the number of citations currently in the database. 871 """ 872 raise NotImplementedError 873 874 def get_number_of_events(self): 875 """ 876 Return the number of events currently in the database. 877 """ 878 raise NotImplementedError 879 880 def get_number_of_families(self): 881 """ 882 Return the number of families currently in the database. 883 """ 884 raise NotImplementedError 885 886 def get_number_of_media(self): 887 """ 888 Return the number of media objects currently in the database. 889 """ 890 raise NotImplementedError 891 892 def get_number_of_notes(self): 893 """ 894 Return the number of notes currently in the database. 895 """ 896 raise NotImplementedError 897 898 def get_number_of_people(self): 899 """ 900 Return the number of people currently in the database. 901 """ 902 raise NotImplementedError 903 904 def get_number_of_places(self): 905 """ 906 Return the number of places currently in the database. 907 """ 908 raise NotImplementedError 909 910 def get_number_of_repositories(self): 911 """ 912 Return the number of source repositories currently in the database. 913 """ 914 raise NotImplementedError 915 916 def get_number_of_sources(self): 917 """ 918 Return the number of sources currently in the database. 919 """ 920 raise NotImplementedError 921 922 def get_number_of_tags(self): 923 """ 924 Return the number of tags currently in the database. 925 """ 926 raise NotImplementedError 927 928 def get_person_event_types(self): 929 """ 930 Deprecated: Use get_event_types 931 """ 932 raise NotImplementedError 933 934 def get_raw_citation_data(self, handle): 935 """ 936 Return raw (serialized and pickled) Citation object from handle 937 """ 938 raise NotImplementedError 939 940 def get_raw_event_data(self, handle): 941 """ 942 Return raw (serialized and pickled) Event object from handle 943 """ 944 raise NotImplementedError 945 946 def get_raw_family_data(self, handle): 947 """ 948 Return raw (serialized and pickled) Family object from handle 949 """ 950 raise NotImplementedError 951 952 def get_raw_media_data(self, handle): 953 """ 954 Return raw (serialized and pickled) Family object from handle 955 """ 956 raise NotImplementedError 957 958 def get_raw_note_data(self, handle): 959 """ 960 Return raw (serialized and pickled) Note object from handle 961 """ 962 raise NotImplementedError 963 964 def get_raw_person_data(self, handle): 965 """ 966 Return raw (serialized and pickled) Person object from handle 967 """ 968 raise NotImplementedError 969 970 def get_raw_place_data(self, handle): 971 """ 972 Return raw (serialized and pickled) Place object from handle 973 """ 974 raise NotImplementedError 975 976 def get_raw_repository_data(self, handle): 977 """ 978 Return raw (serialized and pickled) Repository object from handle 979 """ 980 raise NotImplementedError 981 982 def get_raw_source_data(self, handle): 983 """ 984 Return raw (serialized and pickled) Source object from handle 985 """ 986 raise NotImplementedError 987 988 def get_raw_tag_data(self, handle): 989 """ 990 Return raw (serialized and pickled) Tag object from handle 991 """ 992 raise NotImplementedError 993 994 def get_researcher(self): 995 """ 996 Return the Researcher instance, providing information about the owner 997 of the database. 998 """ 999 raise NotImplementedError 1000 1001 def get_save_path(self): 1002 """ 1003 Return the save path of the file, or "" if one does not exist. 1004 """ 1005 raise NotImplementedError 1006 1007 def get_surname_list(self): 1008 """ 1009 Return the list of locale-sorted surnames contained in the database. 1010 """ 1011 raise NotImplementedError 1012 1013 def get_tag_from_name(self, val): 1014 """ 1015 Find a Tag in the database from the passed Tag name. 1016 1017 If no such Tag exists, None is returned. 1018 """ 1019 raise NotImplementedError 1020 1021 def has_citation_gramps_id(self, gramps_id): 1022 """ 1023 Return True if the Gramps ID exists in the Citation table. 1024 """ 1025 raise NotImplementedError 1026 1027 def has_event_gramps_id(self, gramps_id): 1028 """ 1029 Return True if the Gramps ID exists in the Event table. 1030 """ 1031 raise NotImplementedError 1032 1033 def has_family_gramps_id(self, gramps_id): 1034 """ 1035 Return True if the Gramps ID exists in the Family table. 1036 """ 1037 raise NotImplementedError 1038 1039 def has_media_gramps_id(self, gramps_id): 1040 """ 1041 Return True if the Gramps ID exists in the Media table. 1042 """ 1043 raise NotImplementedError 1044 1045 def has_note_gramps_id(self, gramps_id): 1046 """ 1047 Return True if the Gramps ID exists in the Note table. 1048 """ 1049 raise NotImplementedError 1050 1051 def has_person_gramps_id(self, gramps_id): 1052 """ 1053 Return True if the Gramps ID exists in the Person table. 1054 """ 1055 raise NotImplementedError 1056 1057 def has_place_gramps_id(self, gramps_id): 1058 """ 1059 Return True if the Gramps ID exists in the Place table. 1060 """ 1061 raise NotImplementedError 1062 1063 def has_repository_gramps_id(self, gramps_id): 1064 """ 1065 Return True if the Gramps ID exists in the Repository table. 1066 """ 1067 raise NotImplementedError 1068 1069 def has_source_gramps_id(self, gramps_id): 1070 """ 1071 Return True if the Gramps ID exists in the Source table. 1072 """ 1073 raise NotImplementedError 1074 1075 def has_event_handle(self, handle): 1076 """ 1077 Return True if the handle exists in the current Event database. 1078 """ 1079 raise NotImplementedError 1080 1081 def has_family_handle(self, handle): 1082 """ 1083 Return True if the handle exists in the current Family database. 1084 """ 1085 raise NotImplementedError 1086 1087 def has_media_handle(self, handle): 1088 """ 1089 Return True if the handle exists in the current Mediadatabase. 1090 """ 1091 raise NotImplementedError 1092 1093 def has_note_handle(self, handle): 1094 """ 1095 Return True if the handle exists in the current Note database. 1096 """ 1097 raise NotImplementedError 1098 1099 def has_person_handle(self, handle): 1100 """ 1101 Return True if the handle exists in the current Person database. 1102 """ 1103 raise NotImplementedError 1104 1105 def has_place_handle(self, handle): 1106 """ 1107 Return True if the handle exists in the current Place database. 1108 """ 1109 raise NotImplementedError 1110 1111 def has_repository_handle(self, handle): 1112 """ 1113 Return True if the handle exists in the current Repository database. 1114 """ 1115 raise NotImplementedError 1116 1117 def has_source_handle(self, handle): 1118 """ 1119 Return True if the handle exists in the current Source database. 1120 """ 1121 raise NotImplementedError 1122 1123 def has_citation_handle(self, handle): 1124 """ 1125 Return True if the handle exists in the current Citation database. 1126 """ 1127 raise NotImplementedError 1128 1129 def has_tag_handle(self, handle): 1130 """ 1131 Return True if the handle exists in the current Tag database. 1132 """ 1133 raise NotImplementedError 1134 1135 def has_name_group_key(self, name): 1136 """ 1137 Return if a key exists in the name_group table. 1138 """ 1139 raise NotImplementedError 1140 1141 def is_open(self): 1142 """ 1143 Return True if the database has been opened. 1144 """ 1145 raise NotImplementedError 1146 1147 def iter_citations(self): 1148 """ 1149 Return an iterator over objects for Citations in the database 1150 """ 1151 raise NotImplementedError 1152 1153 def iter_events(self): 1154 """ 1155 Return an iterator over objects for Events in the database 1156 """ 1157 raise NotImplementedError 1158 1159 def iter_families(self): 1160 """ 1161 Return an iterator over objects for Families in the database 1162 """ 1163 raise NotImplementedError 1164 1165 def iter_media(self): 1166 """ 1167 Return an iterator over objects for Medias in the database 1168 """ 1169 raise NotImplementedError 1170 1171 def iter_notes(self): 1172 """ 1173 Return an iterator over objects for Notes in the database 1174 """ 1175 raise NotImplementedError 1176 1177 def iter_people(self): 1178 """ 1179 Return an iterator over objects for Persons in the database 1180 """ 1181 raise NotImplementedError 1182 1183 def iter_places(self): 1184 """ 1185 Return an iterator over objects for Places in the database 1186 """ 1187 raise NotImplementedError 1188 1189 def iter_repositories(self): 1190 """ 1191 Return an iterator over objects for Repositories in the database 1192 """ 1193 raise NotImplementedError 1194 1195 def iter_sources(self): 1196 """ 1197 Return an iterator over objects for Sources in the database 1198 """ 1199 raise NotImplementedError 1200 1201 def iter_tags(self): 1202 """ 1203 Return an iterator over objects for Tags in the database 1204 """ 1205 raise NotImplementedError 1206 1207 def iter_citation_handles(self): 1208 """ 1209 Return an iterator over handles for Citations in the database 1210 """ 1211 raise NotImplementedError 1212 1213 def iter_event_handles(self): 1214 """ 1215 Return an iterator over handles for Events in the database 1216 """ 1217 raise NotImplementedError 1218 1219 def iter_family_handles(self): 1220 """ 1221 Return an iterator over handles for Families in the database 1222 """ 1223 raise NotImplementedError 1224 1225 def iter_media_handles(self): 1226 """ 1227 Return an iterator over handles for Media in the database 1228 """ 1229 raise NotImplementedError 1230 1231 def iter_note_handles(self): 1232 """ 1233 Return an iterator over handles for Notes in the database 1234 """ 1235 raise NotImplementedError 1236 1237 def iter_person_handles(self): 1238 """ 1239 Return an iterator over handles for Persons in the database 1240 """ 1241 raise NotImplementedError 1242 1243 def iter_place_handles(self): 1244 """ 1245 Return an iterator over handles for Places in the database 1246 """ 1247 raise NotImplementedError 1248 1249 def iter_repository_handles(self): 1250 """ 1251 Return an iterator over handles for Repositories in the database 1252 """ 1253 raise NotImplementedError 1254 1255 def iter_source_handles(self): 1256 """ 1257 Return an iterator over handles for Sources in the database 1258 """ 1259 raise NotImplementedError 1260 1261 def iter_tag_handles(self): 1262 """ 1263 Return an iterator over handles for Tags in the database 1264 """ 1265 raise NotImplementedError 1266 1267 def load(self, name, callback, mode=None, force_schema_upgrade=False, 1268 force_bsddb_upgrade=False): 1269 """ 1270 Open the specified database. 1271 """ 1272 raise NotImplementedError 1273 1274 def report_bm_change(self): 1275 """ 1276 Add 1 to the number of bookmark changes during this session. 1277 """ 1278 raise NotImplementedError 1279 1280 def request_rebuild(self): 1281 """ 1282 Notify clients that the data has changed significantly, and that all 1283 internal data dependent on the database should be rebuilt. 1284 Note that all rebuild signals on all objects are emitted at the same 1285 time. It is correct to assume that this is always the case. 1286 1287 .. todo:: it might be better to replace these rebuild signals by one 1288 single database-rebuild signal. 1289 """ 1290 raise NotImplementedError 1291 1292 def version_supported(self): 1293 """ 1294 Return True when the file has a supported version. 1295 """ 1296 raise NotImplementedError 1297 1298 def set_prefixes(self, person, media, family, source, citation, 1299 place, event, repository, note): 1300 """ 1301 Set the prefixes for the gramps ids for all gramps objects 1302 """ 1303 raise NotImplementedError 1304 1305 def set_citation_id_prefix(self, val): 1306 """ 1307 Set the naming template for Gramps Citation ID values. 1308 1309 The string is expected to be in the form of a simple text string, or 1310 in a format that contains a C/Python style format string using %d, 1311 such as C%d or C%04d. 1312 """ 1313 raise NotImplementedError 1314 1315 def set_event_id_prefix(self, val): 1316 """ 1317 Set the naming template for Gramps Event ID values. 1318 1319 The string is expected to be in the form of a simple text string, or 1320 in a format that contains a C/Python style format string using %d, 1321 such as E%d or E%04d. 1322 """ 1323 raise NotImplementedError 1324 1325 def set_family_id_prefix(self, val): 1326 """ 1327 Set the naming template for Gramps Family ID values. 1328 1329 The string is expected to be in the form of a simple text string, or 1330 in a format that contains a C/Python style format string using %d, 1331 such as F%d or F%04d. 1332 """ 1333 raise NotImplementedError 1334 1335 def set_note_id_prefix(self, val): 1336 """ 1337 Set the naming template for Gramps Note ID values. 1338 1339 The string is expected to be in the form of a simple text string, or 1340 in a format that contains a C/Python style format string using %d, 1341 such as N%d or N%04d. 1342 """ 1343 raise NotImplementedError 1344 1345 def set_media_id_prefix(self, val): 1346 """ 1347 Set the naming template for Gramps Media ID values. 1348 1349 The string is expected to be in the form of a simple text string, or 1350 in a format that contains a C/Python style format string using %d, 1351 such as O%d or O%04d. 1352 """ 1353 raise NotImplementedError 1354 1355 def set_person_id_prefix(self, val): 1356 """ 1357 Set the naming template for Gramps Person ID values. 1358 1359 The string is expected to be in the form of a simple text string, or 1360 in a format that contains a C/Python style format string using %d, 1361 such as I%d or I%04d. 1362 """ 1363 raise NotImplementedError 1364 1365 def set_place_id_prefix(self, val): 1366 """ 1367 Set the naming template for Gramps Place ID values. 1368 1369 The string is expected to be in the form of a simple text string, or 1370 in a format that contains a C/Python style format string using %d, 1371 such as P%d or P%04d. 1372 """ 1373 raise NotImplementedError 1374 1375 def set_repository_id_prefix(self, val): 1376 """ 1377 Set the naming template for Gramps Repository ID values. 1378 1379 The string is expected to be in the form of a simple text string, or 1380 in a format that contains a C/Python style format string using %d, 1381 such as R%d or R%04d. 1382 """ 1383 raise NotImplementedError 1384 1385 def set_source_id_prefix(self, val): 1386 """ 1387 Set the naming template for Gramps Source ID values. 1388 1389 The string is expected to be in the form of a simple text string, or 1390 in a format that contains a C/Python style format string using %d, 1391 such as S%d or S%04d. 1392 """ 1393 raise NotImplementedError 1394 1395 def set_mediapath(self, path): 1396 """ 1397 Set the default media path for database. 1398 """ 1399 raise NotImplementedError 1400 1401 def set_researcher(self, owner): 1402 """ 1403 Set the information about the owner of the database. 1404 """ 1405 raise NotImplementedError 1406 1407 def get_dbid(self): 1408 """ 1409 A unique ID for this database on this computer. 1410 """ 1411 raise NotImplementedError 1412 1413 def get_dbname(self): 1414 """ 1415 A name for this database on this computer. 1416 """ 1417 raise NotImplementedError 1418 1419 def get_summary(self): 1420 """ 1421 Returns dictionary of summary item. 1422 Should include, if possible: 1423 1424 _("Number of people") 1425 _("Version") 1426 _("Data version") 1427 """ 1428 raise NotImplementedError 1429 1430 def requires_login(self): 1431 """ 1432 Returns True for backends that require a login dialog, else False. 1433 """ 1434 return False 1435 1436 def method(self, fmt, *args): 1437 """ 1438 Convenience function to return database methods. 1439 1440 :param fmt: Method format string. 1441 :type fmt: str 1442 :param args: Substitutions arguments. 1443 :type args: str 1444 :returns: Returns a database method or None. 1445 :rtype: method 1446 1447 Examples:: 1448 1449 db.method('get_%s_from_handle, 'Person') 1450 Returns the get_person_from_handle method. 1451 1452 db.method('get_%s_from_%s, 'Event', 'gramps_id') 1453 Returns the get_event_from_gramps_id method. 1454 1455 db.method('get_%s_handles, 'Attribute') 1456 Returns None. Attribute is not a primary object. 1457 1458 .. warning:: Formats 'iter_%s' and 'get_number_of_%s' are not yet 1459 implemented. 1460 """ 1461 return getattr(self, fmt % tuple([arg.lower() for arg in args]), None) 1462 1463 1464class DbWriteBase(DbReadBase): 1465 """ 1466 Gramps database object. This object is a base class for all 1467 database interfaces. All methods raise NotImplementedError 1468 and must be implemented in the derived class as required. 1469 """ 1470 1471 def __init__(self): 1472 """ 1473 Create a new DbWriteBase instance. 1474 1475 A new DbWriteBase class should never be directly created. Only classes 1476 derived from this class should be created. 1477 """ 1478 DbReadBase.__init__(self) 1479 1480 def add_citation(self, event, transaction, set_gid=True): 1481 """ 1482 Add an Citation to the database, assigning internal IDs if they have 1483 not already been defined. 1484 1485 If not set_gid, then gramps_id is not set. 1486 """ 1487 raise NotImplementedError 1488 1489 def add_event(self, event, transaction, set_gid=True): 1490 """ 1491 Add an Event to the database, assigning internal IDs if they have 1492 not already been defined. 1493 1494 If not set_gid, then gramps_id is not set. 1495 """ 1496 raise NotImplementedError 1497 1498 def add_family(self, family, transaction, set_gid=True): 1499 """ 1500 Add a Family to the database, assigning internal IDs if they have 1501 not already been defined. 1502 1503 If not set_gid, then gramps_id is not set. 1504 """ 1505 raise NotImplementedError 1506 1507 def add_media(self, obj, transaction, set_gid=True): 1508 """ 1509 Add a Media to the database, assigning internal IDs if they have 1510 not already been defined. 1511 1512 If not set_gid, then gramps_id is not set. 1513 """ 1514 raise NotImplementedError 1515 1516 def add_note(self, obj, transaction, set_gid=True): 1517 """ 1518 Add a Note to the database, assigning internal IDs if they have 1519 not already been defined. 1520 1521 If not set_gid, then gramps_id is not set. 1522 """ 1523 raise NotImplementedError 1524 1525 def add_person(self, person, transaction, set_gid=True): 1526 """ 1527 Add a Person to the database, assigning internal IDs if they have 1528 not already been defined. 1529 1530 If not set_gid, then gramps_id is not set. 1531 """ 1532 raise NotImplementedError 1533 1534 def add_place(self, place, transaction, set_gid=True): 1535 """ 1536 Add a Place to the database, assigning internal IDs if they have 1537 not already been defined. 1538 1539 If not set_gid, then gramps_id is not set. 1540 """ 1541 raise NotImplementedError 1542 1543 def add_repository(self, obj, transaction, set_gid=True): 1544 """ 1545 Add a Repository to the database, assigning internal IDs if they have 1546 not already been defined. 1547 1548 If not set_gid, then gramps_id is not set. 1549 """ 1550 raise NotImplementedError 1551 1552 def add_source(self, source, transaction, set_gid=True): 1553 """ 1554 Add a Source to the database, assigning internal IDs if they have 1555 not already been defined. 1556 1557 If not set_gid, then gramps_id is not set. 1558 """ 1559 raise NotImplementedError 1560 1561 def add_tag(self, tag, transaction): 1562 """ 1563 Add a Tag to the database, assigning a handle if it has not already 1564 been defined. 1565 """ 1566 raise NotImplementedError 1567 1568 def add_to_surname_list(self, person, batch_transaction, name): 1569 """ 1570 Add surname from given person to list of surnames 1571 """ 1572 raise NotImplementedError 1573 1574 def commit_citation(self, event, transaction, change_time=None): 1575 """ 1576 Commit the specified Event to the database, storing the changes as 1577 part of the transaction. 1578 """ 1579 raise NotImplementedError 1580 1581 def commit_event(self, event, transaction, change_time=None): 1582 """ 1583 Commit the specified Event to the database, storing the changes as 1584 part of the transaction. 1585 """ 1586 raise NotImplementedError 1587 1588 def commit_family(self, family, transaction, change_time=None): 1589 """ 1590 Commit the specified Family to the database, storing the changes as 1591 part of the transaction. 1592 """ 1593 raise NotImplementedError 1594 1595 def commit_media(self, obj, transaction, change_time=None): 1596 """ 1597 Commit the specified Media to the database, storing the changes 1598 as part of the transaction. 1599 """ 1600 raise NotImplementedError 1601 1602 def commit_note(self, note, transaction, change_time=None): 1603 """ 1604 Commit the specified Note to the database, storing the changes as part 1605 of the transaction. 1606 """ 1607 raise NotImplementedError 1608 1609 def commit_person(self, person, transaction, change_time=None): 1610 """ 1611 Commit the specified Person to the database, storing the changes as 1612 part of the transaction. 1613 """ 1614 raise NotImplementedError 1615 1616 def commit_place(self, place, transaction, change_time=None): 1617 """ 1618 Commit the specified Place to the database, storing the changes as 1619 part of the transaction. 1620 """ 1621 raise NotImplementedError 1622 1623 def commit_repository(self, repository, transaction, change_time=None): 1624 """ 1625 Commit the specified Repository to the database, storing the changes 1626 as part of the transaction. 1627 """ 1628 raise NotImplementedError 1629 1630 def commit_source(self, source, transaction, change_time=None): 1631 """ 1632 Commit the specified Source to the database, storing the changes as 1633 part of the transaction. 1634 """ 1635 raise NotImplementedError 1636 1637 def commit_tag(self, tag, transaction, change_time=None): 1638 """ 1639 Commit the specified Tag to the database, storing the changes as 1640 part of the transaction. 1641 """ 1642 raise NotImplementedError 1643 1644 def get_undodb(self): 1645 """ 1646 Return the database that keeps track of Undo/Redo operations. 1647 """ 1648 raise NotImplementedError 1649 1650 def rebuild_secondary(self, callback): 1651 """ 1652 Rebuild secondary indices 1653 """ 1654 raise NotImplementedError 1655 1656 def reindex_reference_map(self, callback): 1657 """ 1658 Reindex all primary records in the database. 1659 """ 1660 raise NotImplementedError 1661 1662 def remove_citation(self, handle, transaction): 1663 """ 1664 Remove the Event specified by the database handle from the 1665 database, preserving the change in the passed transaction. 1666 """ 1667 raise NotImplementedError 1668 1669 def remove_event(self, handle, transaction): 1670 """ 1671 Remove the Event specified by the database handle from the 1672 database, preserving the change in the passed transaction. 1673 """ 1674 raise NotImplementedError 1675 1676 def remove_family(self, handle, transaction): 1677 """ 1678 Remove the Family specified by the database handle from the 1679 database, preserving the change in the passed transaction. 1680 """ 1681 raise NotImplementedError 1682 1683 def remove_media(self, handle, transaction): 1684 """ 1685 Remove the MediaPerson specified by the database handle from the 1686 database, preserving the change in the passed transaction. 1687 """ 1688 raise NotImplementedError 1689 1690 def remove_note(self, handle, transaction): 1691 """ 1692 Remove the Note specified by the database handle from the 1693 database, preserving the change in the passed transaction. 1694 """ 1695 raise NotImplementedError 1696 1697 def remove_person(self, handle, transaction): 1698 """ 1699 Remove the Person specified by the database handle from the database, 1700 preserving the change in the passed transaction. 1701 """ 1702 raise NotImplementedError 1703 1704 def remove_place(self, handle, transaction): 1705 """ 1706 Remove the Place specified by the database handle from the 1707 database, preserving the change in the passed transaction. 1708 """ 1709 raise NotImplementedError 1710 1711 def remove_repository(self, handle, transaction): 1712 """ 1713 Remove the Repository specified by the database handle from the 1714 database, preserving the change in the passed transaction. 1715 """ 1716 raise NotImplementedError 1717 1718 def remove_source(self, handle, transaction): 1719 """ 1720 Remove the Source specified by the database handle from the 1721 database, preserving the change in the passed transaction. 1722 """ 1723 raise NotImplementedError 1724 1725 def remove_tag(self, handle, transaction): 1726 """ 1727 Remove the Tag specified by the database handle from the 1728 database, preserving the change in the passed transaction. 1729 """ 1730 raise NotImplementedError 1731 1732 def remove_from_surname_list(self, person): 1733 """ 1734 Check whether there are persons with the same surname left in 1735 the database. 1736 1737 If not then we need to remove the name from the list. 1738 The function must be overridden in the derived class. 1739 """ 1740 raise NotImplementedError 1741 1742 def set_default_person_handle(self, handle): 1743 """ 1744 Set the default Person to the passed instance. 1745 """ 1746 raise NotImplementedError 1747 1748 def set_name_group_mapping(self, name, group): 1749 """ 1750 Set the default grouping name for a surname. 1751 1752 Needs to be overridden in the derived class. 1753 """ 1754 raise NotImplementedError 1755 1756 def transaction_begin(self, transaction): 1757 """ 1758 Prepare the database for the start of a new transaction. 1759 1760 Two modes should be provided: transaction.batch=False for ordinary 1761 database operations that will be encapsulated in database transactions 1762 to make them ACID and that are added to Gramps transactions so that 1763 they can be undone. And transaction.batch=True for lengthy database 1764 operations, that benefit from a speedup by making them none ACID, and 1765 that can't be undone. The user is warned and is asked for permission 1766 before the start of such database operations. 1767 1768 :param transaction: Gramps transaction ... 1769 :type transaction: :py:class:`.DbTxn` 1770 :returns: Returns the Gramps transaction. 1771 :rtype: :py:class:`.DbTxn` 1772 """ 1773 raise NotImplementedError 1774 1775 def transaction_commit(self, transaction): 1776 """ 1777 Make the changes to the database final and add the content of the 1778 transaction to the undo database. 1779 """ 1780 raise NotImplementedError 1781 1782 def transaction_abort(self, transaction): 1783 """ 1784 Revert the changes made to the database so far during the transaction. 1785 """ 1786 raise NotImplementedError 1787 1788 def undo(self, update_history=True): 1789 """ 1790 Undo last transaction. 1791 """ 1792 raise NotImplementedError 1793 1794 def redo(self, update_history=True): 1795 """ 1796 Redo last transaction. 1797 """ 1798 raise NotImplementedError 1799 1800 def add_child_to_family(self, family, child, 1801 mrel=ChildRefType(), 1802 frel=ChildRefType(), 1803 trans=None): 1804 """ 1805 Adds a child to a family. 1806 """ 1807 cref = ChildRef() 1808 cref.ref = child.handle 1809 cref.set_father_relation(frel) 1810 cref.set_mother_relation(mrel) 1811 1812 family.add_child_ref(cref) 1813 child.add_parent_family_handle(family.handle) 1814 1815 if trans is None: 1816 with DbTxn(_('Add child to family'), self) as trans: 1817 self.commit_family(family, trans) 1818 self.commit_person(child, trans) 1819 else: 1820 self.commit_family(family, trans) 1821 self.commit_person(child, trans) 1822 1823 def remove_child_from_family(self, person_handle, family_handle, 1824 trans=None): 1825 """ 1826 Remove a person as a child of the family, deleting the family if 1827 it becomes empty. 1828 """ 1829 if trans is None: 1830 with DbTxn(_("Remove child from family"), self) as trans: 1831 self.__remove_child_from_family(person_handle, family_handle, 1832 trans) 1833 else: 1834 self.__remove_child_from_family(person_handle, family_handle, 1835 trans) 1836 trans.set_description(_("Remove child from family")) 1837 1838 def __remove_child_from_family(self, person_handle, family_handle, trans): 1839 """ 1840 Remove a person as a child of the family, deleting the family if 1841 it becomes empty; trans is compulsory. 1842 """ 1843 person = self.get_person_from_handle(person_handle) 1844 family = self.get_family_from_handle(family_handle) 1845 person.remove_parent_family_handle(family_handle) 1846 family.remove_child_handle(person_handle) 1847 1848 if (not family.get_father_handle() and not family.get_mother_handle() 1849 and not family.get_child_ref_list()): 1850 self.remove_family_relationships(family_handle, trans) 1851 else: 1852 self.commit_family(family, trans) 1853 self.commit_person(person, trans) 1854 1855 def delete_person_from_database(self, person, trans): 1856 """ 1857 Deletes a person from the database, cleaning up all associated 1858 references. 1859 """ 1860 1861 # clear out the default person if the person is the default person 1862 if self.get_default_person() == person: 1863 self.set_default_person_handle(None) 1864 1865 # loop through the family list 1866 for family_handle in person.get_family_handle_list(): 1867 if not family_handle: 1868 continue 1869 1870 family = self.get_family_from_handle(family_handle) 1871 1872 if person.get_handle() == family.get_father_handle(): 1873 family.set_father_handle(None) 1874 else: 1875 family.set_mother_handle(None) 1876 1877 if not family.get_father_handle() and \ 1878 not family.get_mother_handle() and \ 1879 not family.get_child_ref_list(): 1880 self.remove_family_relationships(family_handle, trans) 1881 else: 1882 self.commit_family(family, trans) 1883 1884 for family_handle in person.get_parent_family_handle_list(): 1885 if family_handle: 1886 family = self.get_family_from_handle(family_handle) 1887 family.remove_child_handle(person.get_handle()) 1888 if not family.get_father_handle() and \ 1889 not family.get_mother_handle() and \ 1890 not family.get_child_ref_list(): 1891 self.remove_family_relationships(family_handle, trans) 1892 else: 1893 self.commit_family(family, trans) 1894 1895 handle = person.get_handle() 1896 1897 person_list = [ 1898 item[1] for item in 1899 self.find_backlink_handles(handle, ['Person'])] 1900 1901 for phandle in person_list: 1902 prsn = self.get_person_from_handle(phandle) 1903 prsn.remove_handle_references('Person', [handle]) 1904 self.commit_person(prsn, trans) 1905 self.remove_person(handle, trans) 1906 1907 def remove_family_relationships(self, family_handle, trans=None): 1908 """ 1909 Remove a family and its relationships. 1910 """ 1911 if trans is None: 1912 with DbTxn(_("Remove Family"), self) as trans: 1913 self.__remove_family_relationships(family_handle, trans) 1914 else: 1915 self.__remove_family_relationships(family_handle, trans) 1916 trans.set_description(_("Remove Family")) 1917 1918 def __remove_family_relationships(self, family_handle, trans): 1919 """ 1920 Remove a family and all that references it; trans is compulsory. 1921 """ 1922 person_list = [item[1] for item in 1923 self.find_backlink_handles(family_handle, ['Person'])] 1924 for phandle in person_list: 1925 person = self.get_person_from_handle(phandle) 1926 if person: 1927 person.remove_handle_references('Family', [family_handle]) 1928 self.commit_person(person, trans) 1929 self.remove_family(family_handle, trans) 1930 1931 def remove_parent_from_family(self, person_handle, family_handle, 1932 trans=None): 1933 """ 1934 Remove a person as either the father or mother of a family, 1935 deleting the family if it becomes empty. 1936 """ 1937 if trans is None: 1938 with DbTxn('', self) as trans: 1939 msg = self.__remove_parent_from_family(person_handle, 1940 family_handle, trans) 1941 trans.set_description(msg) 1942 else: 1943 msg = self.__remove_parent_from_family(person_handle, 1944 family_handle, trans) 1945 trans.set_description(msg) 1946 1947 def __remove_parent_from_family(self, person_handle, family_handle, trans): 1948 """ 1949 Remove a person as either the father or mother of a family, 1950 deleting the family if it becomes empty; trans is compulsory. 1951 """ 1952 person = self.get_person_from_handle(person_handle) 1953 family = self.get_family_from_handle(family_handle) 1954 1955 person.remove_family_handle(family_handle) 1956 if family.get_father_handle() == person_handle: 1957 family.set_father_handle(None) 1958 msg = _("Remove father from family") 1959 elif family.get_mother_handle() == person_handle: 1960 msg = _("Remove mother from family") 1961 family.set_mother_handle(None) 1962 else: 1963 raise DbTransactionCancel("The relation between the person and " 1964 "the family you try to remove is not consistent, please fix " 1965 "that first, for example from the family editor or by running " 1966 "the database repair tool, before removing the family.") 1967 1968 if (not family.get_father_handle() and not family.get_mother_handle() 1969 and not family.get_child_ref_list()): 1970 self.remove_family_relationships(family_handle, trans) 1971 else: 1972 self.commit_family(family, trans) 1973 self.commit_person(person, trans) 1974 return msg 1975 1976 def marriage_from_eventref_list(self, eventref_list): 1977 """ 1978 Get the marriage event from an eventref list. 1979 """ 1980 for eventref in eventref_list: 1981 event = self.get_event_from_handle(eventref.ref) 1982 if event and event.type.is_marriage(): 1983 return event 1984 return None 1985 1986 def get_total(self): 1987 """ 1988 Get the total of primary objects. 1989 """ 1990 person_len = self.get_number_of_people() 1991 family_len = self.get_number_of_families() 1992 event_len = self.get_number_of_events() 1993 place_len = self.get_number_of_places() 1994 repo_len = self.get_number_of_repositories() 1995 source_len = self.get_number_of_sources() 1996 citation_len = self.get_number_of_citations() 1997 media_len = self.get_number_of_media() 1998 note_len = self.get_number_of_notes() 1999 tag_len = self.get_number_of_tags() 2000 2001 return (person_len + family_len + event_len + place_len + repo_len + 2002 source_len + citation_len + media_len + note_len + tag_len) 2003 2004 def set_birth_death_index(self, person): 2005 """ 2006 Set the birth and death indices for a person. 2007 """ 2008 birth_ref_index = -1 2009 death_ref_index = -1 2010 event_ref_list = person.get_event_ref_list() 2011 for index in range(len(event_ref_list)): 2012 ref = event_ref_list[index] 2013 event = self.get_event_from_handle(ref.ref) 2014 if (event.type.is_birth() 2015 and ref.role.is_primary() 2016 and (birth_ref_index == -1)): 2017 birth_ref_index = index 2018 elif (event.type.is_death() 2019 and ref.role.is_primary() 2020 and (death_ref_index == -1)): 2021 death_ref_index = index 2022 2023 person.birth_ref_index = birth_ref_index 2024 person.death_ref_index = death_ref_index 2025