Compare commits

...

58 Commits

Author SHA1 Message Date
Tim G L Lyons
7fb1ad876a Improve/harmonise error handling for missing template (even though missing template should never occur).
svn: r23195
2013-09-25 13:59:54 +00:00
Tim G L Lyons
89909f87cd Correct error introduced in r23144
svn: r23194
2013-09-25 13:48:17 +00:00
Tim G L Lyons
5903853640 Fix citation filters so they no longer try to filter citations with a sources filter. Citation filter now allows specification of both source and citation data. When a citation is shown in a search or a filtered citation tree view, the corresponding source is also shown.
svn: r23144
2013-09-16 21:42:28 +00:00
Tim G L Lyons
7c90638ad3 Various changes to use title, author, pubinfo and page from citeref, rather than from Src and Citation.
svn: r22912
2013-08-23 18:25:21 +00:00
Tim G L Lyons
9037f827a5 - update exportxml and importxml for templates,
- move TemplateElement into separate module,
- remove redundant srctemplatelist module,
- fix editsource so source attribute tab updates when template fields are input,
- fix importcsv so it uses map names defined in citeref module,

svn: r22880
2013-08-19 22:31:52 +00:00
Tim G L Lyons
367de337a4 - Move citeref formatting to gen.utils. Functions now have a db parameter, so they find the template themselves.
- Separate out the GEDCOM template creation. It becomes a separate plugin that can be loaded or not as the user chooses (but it is loaded automatically on upgrade).
- Fixes to allow templates to work even when no templates are loaded (data is input via the Attributes tab not the source template tab).
- Enhance upgrade to include GEDCOM template. The GEDCOM template is automatically loaded when a database that contains sources is upgraded.
- Tidy up unused variables and redundant code.


svn: r22856
2013-08-12 16:04:37 +00:00
Tim G L Lyons
06de73c8f4 Templates are a full TableObject and stored in the database. Template attributes are CUSTOM attributes.
svn: r22843
2013-08-10 15:25:56 +00:00
Tim G L Lyons
c4ecfaafe9 Modified EE-references and GEDCOM generation to use Template data structures. Added support for interface to citeproc for CSL style sheets (not ready for use yet). Modified code to work with Python3.
svn: r22737
2013-07-25 14:22:48 +00:00
Tim G L Lyons
2430607b63 Modify srctemplatetab to use new Template data model
svn: r22698
2013-07-20 18:15:58 +00:00
Tim G L Lyons
94fe287886 Restructure SrcTemplate and introduce SrcTemplateList (work in progress)
svn: r22694
2013-07-17 18:26:35 +00:00
Tim G L Lyons
6cf005cb38 Source editor, wrap 'Reference Information' lines.
svn: r22692
2013-07-16 23:26:46 +00:00
Benny Malengier
38db8959fa GEP18: big database change for source and citation
svn: r22639
2013-07-01 19:27:48 +00:00
Benny Malengier
6c04f8b151 GEP18: add deprecated decorator to gramps, use in src and citation
Usage: python -W all Gramps.py


svn: r22622
2013-06-28 12:49:31 +00:00
Benny Malengier
85cc487ee9 GEP18: no longer show default cite fields on source level. Flag could be reactivated in the future
svn: r22621
2013-06-28 06:43:31 +00:00
Benny Malengier
38d7ee72f2 GEP18: csv loading based on English only
svn: r22620
2013-06-28 06:36:45 +00:00
Benny Malengier
9ce8403106 GEP 18: Improve error message
svn: r22619
2013-06-27 19:02:11 +00:00
Benny Malengier
ee3350e9d5 GEP 18: fix bug in List reference determination
svn: r22614
2013-06-25 23:05:49 +00:00
Benny Malengier
6cde88e22d GEP 18: fix index error
svn: r22613
2013-06-25 22:33:37 +00:00
Benny Malengier
e9efb9debc GEP 18: merge trunk into GEP branch
svn: r22612
2013-06-25 22:28:13 +00:00
Benny Malengier
0a2580e9c5 GEP 18: 1. Source templates as new plugin type
2. EE templates in their own plugin, loading from csv in data


svn: r22611
2013-06-25 22:26:56 +00:00
Benny Malengier
5b6da40866 GEP 18: merge latest trunk changes in branch
svn: r22605
2013-06-25 10:56:02 +00:00
Benny Malengier
0d3aec7313 GEP 18: merge trunk changes in gep branch
svn: r22603
2013-06-25 10:45:43 +00:00
Benny Malengier
a7e5ecbadf GEP 18: add date from cite in reference part of citation
svn: r22602
2013-06-25 09:20:16 +00:00
Benny Malengier
54ef9241a1 GEP 18: remove subgroup, replace by section
svn: r22575
2013-06-23 21:42:54 +00:00
Benny Malengier
1fd823bb71 GEP 18: Obtain repo data from attached repo, no user input field
svn: r22572
2013-06-23 14:38:36 +00:00
Benny Malengier
99671bdfaf GEP18: refractor: move template stuff to srctemplate.py
svn: r22554
2013-06-22 16:09:24 +00:00
Benny Malengier
8ad6600746 GEP 18: automatic update as you type for citation fields, fix in formatting, fix with indicators
svn: r22526
2013-06-19 21:14:18 +00:00
Benny Malengier
2b6ee1aa60 GEP18: add hint for indicators, add tooltips, again remove some fields
svn: r22519
2013-06-19 06:56:52 +00:00
Benny Malengier
3a42651fb1 GEP 18: still more aggressive reduction of attribute fields
svn: r22516
2013-06-18 14:10:18 +00:00
Benny Malengier
cc839bf167 GEP 18: introduce label in template, drastical reduction of number of source attributes
svn: r22514
2013-06-17 13:49:26 +00:00
Benny Malengier
f177537525 Merged trunk back into gep 18
svn: r22513
2013-06-17 11:14:05 +00:00
Benny Malengier
dce3fc0605 GEP 18: show citation template fields, source fields in scrolled window.
svn: r22512
2013-06-15 10:17:58 +00:00
Benny Malengier
9391218f20 GEP18: start with construction citation template fields
svn: r22511
2013-06-14 23:03:52 +00:00
Benny Malengier
06e4dcd11d GEP 18: fix bug setting cite when no cite loaded. Factor out fields for reuse in citation GUI
svn: r22507
2013-06-14 11:05:21 +00:00
Benny Malengier
3135b2b304 GEP 18: * fix bug with gid of citation not updating
* allow to add new citation from the citedin tab


svn: r22502
2013-06-13 20:38:08 +00:00
Benny Malengier
5ee5ef158e GEP 18: fixes with citedintab.
*show unused citations also
 *correct switching between citation by updating citation displaytabs
 *backref, correct handling of connectid


svn: r22496
2013-06-12 08:48:48 +00:00
Benny Malengier
5ffcd383ac GEP 18: Allow citation part to be closed, so people can change citation loaded
svn: r22493
2013-06-11 18:02:50 +00:00
Benny Malengier
8204724f32 GEP 18: save the citation also in the source editor
svn: r22489
2013-06-10 20:58:04 +00:00
Benny Malengier
973e143b22 GEP 18: Deprecate EditCitation
svn: r22486
2013-06-10 20:09:03 +00:00
Benny Malengier
e5f80e521c GEP 18: avoid GTK warning on notebook tab overwrite
svn: r22484
2013-06-07 08:26:25 +00:00
Benny Malengier
ccf1f2eac5 GEP 18: add autotitle setting from given attributes
svn: r22483
2013-06-05 21:47:18 +00:00
Benny Malengier
1e99275b84 GEP 18: allow default citation values and short values to be set on source level
svn: r22482
2013-06-05 13:07:55 +00:00
Benny Malengier
b28bd17980 GEP 18: allow viewing of different citations in source editor
Start of merging editsource and editcitation


svn: r22481
2013-06-05 07:34:47 +00:00
Benny Malengier
8e922b562d GEP 18: extend functionality of citedin tab
svn: r22473
2013-06-03 16:11:13 +00:00
Benny Malengier
72748498b2 GEP 18 - General improvement: Add a cited in tab to sources for general overview of uses
svn: r22472
2013-06-03 14:34:44 +00:00
Benny Malengier
9310d5c32d GEP 18: * fixes in template handling
* add source text to overview tab of source


svn: r22471
2013-06-02 15:20:08 +00:00
Benny Malengier
6e2272bb78 GEP 18: * read in template data
* manage template via SrcTemplate
        * obtain author/pubinfo from attributes via template


svn: r22469
2013-06-02 10:08:26 +00:00
Benny Malengier
be45ac54fe GEP 18
* more reduction of fields
 * mapping to gedcom fields
 * style shorteralg as numbers in code


svn: r22466
2013-06-01 09:48:52 +00:00
Benny Malengier
b28bfb39db bring gep18 branch in line with trunk
svn: r22463
2013-05-31 19:19:27 +00:00
Benny Malengier
6ef2e77568 GEP 18: sanitize the many fields
svn: r22462
2013-05-31 19:17:33 +00:00
Benny Malengier
a8ddc8e635 gep18: remove print, attr type in two columns for now
svn: r22457
2013-05-30 08:31:33 +00:00
Benny Malengier
30e051a7fe GEP18: fix expand of reference section in editsource
svn: r22456
2013-05-29 20:31:11 +00:00
Benny Malengier
3b99b31656 GEP 18: fix bug due to previous commit
svn: r22455
2013-05-29 20:27:24 +00:00
Benny Malengier
a091d97677 GEP 18: automatic setting of fields, and updating attribute list
svn: r22454
2013-05-29 18:58:23 +00:00
Benny Malengier
69cfbe7a02 automatic creation of needed fields
svn: r22453
2013-05-29 17:08:51 +00:00
Benny Malengier
6dce67703e preselect the template of the source in the template tree
svn: r22452
2013-05-29 15:35:44 +00:00
Benny Malengier
c449bbf588 Evidence source new source editor version 1
* Overview tab
 * selection of template, which updates the template attribute


svn: r22451
2013-05-29 14:56:38 +00:00
Benny Malengier
f167507a0f Start with GUI ideas for GEPS 018
http://www.gramps-project.org/wiki/index.php?title=GEPS_018:_Evidence_style_sources


svn: r22441
2013-05-28 09:56:38 +00:00
95 changed files with 21169 additions and 15529 deletions

File diff suppressed because it is too large Load Diff

View File

@ -48,10 +48,222 @@ CITETYPECOL = 5
IDENTCOL = 6
LDELCOL = 7 # left delimiter
FIELDCOL = 8
RDELCOL = 9 # right delimiter
STYLECOL = 10
PRIVACYCOL = 11
OPTCOL = 12
LABELCOL = 9
RDELCOL = 10 # right delimiter
GEDCOMCOL = 11
SHORTERCOL = 12
STYLECOL = 13
PRIVACYCOL = 14
OPTCOL = 15
HINTCOL = 16
TOOLTIPCOL = 17
CITE_TYPES = {'F': 'REF_TYPE_F', 'L': 'REF_TYPE_L', 'S': 'REF_TYPE_S'}
GEDCOMFIELDS = {'A': 'GED_AUTHOR', 'T': 'GED_TITLE',
'P': 'GED_PUBINF', 'D': 'GED_DATE'}
SHORTERALG = {'LOC': 'SHORTERALG_LOC', 'YEAR': 'SHORTERALG_YEAR',
'ETAL': 'SHORTERALG_ETAL', 'REV.': 'SHORTERALG_REVERT_TO_DOT'}
STYLES = {'Quoted': 'STYLE_QUOTE', 'Italics': 'STYLE_EMPH',
'QuotedCont': 'STYLE_QUOTECONT', 'Bold': 'STYLE_BOLD'}
#already defined srcattrtypes
KNOWN_FIELDS = ['EVEN_REC', 'EVEN_CITED', 'EVEN_ROLE', 'GEN_BY', 'REPOSITORY',
'REPOSITORY_ADDRESS', 'REPOSITORY_SHORT_VERSION', 'REPOSITORY_CALL_NUMBER',
'DATE']
DEFAULT_HINTS = {
"ACT": "Public Law 12-98",
"ADDRESS": "Broadway Avenue, New York",
"AFFILIATION": "Agent of Gramps Software",
"AUTHOR": "Doe, D.P. & Cameron, E.",
"AUTHOR_LOCATION": "Chicago",
"BOOK": "The big example Gramps manual",
"CASE": "B. Malengier versus N. Hall",
"CEMETERY": "Greenwich Cemetery Office",
"CHAPTER": "The first office of T. Rooseveld",
"CHAPTER_PAGES": "24-55",
"COLLECTION": "Bruges Lace Collection",
"COLUMN": "col. 3",
"COMPILER": "T. Da Silva",
"CREATION_DATE": "13 Aug 1965",
"CREATOR": "P. Picasso",
"CREDIT_LINE": "Based on unnamed document lost in fire",
"DATE": "17 Sep 1745",
"DATE_ACCESSED": "18 Jun 2013",
"DATE_RANGE": "2003-6",
"DESCRIPTION": "The lace has inscriptions with names of nobility",
"DISTRICT": "Enumeration district (ED) 14",
"DIVISION": "Peterburg Post Office, or Portland, ward 4",
"EDITION": "Second Edition",
"EDITOR": "Hoover, J.E.",
"FILE": "Membership application J. Rapinat",
"FILE_DATE": "15 Jan 1870",
"FILE_LOCATION": "Accession 7, Box 3",
"FILE_NO": "1243-EB-98",
"FILE_UNIT": "Letters to George Washington",
"FILM_ID": "T345",
"FILM_PUBLICATION_PLACE": "Kansas City",
"FILM_PUBLISHER": "NY Genealogy Association",
"FILM_TYPE": "FHL microfilm",
"FORMAT": "Digital Images, or Database, or Cards, ...",
"FRAME": "frames 387-432",
"GROUP": "Miami Patent Office",
"HOUSEHOLD": "dwelling 345, family 654",
"ID": "I50-68, or 1910 U.S. census, or ...",
"INSTITUTION": "Sorbonne University",
"INTERVIEWER": "Materley, B.",
"ISSUE_DATE": "Jun 2004",
"ISSUE_RANGE": "145-394, scattered issues",
"ITEM_OF_INTEREST": "entry for G. Galileo, or Doe Household, or A. Einstein Grave ...",
"JURISDICTION": "Jackson County, Alabama",
"LOCATION": "Istanbul",
"NUMBER": "2, or Record Group 34, or ...",
"NUMBER_6TOTAL9": "5",
"ORIGINAL_REPOSITORY": "National Archives",
"ORIGINAL_REPOSITORY_LOCATION": "Washington, D.C.",
"ORIGINAL_YEAR": "1966",
"PAGE": "5; or 4,6-8, ...",
"PAGE_RANGE": "1-13",
"PART": "Part 3",
"PLACE_CREATED": "London",
"POSITION": "written in the left margin, or second row, 3th line",
"POSTING_DATE": "5 Jul 1799",
"PROFESSIONAL_CREDENTIALS": "Prof.; or Dr. ...",
"PROVENANCE": "add provenance of the material",
"PUBLICATION_FORMAT": "CD-ROM or eprint or ...",
"PUBLICATION_PLACE": "Berlin",
"PUBLICATION_TITLE": "Title of Blog, Newsletter, DVD, ...",
"PUBLICATION_YEAR": "2014",
"PUBLISHER": "Springer",
"PUB_INFO": "Springer, Berlin, 2014",
"RECIPIENT": "J. Ralls",
"RELATIONSHIP": "Paul's uncle and brother of Erik",
"REPORT_DATE": "3 May 1999",
"RESEARCH_COMMENT": "Descriptive detail or provenance or research analysis conclusion, ...",
"RESEARCH_PROJECT": "Tahiti Natives",
"ROLL": "176, or rolls 145-160",
"SCHEDULE": "population schedule or slave schedule or ...",
"SECTION": "1890 section or ER patients or ...",
"SERIES": "Carnival County Records",
"SERIES_NO": "series 34-38",
"SESSION": "2nd session",
"SHEET_NO": "sheet 13-C",
"SUBJECT": "D. Copernicus and close family",
"SUBSERIES": "",
"SUBTITLE": "Subtitle of article or magazine ...",
"TERM": "June Term 1934 or 13th Congress or Reagan Office or ...",
"TIMESTAMP": "min. 34-36",
"TITLE": "Diary Title, Message Title, Bible Name, Article Title, ...",
"TRANSLATION": "A translated version, typically of the title",
"TYPE": "Letter",
"URL_6DIGITAL_LOCATION9": "http://gramps-project.org/blog",
"VOLUME": "4",
"VOLUME_INFO": "5 volumes",
"WEBSITE": "gramps-project.org",
"WEBSITE_CREATOR_OR_OWNER": "Family Historians Inc",
"YEAR": "1888",
"YEAR_ACCESSED": "2013",
}
DEFAULT_TOOLTIPS = {
"ACT": "A statute or law name passed by a legislature",
"ADDRESS": "Store address information. Set Private if needed! Give"
" information from lowest to highest level separated by comma's",
"AFFILIATION": "A relevant affiliation that might influence data in the source",
"AUTHOR": "Give names in following form: 'FirstAuthorSurname, Given Names & SecondAuthorSurname, Given Names'."
" Like this Gramps can parse the name and shorten as needed.",
"AUTHOR_LOCATION": "City where author resides or wrote.",
"BOOK": "Title of the Book",
"CASE": "Dispute between opposing parties in a court of law.",
"CEMETERY": "Name of cemetery or cemetery office with sources.",
"CHAPTER": "",
"CHAPTER_PAGES": "The pages in the chapter.",
"COLLECTION": "",
"COLUMN": "",
"COMPILER": "The name of the person who compiled the source.",
"CREATION_DATE": "",
"CREATOR": "The name of the creator of the artifact.",
"CREDIT_LINE": "Acknowledgement of writers and contributors",
"DATE": "",
"DATE_ACCESSED": "",
"DATE_RANGE": "The range of years which are present in the source.",
"DESCRIPTION": "Some important detail of the source.",
"DISTRICT": "District as handled by Census",
"DIVISION": "The subdivision of a larger group that is handled in the source.",
"EDITION": "",
"EDITOR": "The Editor of a multi-author book.",
"FILE": "The title of a specific file in a source.",
"FILE_DATE": "Date of submitting the document to a clerk or court.",
"FILE_LOCATION": "Accession method to the file",
"FILE_NO": "Number to indicate a file",
"FILE_UNIT": "A grouping unit for a number of files in a source.",
"FILM_ID": "ID of a Microfilm.",
"FILM_PUBLICATION_PLACE": "",
"FILM_PUBLISHER": "",
"FILM_TYPE": "The type of the microfilm.",
"FORMAT": "The format of the source.",
"FRAME": "What frames in the source are relevant.",
"GROUP": "A larger grouping to which the source belongs.",
"HOUSEHOLD": "Household of interest on a census.",
"ID": "ID to identify the source or citation part",
"INSTITUTION": "Institution that issued the source.",
"INTERVIEWER": "",
"ISSUE_DATE": "Date the source was issued.",
"ISSUE_RANGE": "A range of magazine, journal, ... issues covered in the source",
"ITEM_OF_INTEREST": "Specific part, item, or person of interest in the source",
"JURISDICTION": "Area with a set of laws under the control of a system of courts or government entity."
" Enter this from lowest to highest relevant jurisdiction, separated by comma's.",
"LOCATION": "City that is relevant.",
"NUMBER": "A number.",
"NUMBER_6TOTAL9": "The maximum of entities available.",
"ORIGINAL_REPOSITORY": "Name of the repository where the original is stored.",
"ORIGINAL_REPOSITORY_LOCATION": "Address or only city of the repository where the original is stored.",
"ORIGINAL_YEAR": "Year the original source was published/created",
"PAGE": "The page or page(s) relevant for the citation",
"PAGE_RANGE": "The range of the pages in the source. The page given for"
" a citation must be in this range.",
"PART": "",
"PLACE_CREATED": "",
"POSITION": "Where in or on the source the citation piece can be found.",
"POSTING_DATE": "",
"PROFESSIONAL_CREDENTIALS": "",
"PROVENANCE": "Where the material originated from.",
"PUBLICATION_FORMAT": "",
"PUBLICATION_PLACE": "",
"PUBLICATION_TITLE": "",
"PUBLICATION_YEAR": "",
"PUBLISHER": "",
"PUB_INFO": "Publication Information, such as city and year of publication, name of publisher, ...",
"RECIPIENT": "The person to who the letter is addressed.",
"RELATIONSHIP": "The relationship of the author to the person of interest that is the subject.",
"REPORT_DATE": "Date the report was written/submitted.",
"RESEARCH_COMMENT": "Descriptive detail or provenance or research analysis conclusion, ...",
"RESEARCH_PROJECT": "The genealogical or scientific research project.",
"ROLL": "The Microfilm role.",
"SCHEDULE": "The census schedule (the type of census table) used, eg population schedule or slave schedule. or ...",
"SECTION": "The section or subgroup under which filed, eg 'Diplomatic correspondance, 1798-1810'",
"SERIES": "",
"SERIES_NO": "",
"SESSION": "The number of the meeting or series of connected meetings devoted "
"by a legislature to a single order of business, program, agenda, or announced purpose.",
"SHEET_NO": "Number of a census sheet.",
"SUBJECT": "",
"SUBSERIES": "",
"SUBTITLE": "",
"TERM": "Reference to the time a person/group/parliament is in office or session.",
"TIMESTAMP": "Indication of the time in audio or video where the relevant fragment can be found.",
"TITLE": "",
"TRANSLATION": "A translated version, typically of the title",
"TYPE": "",
"URL_6DIGITAL_LOCATION9": "Detailed internet address of the content",
"VOLUME": "",
"VOLUME_INFO": "Information about the volumes, eg the amount of volumes.",
"WEBSITE": "The main internet address.",
"WEBSITE_CREATOR_OR_OWNER": "Organization or person behind a website.",
"YEAR": "",
"YEAR_ACCESSED": "",
}
nr = -1
cat = ''
@ -63,12 +275,13 @@ ident = ''
TYPE2CITEMAP = {}
FIELDTYPEMAP = {}
FIELDS_SHORT = []
index = 100
indexval = 10
first = True
with open(csvfilename, 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
reader = csv.reader(csvfile, delimiter=';')
for row in reader:
if first:
#skip first row with headers
@ -77,35 +290,58 @@ with open(csvfilename, 'rb') as csvfile:
if row[CATCOL]:
cat = row[CATCOL].strip()
if cat.startswith('EE '):
cat = cat[3:]
EE = True
else:
EE = False
cattype = row[CATTYPECOL].strip()
types = row[TYPECOL].strip()
descr = row[DESCRCOL].strip()
source_type = row[IDENTCOL].strip()
if descr:
source_descr = '%s - %s - %s (%s)' % (cat, cattype, types, descr)
source_descr_code = "_('%(first)s - %(sec)s - %(third)s (%(fourth)s)') % { "\
if not EE:
source_descr_code = "_('%(first)s - %(sec)s - %(third)s (%(fourth)s)') % { "\
" 'first': _('" + cat + "'),"\
" 'sec': _('" + cattype + "'),"\
" 'third': _('" + types + "'),"\
" 'fourth': _('" + descr + "')}"
else:
source_descr_code = "_('EE %(first)s - %(sec)s - %(third)s (%(fourth)s)') % { "\
" 'first': _('" + cat + "'),"\
" 'sec': _('" + cattype + "'),"\
" 'third': _('" + types + "'),"\
" 'fourth': _('" + descr + "')}"
else:
source_descr = '%s - %s - %s' % (cat, cattype, types)
source_descr_code = "_('%(first)s - %(sec)s - %(third)s') % { "\
if not EE:
source_descr_code = "_('%(first)s - %(sec)s - %(third)s') % { "\
" 'first': _('" + cat + "'),"\
" 'sec': _('" + cattype + "'),"\
" 'third': _('" + types + "')}"
else:
source_descr_code = "_('EE %(first)s - %(sec)s - %(third)s') % { "\
" 'first': _('" + cat + "'),"\
" 'sec': _('" + cattype + "'),"\
" 'third': _('" + types + "')}"
if source_type in TYPE2CITEMAP:
assert TYPE2CITEMAP[source_type] ['descr'] == source_descr, source_type + ' ' + TYPE2CITEMAP[source_type] ['descr'] + ' NOT ' + source_descr
else:
TYPE2CITEMAP[source_type] = {'L': [], 'F': [], 'S': [],
TYPE2CITEMAP[source_type] = {'REF_TYPE_L': [], 'REF_TYPE_F': [],
'REF_TYPE_S': [],
'i': indexval, 'descr': source_descr,
'descrcode': source_descr_code}
indexval += 1
if row[CITETYPECOL]:
#new citation type,
#new citation type,
cite_type = row[CITETYPECOL].strip()
if cite_type == 'S':
shortcite = True
else:
shortcite = False
cite_type = CITE_TYPES[cite_type]
#add field for template to evidence style
field = row[FIELDCOL].strip()
field_type = field.replace(' ', '_').replace("'","")\
@ -114,8 +350,13 @@ with open(csvfilename, 'rb') as csvfile:
.replace(',', '').replace('.', '').replace(':', '')\
.replace('-', '_')
field_descr = field.replace('[', '').replace(']','').lower().capitalize()
field_label = row[LABELCOL].strip()
field_label = field_label.replace("'", "\\'")
if field_type in FIELDTYPEMAP:
assert field_descr == FIELDTYPEMAP[field_type][1], 'Problem %s %s %s' % (field_type, field_descr, FIELDTYPEMAP[field_type][1])
elif field_type in KNOWN_FIELDS:
#no need to add it
pass
else:
FIELDTYPEMAP[field_type] = (index, field_descr)
index += 1
@ -126,8 +367,25 @@ with open(csvfilename, 'rb') as csvfile:
optional = 'False'
if row[OPTCOL].strip():
optional = 'True'
shorteralg = SHORTERALG.get(row[SHORTERCOL].strip()) or 'EMPTY'
gedcommap = GEDCOMFIELDS.get(row[GEDCOMCOL].strip()) or 'EMPTY'
style = STYLES.get(row[STYLECOL].strip()) or 'EMPTY'
hint = row[HINTCOL]
tooltip = row[TOOLTIPCOL]
TYPE2CITEMAP[source_type][cite_type] += [(row[LDELCOL], field_type,
row[RDELCOL], row[STYLECOL], private, optional)]
row[RDELCOL], field_label, style, private, optional,
shorteralg, gedcommap, hint, tooltip)]
#if shorttype, we store a type for the short version so user can store
#this
if shortcite and shorteralg == 'EMPTY':
field_type_short = field_type + '_SHORT_VERSION'
if field_type_short in FIELDTYPEMAP or field_type_short in KNOWN_FIELDS:
pass
else:
FIELDTYPEMAP[field_type_short] = (index, field_descr + ' (Short)')
FIELDS_SHORT.append(field_type_short)
index += 1
#now generate the python code we need in source attr types
code = " #following fields are generated with evidencefieldgenerator.py\n" \
@ -138,8 +396,23 @@ for field_type in allkeys:
code += " " + field_type + ' = %d\n' % FIELDTYPEMAP[field_type][0]
datamap += ' (' + field_type + ', _("' + FIELDTYPEMAP[field_type][1] \
+'"), "' + FIELDTYPEMAP[field_type][1] + '"),\n'
code += "\n _DATAMAPIGNORE = [\n"
for field in FIELDS_SHORT:
code += " " + field + ',\n'
code += ' ]\n\n' + datamap + ' ]\n'
code += '\n' + datamap + ' ]\n'
#now add default hints
code += "\n _DEFAULT_HINTS = {\n"
for key in sorted(DEFAULT_HINTS.keys()):
if DEFAULT_HINTS[key]:
code += " " + key +': _("' + DEFAULT_HINTS[key] + '"),\n'
code += " }\n"
#now add default tooltips
code += "\n _DEFAULT_TOOLTIPS = {\n"
for key in sorted(DEFAULT_TOOLTIPS.keys()):
if DEFAULT_TOOLTIPS[key]:
code += " " + key + ': _("' + DEFAULT_TOOLTIPS[key] + '"),\n'
code += " }\n"
with open('srcattrtype_extra.py', 'wb') as srcattrfile:
srcattrfile.write(code)
@ -151,13 +424,14 @@ with open('srcattrtype_extra.py', 'wb') as srcattrfile:
#first an English to internationalized map
code = " #SRCTEMPLATE has some predefined values which map to citation styles\n"
datamap = " _SRCTEMPLATEVAL_MAP = [\n"
datamap = " _SRCTEMPLATEVAL_MAP = [\n"\
" (UNKNOWN, _('Unknown'), 'Unknown'),\n"
allkeys = sorted(TYPE2CITEMAP.keys())
for source_type in allkeys:
code += " " + source_type + ' = %d\n' % TYPE2CITEMAP[source_type]['i']
# we use descrcode in to translate string to reduce work for translators
datamap += ' (' + source_type + ', ' + TYPE2CITEMAP[source_type]['descrcode'] \
+', "' + TYPE2CITEMAP[source_type]['descr'] + '"),\n'
datamap += " (" + source_type + ", " + TYPE2CITEMAP[source_type]['descrcode'] \
+", '" + source_type+ "'),\n"
code += '\n # Localization of the different source types\n'\
+ datamap + ' ]\n'
@ -169,13 +443,24 @@ code += "\n #templates for the source types defined\n"\
code += ' EVIDENCETEMPLATES = {\n'
for source_type in allkeys:
code += " " + source_type + ": {\n"
for val in ['F', 'L', 'S']:
code += " '" + val + "': [\n"
for val in ['REF_TYPE_L', 'REF_TYPE_F', 'REF_TYPE_S']:
code += " " + val + ": [\n"
for field in TYPE2CITEMAP[source_type][val]:
# field is tuple (row[LDELCOL], field_type, row[RDELCOL], row[STYLECOL]
# , private, optional)
code += " ('"+ field[0] + "', " + field[1] + ", '" + field[2] + \
"', '" + field[3] + "', " + field[4] + ", " + field[5] + "),\n"
# field is tuple (row[LDELCOL], field_type, row[RDELCOL],
# field_label, row[STYLECOL]
# , private, optional, shorteralg, gedcommap, hint, tooltip)
if field[9]:
hint = '_("' + field[9] + '")'
else:
hint = 'None'
if field[10]:
tooltip = '_("' + field[10] + '")'
else:
tooltip = 'None'
code += " ('"+ field[0] + "', SrcAttributeType." + field[1] + ", _('"\
+field[3] + "'), '"+ field[2] + "', " + field[4] + ", " + field[5] + ", "\
+ field[6] + ", " + field[7] + ", " + field[8] + ",\n" \
+ " " +hint + ", " + tooltip + "),\n"
code += " ],\n"
code += " },\n"
code += " }\n"

View File

@ -0,0 +1,98 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
This module parses the evidence csv file and generates the code we need in
Gramps to use the evidence style.
"""
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
import csv
#-------------------------------------------------------------------------
#
# Code
#
#-------------------------------------------------------------------------
csvfilename = "evidence_style.csv"
NRCOL = 0
CATCOL = 1
CATTYPECOL = 2
TYPECOL = 3
DESCRCOL= 4
CITETYPECOL = 5
IDENTCOL = 6
LDELCOL = 7 # left delimiter
FIELDCOL = 8
LABELCOL = 9
RDELCOL = 10 # right delimiter
GEDCOMCOL = 11
SHORTERCOL = 12
STYLECOL = 13
PRIVACYCOL = 14
OPTCOL = 15
HINTCOL = 16
TOOLTIPCOL = 17
first = True
trans = {}
with open(csvfilename, 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=';')
for row in reader:
if first:
first=False
continue
elif row[CATCOL]:
cat = row[CATCOL].strip()
cattype = row[CATTYPECOL].strip()
types = row[TYPECOL].strip()
descr = row[DESCRCOL].strip()
for val in [cat, cattype, types, descr]:
if val and val not in trans:
trans[val] = '_("' + val + '")'
val = row[HINTCOL]
if val and val not in trans:
trans[val] = '_("' + val + '")'
val = row[TOOLTIPCOL]
if val and val not in trans:
trans[val] = '_("' + val + '")'
#now generate the python code we need in source attr types
code = "#following translations are generated with extract_trans_csv.py\n"
code += "if False:\n"
code += " #these translations will only occur when needed first time!\n"
allkeys = sorted(trans.keys())
for field in allkeys:
code += " " + trans[field] + '\n'
with open('csv_trans.py', 'wb') as srcattrfile:
srcattrfile.write(code)

View File

@ -229,7 +229,7 @@ SOURCES
-->
<!ELEMENT sources (source)*>
<!ELEMENT source (stitle?, sauthor?, spubinfo?, sabbrev?,
<!ELEMENT source (sname?, stemplate?, sabbrev?,
noteref*, objref*, srcattribute*, reporef*, tagref*)>
<!ATTLIST source
id CDATA #IMPLIED
@ -237,9 +237,8 @@ SOURCES
priv (0|1) #IMPLIED
change CDATA #REQUIRED
>
<!ELEMENT stitle (#PCDATA)>
<!ELEMENT sauthor (#PCDATA)>
<!ELEMENT spubinfo (#PCDATA)>
<!ELEMENT sname (#PCDATA)>
<!ELEMENT stemplate (#PCDATA)>
<!ELEMENT sabbrev (#PCDATA)>
<!-- ************************************************************
@ -368,7 +367,7 @@ CITATIONS
<!ELEMENT citations (citation)*>
<!ELEMENT citation ((daterange|datespan|dateval|datestr)?, page?, confidence?,
<!ELEMENT citation ((daterange|datespan|dateval|datestr)?, cname?, confidence?,
noteref*, objref*, srcattribute*, sourceref, tagref*)>
<!ATTLIST citation
id CDATA #IMPLIED
@ -376,6 +375,7 @@ CITATIONS
priv (0|1) #IMPLIED
change CDATA #REQUIRED
>
<!ELEMENT cname (#PCDATA)>
<!-- ************************************************************
BOOKMARKS

View File

@ -430,7 +430,7 @@
<define name="citation-content">
<ref name="primary-object"/>
<optional><ref name="date-content"/></optional>
<optional><element name="page"><text/></element></optional>
<optional><element name="cname"><text/></element></optional>
<optional><element name="confidence"><text/></element></optional>
<zeroOrMore><element name="noteref">
<ref name="noteref-content"/>
@ -448,9 +448,8 @@
<define name="source-content">
<ref name="primary-object"/>
<optional><element name="stitle"><text/></element></optional>
<optional><element name="sauthor"><text/></element></optional>
<optional><element name="spubinfo"><text/></element></optional>
<optional><element name="sname"><text/></element></optional>
<optional><element name="stemplate"><text/></element></optional>
<optional><element name="sabbrev"><text/></element></optional>
<zeroOrMore><element name="noteref">
<ref name="noteref-content"/>

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,14 @@ perform a translation on import, eg Gtk.
import platform
import sys
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import warnings
import functools
#-------------------------------------------------------------------------
#
# Platforms
@ -159,3 +167,33 @@ def mod_key():
return "<ctrl>"
return "<alt>"
#-------------------------------------------------------------------------
#
# DECORATORS
#
#-------------------------------------------------------------------------
def deprecated(func):
'''This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emitted
when the function is used.'''
@functools.wraps(func)
def new_func(*args, **kwargs):
if sys.version_info[0] <3:
warnings.warn_explicit(
"Call to deprecated function {}.".format(func.__name__),
category=DeprecationWarning,
filename=func.func_code.co_filename,
lineno=func.func_code.co_firstlineno + 1
)
else:
warnings.warn_explicit(
"Call to deprecated function {}.".format(func.__name__),
category=DeprecationWarning,
filename=func.__code__.co_filename,
lineno=func.__code__.co_firstlineno + 1
)
return func(*args, **kwargs)
return new_func

View File

@ -46,7 +46,7 @@ __all__ = (
('PERSON_KEY', 'FAMILY_KEY', 'SOURCE_KEY', 'CITATION_KEY',
'EVENT_KEY', 'MEDIA_KEY', 'PLACE_KEY', 'REPOSITORY_KEY',
'NOTE_KEY', 'REFERENCE_KEY', 'TAG_KEY'
'NOTE_KEY', 'REFERENCE_KEY', 'TAG_KEY', 'TEMPLATE_KEY'
) +
('TXNADD', 'TXNUPD', 'TXNDEL')
@ -87,5 +87,6 @@ REFERENCE_KEY = 7
NOTE_KEY = 8
TAG_KEY = 9
CITATION_KEY = 10
TEMPLATE_KEY = 11
TXNADD, TXNUPD, TXNDEL = 0, 1, 2

View File

@ -3,7 +3,7 @@
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2010 Nick Hall
# Copyright (C) 2011 Tim G L Lyons
# Copyright (C) 2011-2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -69,6 +69,7 @@ from ..lib.place import Place
from ..lib.repo import Repository
from ..lib.note import Note
from ..lib.tag import Tag
from ..lib.srctemplate import SrcTemplate
from ..lib.genderstats import GenderStats
from ..lib.researcher import Researcher
from ..lib.nameorigintype import NameOriginType
@ -93,7 +94,7 @@ from .dbconst import *
_SIGBASE = ('person', 'family', 'source', 'citation',
'event', 'media', 'place', 'repository',
'reference', 'note', 'tag')
'reference', 'note', 'tag', 'srctemplate')
DBERRS = (db.DBRunRecoveryError, db.DBAccessError,
db.DBPageNotFoundError, db.DBInvalidArgError)
@ -339,6 +340,14 @@ class DbBsddbRead(DbReadBase, Callback):
"cursor_func": self.get_tag_cursor,
"handles_func": self.get_tag_handles,
},
'SrcTemplate':
{
"handle_func": self.get_template_from_handle,
"gramps_id_func": None,
"class_func": SrcTemplate,
"cursor_func": self.get_template_cursor,
"handles_func": self.get_template_handles,
},
}
self.set_person_id_prefix('I%04d')
@ -394,6 +403,7 @@ class DbBsddbRead(DbReadBase, Callback):
self.nid_trans = {}
self.eid_trans = {}
self.tag_trans = {}
self.template_trans = {}
self.env = None
self.person_map = {}
self.family_map = {}
@ -404,6 +414,7 @@ class DbBsddbRead(DbReadBase, Callback):
self.note_map = {}
self.media_map = {}
self.event_map = {}
self.template_map = {}
self.metadata = {}
self.name_group = {}
self.undo_callback = None
@ -497,6 +508,9 @@ class DbBsddbRead(DbReadBase, Callback):
def get_tag_cursor(self, *args, **kwargs):
return self.get_cursor(self.tag_map, *args, **kwargs)
def get_template_cursor(self, *args, **kwargs):
return self.get_cursor(self.template_map, *args, **kwargs)
def close(self):
"""
Close the specified database.
@ -545,6 +559,7 @@ class DbBsddbRead(DbReadBase, Callback):
self.emit('repository-rebuild')
self.emit('note-rebuild')
self.emit('tag-rebuild')
self.emit('template-rebuild')
def __find_next_gramps_id(self, prefix, map_index, trans):
"""
@ -760,6 +775,14 @@ class DbBsddbRead(DbReadBase, Callback):
"""
return self.get_from_handle(handle, Tag, self.tag_map)
def get_template_from_handle(self, handle):
"""
Find a Tag in the database from the passed handle.
If no such Tag exists, None is returned.
"""
return self.get_from_handle(handle, SrcTemplate, self.template_map)
def __get_obj_from_gramps_id(self, val, tbl, class_, prim_tbl):
if isinstance(tbl, dict):
return None ## trying to get object too early
@ -968,6 +991,12 @@ class DbBsddbRead(DbReadBase, Callback):
"""
return self.get_number_of_records(self.tag_map)
def get_number_of_templates(self):
"""
Return the number of tags currently in the database.
"""
return self.get_number_of_records(self.template_map)
def all_handles(self, table):
""" return all the keys of a database table
CAREFUL: For speed the keys are directly returned, so on python3
@ -1137,6 +1166,24 @@ class DbBsddbRead(DbReadBase, Callback):
return handle_list
return []
def get_template_handles(self, sort_handles=False):
"""
Return a list of database handles, one handle for each Tag in
the database.
If sort_handles is True, the list is sorted by Tag name.
CAREFUL: For speed the keys are directly returned, so on python3
bytestrings are returned! Use constfunc.py handle2internal
on this result!
"""
if self.db_is_open:
handle_list = self.all_handles(self.template_map)
if sort_handles:
handle_list.sort(key=self.__sortbytemplate_key)
return handle_list
return []
def _f(curs_):
"""
Closure that returns an iterator over handles in the database.
@ -1159,6 +1206,7 @@ class DbBsddbRead(DbReadBase, Callback):
iter_repository_handles = _f(get_repository_cursor)
iter_note_handles = _f(get_note_cursor)
iter_tag_handles = _f(get_tag_cursor)
iter_template_handles = _f(get_template_cursor)
del _f
def _f(curs_, obj_):
@ -1185,6 +1233,7 @@ class DbBsddbRead(DbReadBase, Callback):
iter_repositories = _f(get_repository_cursor, Repository)
iter_notes = _f(get_note_cursor, Note)
iter_tags = _f(get_tag_cursor, Tag)
iter_templates = _f(get_template_cursor, SrcTemplate)
del _f
def get_gramps_ids(self, obj_key):
@ -1463,6 +1512,12 @@ class DbBsddbRead(DbReadBase, Callback):
return self.metadata.get(b'default')
return None
def get_GEDCOM_template_handle(self):
"""Return the handle of the GEDCOM template of the database."""
if self.metadata is not None:
return self.metadata.get(b'gedcom_template')
return None
def get_save_path(self):
"""Return the save path of the file, or "" if one does not exist."""
return self.path
@ -1627,6 +1682,9 @@ class DbBsddbRead(DbReadBase, Callback):
def get_raw_tag_data(self, handle):
return self.__get_raw_data(self.tag_map, handle)
def get_raw_template_data(self, handle):
return self.__get_raw_data(self.template_map, handle)
def __has_handle(self, table, handle):
"""
Helper function for has_<object>_handle methods
@ -1699,6 +1757,12 @@ class DbBsddbRead(DbReadBase, Callback):
"""
return self.__has_handle(self.tag_map, handle)
def has_template_handle(self, handle):
"""
Return True if the handle exists in the current Tag database.
"""
return self.__has_handle(self.template_map, handle)
def __sortbyperson_key(self, handle):
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
@ -1778,6 +1842,12 @@ class DbBsddbRead(DbReadBase, Callback):
tag = self.tag_map[key][1]
return glocale.sort_key(tag)
def __sortbytemplate_key(self, key):
if isinstance(key, UNITYPE):
key = key.encode('utf-8')
template = self.template_map[key][1]
return glocale.sort_key(template)
def set_mediapath(self, path):
"""Set the default media path for database, path should be utf-8."""
if (self.metadata is not None) and (not self.readonly):
@ -1789,6 +1859,11 @@ class DbBsddbRead(DbReadBase, Callback):
return self.metadata.get(b'mediapath', None)
return None
def set_GEDCOM_template_handle(self, handle):
"""Set the default GEDCOM template handle for database"""
if (self.metadata is not None) and (not self.readonly):
self.metadata[b'gedcom_template'] = handle
def find_backlink_handles(self, handle, include_classes=None):
"""
Find all objects that hold a reference to the object handle.
@ -1855,6 +1930,10 @@ class DbBsddbRead(DbReadBase, Callback):
'cursor_func': self.get_tag_cursor,
'class_func': Tag,
},
'Template': {
'cursor_func': self.get_template_cursor,
'class_func': SrcTemplate,
},
}
# Find which tables to iterate over

View File

@ -55,6 +55,9 @@ def gramps_upgrade_17(self):
1. This upgrade adds tags to event, place, repository, source and
citation objects.
2. Data of Source becomes SourceAttributes Secondary Object
3. Citation page is deprecated and becomes Citation name
Source title, author and pubinfo are deprecated. Now there is
Source template and name instead.
"""
length = (len(self.event_map) + len(self.place_map) +
len(self.repository_map) + len(self.source_map) +
@ -137,15 +140,47 @@ def gramps_upgrade_17(self):
self.update()
# -------------------------------------------------------
# Upgrade Source and Citation datamap to SrcAttributeBase
# 1. Upgrade Source and Citation datamap to SrcAttributeBase
# 2. Citation page is deprecated and becomes Citation name
# Source title, author and pubinfo are deprecated. Now there is
# Source template and name instead.
# -------------------------------------------------------
from ..lib.srcattrtype import SrcAttributeType
private = False
first = True
for handle in self.source_map.keys():
if first:
from gramps.plugins.srctemplates.gedcomtemplate import build_GEDCOM_template
template = build_GEDCOM_template()
if isinstance(template.handle, UNITYPE):
template.handle = template.handle.encode('utf-8')
teml_handle = template.handle
from gramps.gen.lib.srctemplate import SrcTemplate
template = SrcTemplate.serialize(template)
with BSDDBTxn(self.env, self.template_map) as txn:
txn.put(teml_handle, template)
with BSDDBTxn(self.env, self.metadata) as txn:
txn.put(b'gedcom_template', teml_handle)
first = False
source = self.source_map[handle]
(handle, gramps_id, title, author, pubinfo,
notelist, medialist, abbrev, change, datamap, reporef_list,
taglist, private) = source
srcattributelist = upgrade_datamap_17(datamap)
new_source = (handle, gramps_id, title, author, pubinfo,
if title:
the_type = (SrcAttributeType.CUSTOM, SrcAttributeType.TITLE)
srcattributelist.append((private, the_type, title))
if author:
the_type = (SrcAttributeType.CUSTOM, SrcAttributeType.AUTHOR)
srcattributelist.append((private, the_type, author))
if pubinfo:
the_type = (SrcAttributeType.CUSTOM, SrcAttributeType.PUB_INFO)
srcattributelist.append((private, the_type, pubinfo))
name = title
new_source = (handle, gramps_id, name, teml_handle,
notelist, medialist, abbrev, change, srcattributelist, reporef_list,
taglist, private)
with BSDDBTxn(self.env, self.source_map) as txn:
@ -159,14 +194,19 @@ def gramps_upgrade_17(self):
(handle, gramps_id, datelist, page, confidence, source_handle,
notelist, medialist, datamap, change, taglist, private) = citation
srcattributelist = upgrade_datamap_17(datamap)
new_citation = (handle, gramps_id, datelist, page, confidence, source_handle,
if page:
the_type = (SrcAttributeType.CUSTOM, SrcAttributeType.PAGE)
srcattributelist.append((private, the_type, page))
name = page
new_citation = (handle, gramps_id, datelist, name, confidence, source_handle,
notelist, medialist, srcattributelist, change, taglist, private)
with BSDDBTxn(self.env, self.citation_map) as txn:
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, new_citation)
self.update()
# Bump up database version. Separate transaction to save metadata.
with BSDDBTxn(self.env, self.metadata) as txn:
txn.put(b'version', 17)

View File

@ -3,7 +3,7 @@
#
# Copyright (C) 2000-2008 Donald N. Allingham
# Copyright (C) 2010 Nick Hall
# Copyright (C) 2011 Tim G L Lyons
# Copyright (C) 2011-2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -66,6 +66,7 @@ from ..lib.repo import Repository
from ..lib.mediaobj import MediaObject
from ..lib.note import Note
from ..lib.tag import Tag
from ..lib.srctemplate import SrcTemplate
from ..lib.genderstats import GenderStats
from ..lib.researcher import Researcher
@ -98,6 +99,7 @@ NIDTRANS = "note_id"
SIDTRANS = "source_id"
CIDTRANS = "citation_id"
TAGTRANS = "tag_name"
TEMPLATETRANS = "template_name"
SURNAMES = "surnames"
NAME_GROUP = "name_group"
META = "meta_data"
@ -112,6 +114,7 @@ PERSON_TBL = "person"
REPO_TBL = "repo"
NOTE_TBL = "note"
TAG_TBL = "tag"
TEMPLATE_TBL = "template"
REF_MAP = "reference_map"
REF_PRI = "primary_map"
@ -135,7 +138,9 @@ CLASS_TO_KEY_MAP = {Person.__name__: PERSON_KEY,
Place.__name__: PLACE_KEY,
Repository.__name__:REPOSITORY_KEY,
Note.__name__: NOTE_KEY,
Tag.__name__: TAG_KEY}
Tag.__name__: TAG_KEY,
SrcTemplate.__name__: TEMPLATE_KEY,
}
KEY_TO_CLASS_MAP = {PERSON_KEY: Person.__name__,
FAMILY_KEY: Family.__name__,
@ -146,7 +151,9 @@ KEY_TO_CLASS_MAP = {PERSON_KEY: Person.__name__,
PLACE_KEY: Place.__name__,
REPOSITORY_KEY: Repository.__name__,
NOTE_KEY: Note.__name__,
TAG_KEY: Tag.__name__}
TAG_KEY: Tag.__name__,
TEMPLATE_KEY: SrcTemplate.__name__,
}
KEY_TO_NAME_MAP = {PERSON_KEY: 'person',
FAMILY_KEY: 'family',
@ -158,7 +165,9 @@ KEY_TO_NAME_MAP = {PERSON_KEY: 'person',
REPOSITORY_KEY: 'repository',
#REFERENCE_KEY: 'reference',
NOTE_KEY: 'note',
TAG_KEY: 'tag'}
TAG_KEY: 'tag',
TEMPLATE_KEY: 'template',
}
#-------------------------------------------------------------------------
#
# Helper functions
@ -237,7 +246,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
__signals__ = dict((obj+'-'+op, signal)
for obj in
['person', 'family', 'event', 'place',
'source', 'citation', 'media', 'note', 'repository', 'tag']
'source', 'citation', 'media', 'note', 'repository', 'tag',
'template']
for op, signal in zip(
['add', 'update', 'delete', 'rebuild'],
[(list,), (list,), (list,), None]
@ -271,6 +281,9 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.brief_name = None
self.update_env_version = False
self.update_python_version = False
# Whether SrcTemplates need to be loaded. They need to be loaded on
# creating a new database, and on upgrade from schema version 16 to 17.
self.load_templates = False
def catch_db_error(func):
"""
@ -392,6 +405,17 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
txn.put(b'default', None)
return None
@catch_db_error
def set_GEDCOM_template_handle(self, handle):
"""Set the handle of the GEDCOM template to the passed instance."""
#we store a byte string!
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
if not self.readonly:
# Start transaction
with BSDDBTxn(self.env, self.metadata) as txn:
txn.put(b'gedcom_template', handle)
def set_mediapath(self, path):
"""Set the default media path for database, path should be utf-8."""
if self.metadata and not self.readonly:
@ -555,7 +579,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
# See if we lack write access to any files in the directory
for base in [FAMILY_TBL, PLACES_TBL, SOURCES_TBL, CITATIONS_TBL,
MEDIA_TBL, EVENTS_TBL, PERSON_TBL, REPO_TBL,
NOTE_TBL, REF_MAP, META]:
NOTE_TBL, TEMPLATE_TBL, REF_MAP, META]:
path = os.path.join(name, base + DBEXT)
if os.path.isfile(path) and not os.access(path, os.W_OK):
return True
@ -651,6 +675,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.__load_metadata()
gstats = self.metadata.get(b'gender_stats', default=None)
self.load_templates = False
# Ensure version info in metadata
if not self.readonly:
@ -660,6 +685,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
# New database. Set up the current version.
#self.metadata.put(b'version', _DBVERSION, txn=the_txn)
txn.put(b'version', _DBVERSION)
self.load_templates = True
elif b'version' not in self.metadata:
# Not new database, but the version is missing.
# Use 0, but it is likely to fail anyway.
@ -679,6 +705,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
("repository_map", REPO_TBL, db.DB_HASH),
("note_map", NOTE_TBL, db.DB_HASH),
("tag_map", TAG_TBL, db.DB_HASH),
("template_map", TEMPLATE_TBL, db.DB_HASH),
("reference_map", REF_MAP, db.DB_BTREE),
]
@ -747,6 +774,12 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.__open_undodb()
self.db_is_open = True
if self.load_templates:
# FIXME gstat is used as a proxy to say whether the database is new
# or not, This is not a very clean approach
from gramps.plugins.srctemplates.importcsv import load_srctemplates_data
load_srctemplates_data(self)
if callback:
callback(87)
@ -861,6 +894,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
("rid_trans", RIDTRANS, db.DB_HASH, 0),
("nid_trans", NIDTRANS, db.DB_HASH, 0),
("tag_trans", TAGTRANS, db.DB_HASH, 0),
("template_trans", TEMPLATETRANS, db.DB_HASH, 0),
("reference_map_primary_map", REF_PRI, db.DB_BTREE, 0),
("reference_map_referenced_map", REF_REF, db.DB_BTREE, db.DB_DUPSORT),
]
@ -884,6 +918,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
(self.repository_map, self.rid_trans, find_idmap),
(self.note_map, self.nid_trans, find_idmap),
(self.tag_map, self.tag_trans, find_idmap),
(self.template_map, self.template_trans, find_idmap),
(self.reference_map, self.reference_map_primary_map,
find_primary_handle),
(self.reference_map, self.reference_map_referenced_map,
@ -925,6 +960,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
( self.nid_trans, NIDTRANS ),
( self.cid_trans, CIDTRANS ),
( self.tag_trans, TAGTRANS ),
( self.template_trans, TEMPLATETRANS ),
( self.reference_map_primary_map, REF_PRI),
( self.reference_map_referenced_map, REF_REF),
]
@ -1197,6 +1233,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
(self.get_repository_cursor, Repository),
(self.get_note_cursor, Note),
(self.get_tag_cursor, Tag),
(self.get_template_cursor, SrcTemplate),
)
# Now we use the functions and classes defined above
@ -1304,6 +1341,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.cid_trans.close()
self.pid_trans.close()
self.tag_trans.close()
self.template_trans.close()
self.reference_map_primary_map.close()
self.reference_map_referenced_map.close()
self.reference_map.close()
@ -1321,6 +1359,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.media_map.close()
self.event_map.close()
self.tag_map.close()
self.template_map.close()
self.env.close()
self.__close_undodb()
@ -1334,6 +1373,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.media_map = None
self.event_map = None
self.tag_map = None
self.template_map = None
self.surnames = None
self.env = None
self.metadata = None
@ -1352,6 +1392,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.media_map = None
self.event_map = None
self.tag_map = None
self.template_map = None
self.reference_map_primary_map = None
self.reference_map_referenced_map = None
self.reference_map = None
@ -1503,6 +1544,13 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
"""
return self.__add_object(obj, transaction, None, self.commit_tag)
def add_template(self, obj, transaction):
"""
Add a Template to the database, assigning a handle if it has not already
been defined.
"""
return self.__add_object(obj, transaction, None, self.commit_template)
def __do_remove(self, handle, transaction, data_map, key):
if self.readonly or not handle:
return
@ -1617,6 +1665,14 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.__do_remove(handle, transaction, self.tag_map,
TAG_KEY)
def remove_template(self, handle, transaction):
"""
Remove the Template specified by the database handle from the
database, preserving the change in the passed transaction.
"""
self.__do_remove(handle, transaction, self.template_map,
TEMPLATE_KEY)
@catch_db_error
def set_name_group_mapping(self, name, group):
if not self.readonly:
@ -1945,6 +2001,14 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.commit_base(tag, self.tag_map, TAG_KEY,
transaction, change_time)
def commit_template(self, tag, transaction, change_time=None):
"""
Commit the specified Template to the database, storing the changes as part
of the transaction.
"""
self.commit_base(tag, self.template_map, TEMPLATE_KEY,
transaction, change_time)
def get_from_handle(self, handle, class_type, data_map):
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
@ -2155,6 +2219,10 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
upgrade.gramps_upgrade_16(self)
if version < 17:
upgrade.gramps_upgrade_17(self)
# On upgrade from 16 to 17, SrcTemplate is added, so the templates
# need to be loaded. In the future, on upgrade from 17, the
# templates will already be present and will not need to be loaded
self.load_templates = True
self.reset()
self.set_total(6)

View File

@ -48,7 +48,7 @@ class HasCitationBase(Rule):
First parameter is [Volume/page, Date, Confidence]
"""
labels = [ _('Volume/Page:'),
labels = [ _('Name:'),
_('Date:'),
_('Confidence:') ]
name = _('Citations matching parameters')
@ -72,7 +72,7 @@ class HasCitationBase(Rule):
return False
def _apply(self, db, citation):
if not self.match_substring(0, citation.get_page()):
if not self.match_substring(0, citation.get_name()):
return False
if self.date:

View File

@ -35,6 +35,8 @@ _ = glocale.translation.gettext
#
#-------------------------------------------------------------------------
from . import Rule
from gramps.gen.utils.citeref import (get_gedcom_title, get_gedcom_author,
get_gedcom_pubinfo)
#-------------------------------------------------------------------------
#
@ -55,16 +57,16 @@ class HasSourceBase(Rule):
allow_regex = True
def apply(self,db,source):
if not self.match_substring(0,source.get_title()):
if not self.match_substring(0, get_gedcom_title(db, source)):
return False
if not self.match_substring(1,source.get_author()):
if not self.match_substring(1, get_gedcom_author(db, source)):
return False
if not self.match_substring(2,source.get_abbreviation()):
return False
if not self.match_substring(3,source.get_publication_info()):
if not self.match_substring(3, get_gedcom_pubinfo(db, source)):
return False
return True

View File

@ -37,11 +37,13 @@ from ._hasnotematchingsubstringof import HasNoteMatchingSubstringOf
from ._hasnoteregexp import HasNoteRegexp
from ._hasreferencecountof import HasReferenceCountOf
from ._hassource import HasSource
from ._hassourceidof import HasSourceIdOf
from ._matchesfilter import MatchesFilter
from ._matchespagesubstringof import MatchesPageSubstringOf
from ._matchesrepositoryfilter import MatchesRepositoryFilter
from ._matchessourcefilter import MatchesSourceFilter
from ._regexpidof import RegExpIdOf
from ._regexpsourceidof import RegExpSourceIdOf
from ._hastag import HasTag
editor_rule_list = [
@ -56,10 +58,12 @@ editor_rule_list = [
HasNoteRegexp,
HasReferenceCountOf,
HasSource,
HasSourceIdOf,
MatchesFilter,
MatchesPageSubstringOf,
MatchesRepositoryFilter,
MatchesSourceFilter,
RegExpIdOf,
RegExpSourceIdOf,
HasTag
]

View File

@ -47,7 +47,7 @@ from ....datehandler import parser
class HasCitation(Rule):
"""Rule that checks for a citations with a particular value"""
labels = [ _('Volume/Page:'),
labels = [ _('Name:'),
_('Date:'),
_('Confidence level:')]
name = _('Citations matching parameters')
@ -64,7 +64,7 @@ class HasCitation(Rule):
pass
def apply(self, dbase, citation):
if not self.match_substring(0, citation.get_page()):
if not self.match_substring(0, citation.get_name()):
return False
if self.date:

View File

@ -0,0 +1,58 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2002-2006 Donald N. Allingham
# Copyright (C) 2011-2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
from ....const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from .._hasgrampsid import HasGrampsId
#-------------------------------------------------------------------------
#
# HasSourceIdOf
#
#-------------------------------------------------------------------------
class HasSourceIdOf(HasGrampsId):
"""Rule that checks for a citation with a source which has a specific
GRAMPS ID"""
name = _('Citation with Source <Id>')
description = _("Matches a citation with a source with a specified Gramps "
"ID")
category = _('Source filters')
def apply(self, dbase, citation):
source = dbase.get_source_from_handle(
citation.get_reference_handle())
if HasGrampsId.apply(self, dbase, source):
return True
return False

View File

@ -42,14 +42,14 @@ class MatchesPageSubstringOf(Rule):
"""Citation Volume/Page title containing <substring>"""
labels = [ _('Substring:')]
name = _('Citation Volume/Page containing <substring>')
description = _("Matches citations whose Volume/Page contains a "
name = _('Citation Name containing <substring>')
description = _("Matches citations whose Name contains a "
"certain substring")
category = _('General filters')
def apply(self, db, object):
""" Apply the filter """
title = object.get_page()
title = object.get_name()
if title.upper().find(self.list[0].upper()) != -1:
return True
return False

View File

@ -0,0 +1,60 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2002-2006 Donald N. Allingham
# Copyright (C) 2011 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
from ....const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from .._regexpidbase import RegExpIdBase
#-------------------------------------------------------------------------
#
# HasIdOf
#
#-------------------------------------------------------------------------
class RegExpSourceIdOf(RegExpIdBase):
"""
Rule that checks for a citation whose GRAMPS ID
matches regular expression.
"""
name = _('Citations with Source Id containing <text>')
description = _("Matches citations whose source has a Gramps ID that "
"matches the regular expression")
category = _('Source filters')
def apply(self, dbase, citation):
source = dbase.get_source_from_handle(
citation.get_reference_handle())
if RegExpIdBase.apply(self, dbase, source):
return True
return False

View File

@ -2,7 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2011 Tim G L Lyons
# Copyright (C) 2011-2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -57,6 +57,7 @@ from .citation import Citation
# Table objects
from .tag import Tag
from .srctemplate import SrcTemplate
# These are actually metadata
from .genderstats import GenderStats
@ -78,6 +79,7 @@ from .markertype import MarkerType
from .nameorigintype import NameOriginType
from .notetype import NoteType
from .styledtexttagtype import StyledTextTagType
from .templateelement import TemplateElement
# Text
from .styledtexttag import StyledTextTag

View File

@ -31,7 +31,6 @@ AttributeBase class for GRAMPS.
#
#-------------------------------------------------------------------------
from .attribute import Attribute
from .srcattribute import SrcAttribute
from .const import IDENTICAL, EQUAL
from ..constfunc import STRTYPE
@ -167,7 +166,3 @@ class AttributeRootBase(object):
class AttributeBase(AttributeRootBase):
_CLASS = Attribute
class SrcAttributeBase(AttributeRootBase):
_CLASS = SrcAttribute

View File

@ -3,7 +3,7 @@
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2010 Michiel D. Nauta
# Copyright (C) 2011 Tim G L Lyons
# Copyright (C) 2011-2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -44,8 +44,9 @@ from .mediabase import MediaBase
from .notebase import NoteBase
from .datebase import DateBase
from .tagbase import TagBase
from .attrbase import SrcAttributeBase
from ..constfunc import cuni
from .srcattrbase import SrcAttributeBase
from .srctemplate import SrcTemplate
from ..constfunc import cuni, deprecated
from .handle import Handle
#-------------------------------------------------------------------------
@ -75,7 +76,7 @@ class Citation(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject, DateBase):
NoteBase.__init__(self) # 6
DateBase.__init__(self) # 2
self.source_handle = None # 5
self.page = "" # 3
self.name = "" # 3
self.confidence = Citation.CONF_NORMAL # 4
SrcAttributeBase.__init__(self) # 8
@ -86,7 +87,7 @@ class Citation(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject, DateBase):
return (self.handle, # 0
self.gramps_id, # 1
DateBase.serialize(self, no_text_date),# 2
cuni(self.page), # 3
cuni(self.name), # 3
self.confidence, # 4
self.source_handle, # 5
NoteBase.serialize(self), # 6
@ -119,7 +120,7 @@ class Citation(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject, DateBase):
return {"handle": Handle("Citation", self.handle), # 0
"gramps_id": self.gramps_id, # 1
"date": DateBase.to_struct(self), # 2
"page": cuni(self.page), # 3
"name": cuni(self.name), # 3
"confidence": self.confidence, # 4
"source_handle": Handle("Source", self.source_handle), # 5
"note_list": NoteBase.to_struct(self), # 6
@ -137,7 +138,7 @@ class Citation(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject, DateBase):
(self.handle, # 0
self.gramps_id, # 1
date, # 2
self.page, # 3
self.name, # 3
self.confidence, # 4
self.source_handle, # 5
note_list, # 6
@ -283,17 +284,47 @@ class Citation(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject, DateBase):
def get_confidence_level(self):
"""Return the confidence level."""
return self.confidence
def set_page(self, page):
"""Set the page indicator of the Citation."""
self.page = page
def get_page(self):
"""Get the page indicator of the Citation."""
return self.page
def set_name(self, name):
"""
Set a descriptive name for the Citation object, which will be used in
Gramps for sorting, identification.
Typically, this value is set automatically based on the template of the
Source of this Citation, but is user changeable if needed.
:param name: a descriptive name to assign to the Citation
:type name: str
"""
self.name = name
def get_name(self):
"""
Return the descriptive name of the citation
:returns: Returns the descriptive name of the Citation
:rtype: str
"""
return self.name
def set_reference_handle(self, val):
self.source_handle = val
def get_reference_handle(self):
return self.source_handle
#-------------------------------------------------------------------------
#
# GEDCOM interface
#
#-------------------------------------------------------------------------
@deprecated
def get_page(self):
"""Get the page indicator of the Citation.
This method is deprecated. the citation name is returned as fallback.
Convert to get_name, or use the source template to construct citation
reference information
"""
return self.get_name()

View File

@ -35,10 +35,10 @@ from .primaryobj import PrimaryObject
from .mediabase import MediaBase
from .notebase import NoteBase
from .tagbase import TagBase
from .attrbase import SrcAttributeBase
from .srcattrbase import SrcAttributeBase
from .reporef import RepoRef
from .const import DIFFERENT, EQUAL, IDENTICAL
from ..constfunc import cuni
from ..constfunc import cuni, deprecated
from .handle import Handle
#-------------------------------------------------------------------------
@ -55,9 +55,8 @@ class Source(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject):
MediaBase.__init__(self)
NoteBase.__init__(self)
SrcAttributeBase.__init__(self)
self.title = ""
self.author = ""
self.pubinfo = ""
self.name = ""
self.template = None
self.abbrev = ""
self.reporef_list = []
@ -67,17 +66,16 @@ class Source(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject):
"""
return (self.handle, # 0
self.gramps_id, # 1
cuni(self.title), # 2
cuni(self.author), # 3
cuni(self.pubinfo), # 4
NoteBase.serialize(self), # 5
MediaBase.serialize(self), # 6
cuni(self.abbrev), # 7
self.change, # 8
SrcAttributeBase.serialize(self), # 9
[rr.serialize() for rr in self.reporef_list], # 10
TagBase.serialize(self), # 11
self.private) # 12
cuni(self.name), # 2
self.template, # 3
NoteBase.serialize(self), # 4
MediaBase.serialize(self), # 5
cuni(self.abbrev), # 6
self.change, # 7
SrcAttributeBase.serialize(self), # 8
[rr.serialize() for rr in self.reporef_list], # 9
TagBase.serialize(self), # 10
self.private) # 11
def to_struct(self):
"""
@ -101,9 +99,8 @@ class Source(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject):
"""
return {"handle": Handle("Source", self.handle),
"gramps_id": self.gramps_id,
"title": cuni(self.title),
"author": cuni(self.author),
"pubinfo": cuni(self.pubinfo),
"name": cuni(self.name),
"template": cuni(self.template),
"note_list": NoteBase.to_struct(self),
"media_list": MediaBase.to_struct(self),
"abbrev": cuni(self.abbrev),
@ -120,17 +117,16 @@ class Source(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject):
"""
(self.handle, # 0
self.gramps_id, # 1
self.title, # 2
self.author, # 3
self.pubinfo, # 4
note_list, # 5
media_list, # 6
self.abbrev, # 7
self.change, # 8
srcattr_list, # 9
reporef_list, # 10
tag_list, # 11
self.private # 12
self.name, # 2
self.template, # 3
note_list, # 4
media_list, # 5
self.abbrev, # 6
self.change, # 7
srcattr_list, # 8
reporef_list, # 9
tag_list, # 10
self.private # 11
) = data
NoteBase.unserialize(self, note_list)
@ -263,46 +259,61 @@ class Source(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject):
self._merge_attribute_list(acquisition)
self._merge_reporef_list(acquisition)
def set_title(self, title):
def set_template(self, template):
"""
Set the descriptive title of the Source object.
:param title: descriptive title to assign to the Source
:type title: str
Set the template type of the Source object. This defines a number of
preset SrcAttributes to be filled in by the user
:param template: a template code as defined in SrcTemplate
:type template: str
"""
self.title = title
self.template = template
def get_title(self):
"""
Return the descriptive title of the Place object.
:returns: Returns the descriptive title of the Place
def get_template(self):
"""Return the template type of the Source
:returns: Returns the code of the SrcTemplate set for this Source
:rtype: str
"""
return self.title
return self.template
def set_author(self, author):
"""Set the author of the Source."""
self.author = author
def set_name(self, name):
"""
Set a descriptive name for the Source object, which will be used in
Gramps for sorting, identification.
Typically, this value is set automatically based on the template, but
is user changeable if needed.
:param name: a descriptive name to assign to the Source
:type name: str
"""
self.name = name
def get_author(self):
"""Return the author of the Source."""
return self.author
def get_name(self):
"""
Return the descriptive name of the source
def set_publication_info(self, text):
"""Set the publication information of the Source."""
self.pubinfo = text
def get_publication_info(self):
"""Return the publication information of the Source."""
return self.pubinfo
:returns: Returns the descriptive name of the source
:rtype: str
"""
return self.name
def set_abbreviation(self, abbrev):
"""Set the title abbreviation of the Source."""
"""Set the title abbreviation of the Source used for LOCAL
sorting or filing.
:param abbrev: Short form used to retrieve Source locally
:type abbrev: str
"""
self.abbrev = abbrev
def get_abbreviation(self):
"""Return the title abbreviation of the Source."""
"""Return the title abbreviation of the Source used for LOCAL
sorting or filing.
:returns: Short form used to retrieve Source locally
:rtype: str
"""
return self.abbrev
def add_repo_reference(self, repo_ref):
@ -406,3 +417,24 @@ class Source(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject):
new_ref.merge(repo_ref)
self.reporef_list.pop(idx)
refs_list.pop(idx)
#-------------------------------------------------------------------------
#
# GEDCOM interface
#
#-------------------------------------------------------------------------
@deprecated
def get_title(self):
return "title not available"
# return self.get_gedcom_title()
@deprecated
def get_author(self):
return "author not available"
# return self.get_gedcom_author()
@deprecated
def get_publication_info(self):
return "pubinfo not available"
# return self.get_gedcom_publication_info()

View File

@ -0,0 +1,46 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
SrcAttributeBase class for GRAMPS.
"""
from __future__ import print_function
from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from .attrbase import AttributeRootBase
from .srcattribute import SrcAttribute
#-------------------------------------------------------------------------
#
# SrcAttributeBase class
#
#-------------------------------------------------------------------------
class SrcAttributeBase(AttributeRootBase):
_CLASS = SrcAttribute

View File

@ -3,6 +3,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -39,36 +40,6 @@ _ = glocale.translation.gettext
#-------------------------------------------------------------------------
from .grampstype import GrampsType
#-------------------------------------------------------------------------
#
# Template constants
#
#-------------------------------------------------------------------------
REF_TYPE_F = 1 # Full footnote citation to a source
REF_TYPE_S = 2 # Short footnote citation to a source
REF_TYPE_L = 3 # Listed reference of the source (no citation info)
EMPTY = 0
# template to GEDCOM field mapping for L reference fields
GED_AUTHOR = 1
GED_TITLE = 2
GED_PUBINF = 3
# template to GEDCOM field mapping for Date in F reference fields
GED_DATE = 4
# template to a shortening algorithm mapping for predefined algorithms
SHORTERALG_LOC = 1 # reduce a location to a shorter format (typically city level)
SHORTERALG_YEAR = 2 # reduce a date to only the year part
SHORTERALG_ETAL = 3 # reduce an author list to "first author et al."
SHORTERALG_REVERT_TO_DOT = 4 # change a list of first, second, third to
# a list third. second. first.
# template to a style mapping
STYLE_QUOTE = 1 # add quotes around the field
STYLE_QUOTECONT = 2 # add quotes around this field combined with other
# QUOTECONT fields around it
STYLE_EMPH = 3 # emphasize field
STYLE_BOLD = 4 # make field bold
#-------------------------------------------------------------------------
#
# Classes
@ -87,563 +58,124 @@ class SrcAttributeType(GrampsType):
# PREDEFINED TYPES
UNKNOWN = -1
CUSTOM = 0
SRCTEMPLATE = 1
# GEDCOM support
EVEN_REC = 2
EVEN_CITED = 3
EVEN_ROLE = 4
GEN_BY = 5
# Special fields which double existing database
# 1. repository fields
REPOSITORY = 10
REPOSITORY_ADDRESS = 11
REPOSITORY_SHORT_VERSION = 12
REPOSITORY_CALL_NUMBER = 13
# 2. existing class attributes
DATE = 14
_CUSTOM = CUSTOM
_DEFAULT = SRCTEMPLATE
_DATAMAP = [
(UNKNOWN , _("Unknown"), "Unknown"),
(CUSTOM , _("Custom"), "Custom"),
# required attribute to use for Elizabeth Shown Mills citation defs
(SRCTEMPLATE , _("Source Template"), "Source Template"),
# GEDCOM support
(EVEN_REC , _("Events Recorded in Source"), "Events Recorded in Source"), # GEDCOM EVENTS_RECORDED
(EVEN_CITED , _("Event Type Used for Citation"), "Event Type Used for Citation"), # GEDCOM EVENT_TYPE_CITED_FROM
(EVEN_ROLE , _("Role in Event Cited from"), "Role in Event Cited from"), # GEDCOM ROLE_IN_EVENT
(GEN_BY , _("Generated by"), "Generated by"), # Generated sources on import
(REPOSITORY, _("Repository"), "Repository"),
(REPOSITORY_ADDRESS, _("Repository Address"), "Repository Address"),
(REPOSITORY_SHORT_VERSION, _("Repository (Short)"), "Repository (Short)"),
(REPOSITORY_CALL_NUMBER, _("Repository Call Number"), "Repository Call Number"),
(DATE, _("Date"), "Date"),
# possible fields for evidence styles need to be added next
]
]
#following fields are generated with evidencefieldgenerator.py
#the index starts at 100!
ACT = 226
ACT_SHORT_VERSION = 227
ADDRESS = 155
AFFILIATION = 160
AUTHOR = 100
AUTHOR_LOCATION = 170
AUTHOR_SHORT_VERSION = 107
BOOK = 203
BOOK_SHORT_VERSION = 204
CASE = 198
CASE_SHORT_VERSION = 200
CEMETERY = 176
CEMETERY_SHORT_VERSION = 178
CHAPTER = 228
CHAPTER_PAGES = 217
COLLECTION = 104
COLLECTION_SHORT_VERSION = 109
COLUMN = 235
COLUMN_SHORT_VERSION = 236
COMPILER = 163
COMPILER_SHORT_VERSION = 194
CREATION_DATE = 103
CREATION_DATE_SHORT_VERSION = 141
CREATOR = 190
CREATOR_SHORT_VERSION = 213
CREDIT_LINE = 116
DATE_ACCESSED = 114
DATE_RANGE = 133
DATE_SHORT_VERSION = 156
DESCRIPTION = 139
DISTRICT = 188
DISTRICT_SHORT_VERSION = 189
DIVISION = 182
DIVISION_SHORT_VERSION = 186
EDITION = 221
EDITOR = 216
EDITOR_SHORT_VERSION = 218
FILE = 129
FILE_DATE = 206
FILE_DATE_SHORT_VERSION = 207
FILE_LOCATION = 166
FILE_NO = 128
FILE_NO_SHORT_VERSION = 199
FILE_SHORT_VERSION = 152
FILE_UNIT = 143
FILE_UNIT_SHORT_VERSION = 179
FILM_ID = 191
FILM_PUBLICATION_PLACE = 223
FILM_PUBLISHER = 224
FILM_TYPE = 147
FORMAT = 159
FRAME = 205
GROUP = 167
GROUP_SHORT_VERSION = 174
HOUSEHOLD = 183
HOUSEHOLD_SHORT_VERSION = 187
ID = 127
ID_SHORT_VERSION = 131
INSTITUTION = 173
INSTITUTION_SHORT_VERSION = 175
INTERVIEWER = 158
ISSUE_DATE = 231
ISSUE_DATE_SHORT_VERSION = 238
ISSUE_RANGE = 234
ITEM_OF_INTEREST = 119
ITEM_OF_INTEREST_SHORT_VERSION = 150
JURISDICTION = 180
JURISDICTION_SHORT_VERSION = 184
LOCATION = 157
LOCATION_SHORT_VERSION = 195
NUMBER = 105
NUMBER_6TOTAL9 = 144
NUMBER_SHORT_VERSION = 120
ORIGINAL_REPOSITORY = 145
ORIGINAL_REPOSITORY_LOCATION = 146
ORIGINAL_YEAR = 220
PAGE = 115
PAGE_RANGE = 232
PAGE_SHORT_VERSION = 118
PART = 225
PLACE_CREATED = 154
POSITION = 177
POSITION_SHORT_VERSION = 233
POSTING_DATE = 237
PROFESSIONAL_CREDENTIALS = 142
PROVENANCE = 164
PUBLICATION_FORMAT = 209
PUBLICATION_PLACE = 134
PUBLICATION_TITLE = 208
PUBLICATION_TITLE_SHORT_VERSION = 214
PUBLICATION_YEAR = 136
PUBLICATION_YEAR_SHORT_VERSION = 197
PUBLISHER = 135
PUB_INFO = 239
RECIPIENT = 126
RECIPIENT_SHORT_VERSION = 130
RELATIONSHIP = 165
REPORT_DATE = 162
REPORT_DATE_SHORT_VERSION = 171
RESEARCH_COMMENT = 106
RESEARCH_COMMENT_SHORT_VERSION = 137
RESEARCH_PROJECT = 161
ROLL = 151
ROLL_SHORT_VERSION = 196
SCHEDULE = 181
SCHEDULE_SHORT_VERSION = 185
SECTION = 148
SECTION_SHORT_VERSION = 149
SERIES = 122
SERIES_NO = 121
SERIES_NO_SHORT_VERSION = 124
SERIES_SHORT_VERSION = 132
SESSION = 229
SESSION_SHORT_VERSION = 230
SHEET_NO = 192
SHEET_NO_SHORT_VERSION = 193
SUBJECT = 138
SUBJECT_SHORT_VERSION = 140
SUBSERIES = 168
SUBSERIES_SHORT_VERSION = 169
SUBTITLE = 215
TERM = 201
TERM_SHORT_VERSION = 202
TIMESTAMP = 210
TIMESTAMP_SHORT_VERSION = 211
TITLE = 101
TITLE_SHORT_VERSION = 108
TRANSLATION = 222
TYPE = 102
TYPE_SHORT_VERSION = 153
URL_6DIGITAL_LOCATION9 = 112
VOLUME = 123
VOLUME_INFO = 219
VOLUME_SHORT_VERSION = 125
WEBSITE = 111
WEBSITE_CREATOR_OR_OWNER = 110
WEBSITE_SHORT_VERSION = 117
YEAR = 113
YEAR_ACCESSED = 172
YEAR_SHORT_VERSION = 212
# All the SrcAttributeTypes are specified as CUSTOM attributes. This is to
# allow users complete control over the attributes that are present so they
# need only have exactly those attributes that they want. Other attributes
# are only defined in source/citation templates.
# N.B. The attribute values are specified as strings, rather than the
# integers that would be normal for normal pre-defined attributes
# Some attributes are used internally in core Gramps and so are defined
# here.
# The following attributes are used in GEDCOM import and upgrade of
# databases from Gramps versions prior to 4.1 (including xml import). If no
# GEDCOM files are imported, they don't need to be defined.
TITLE = "Title"
AUTHOR = "Author"
PUB_INFO = "Pub_info"
PAGE = "Page"
# The following are used in GEDCOM import and export
EVEN_CITED = "Event Type Used for Citation" # GEDCOM EVENT_TYPE_CITED_FROM
EVEN_ROLE = "Role in Event Cited from" # GEDCOM ROLE_IN_EVENT
# The following is used in GEDCOM import only
GEN_BY = "Generated by" # Generated sources on import
# The following probably should be used in GEDCOM import and export, but
# don't appear there yet
EVEN_REC = "Events Recorded in Source" # GEDCOM EVENTS_RECORDED
# The following are special cased in template processing
REPOSITORY = "Repository"
REPOSITORY_ADDRESS = "Repository address"
REPOSITORY_SHORT_VERSION = "Repository (Short)"
REPOSITORY_CALL_NUMBER = "Repository call number"
DATE = "Date"
# All the special case attributes need to be specified as translatable
# strings so they can be picked up during extraction of translatable strings
if False:
_("Title")
_("Author")
_("Pub_info")
_("Page")
_("Event Type Used for Citation")
_("Role in Event Cited from")
_("Generated by")
_("Events Recorded in Source")
_("Repository")
_("Repository address")
_("Repository (Short)")
_("Repository call number")
_("Date")
_CUSTOM = CUSTOM
# _DEFAULT = TITLE
_DATAMAPIGNORE = [
AUTHOR_SHORT_VERSION,
TITLE_SHORT_VERSION,
COLLECTION_SHORT_VERSION,
WEBSITE_SHORT_VERSION,
PAGE_SHORT_VERSION,
NUMBER_SHORT_VERSION,
SERIES_NO_SHORT_VERSION,
VOLUME_SHORT_VERSION,
RECIPIENT_SHORT_VERSION,
ID_SHORT_VERSION,
SERIES_SHORT_VERSION,
RESEARCH_COMMENT_SHORT_VERSION,
SUBJECT_SHORT_VERSION,
CREATION_DATE_SHORT_VERSION,
SECTION_SHORT_VERSION,
ITEM_OF_INTEREST_SHORT_VERSION,
FILE_SHORT_VERSION,
TYPE_SHORT_VERSION,
DATE_SHORT_VERSION,
SUBSERIES_SHORT_VERSION,
REPORT_DATE_SHORT_VERSION,
GROUP_SHORT_VERSION,
INSTITUTION_SHORT_VERSION,
CEMETERY_SHORT_VERSION,
FILE_UNIT_SHORT_VERSION,
JURISDICTION_SHORT_VERSION,
SCHEDULE_SHORT_VERSION,
DIVISION_SHORT_VERSION,
HOUSEHOLD_SHORT_VERSION,
DISTRICT_SHORT_VERSION,
SHEET_NO_SHORT_VERSION,
COMPILER_SHORT_VERSION,
LOCATION_SHORT_VERSION,
ROLL_SHORT_VERSION,
PUBLICATION_YEAR_SHORT_VERSION,
FILE_NO_SHORT_VERSION,
CASE_SHORT_VERSION,
TERM_SHORT_VERSION,
BOOK_SHORT_VERSION,
FILE_DATE_SHORT_VERSION,
TIMESTAMP_SHORT_VERSION,
YEAR_SHORT_VERSION,
CREATOR_SHORT_VERSION,
PUBLICATION_TITLE_SHORT_VERSION,
EDITOR_SHORT_VERSION,
ACT_SHORT_VERSION,
SESSION_SHORT_VERSION,
POSITION_SHORT_VERSION,
COLUMN_SHORT_VERSION,
ISSUE_DATE_SHORT_VERSION,
"Act (Short)",
"Author (Short)",
"Book (Short)",
"Case (Short)",
"Cemetery (Short)",
"Collection (Short)",
"Column (Short)",
"Compiler (Short)",
"Creation date (Short)",
"Creator (Short)",
"Date (Short)",
"District (Short)",
"Division (Short)",
"Editor (Short)",
"File date (Short)",
"File no. (Short)",
"File (Short)",
"File unit (Short)",
"Group (Short)",
"Household (Short)",
"Id (Short)",
"Institution (Short)",
"Issue date (Short)",
"Item of interest (Short)",
"Jurisdiction (Short)",
"Location (Short)",
"Number (Short)",
"Page (Short)",
"Position (Short)",
"Publication title (Short)",
"Publication year (Short)",
"Recipient (Short)",
"Report date (Short)",
"Research comment (Short)",
"Roll (Short)",
"Schedule (Short)",
"Section (Short)",
"Series no. (Short)",
"Series (Short)",
"Session (Short)",
"Sheet no. (Short)",
"Subject (Short)",
"Subseries (Short)",
"Term (Short)",
"Timestamp (Short)",
"Title (Short)",
"Type (Short)",
"Volume (Short)",
"Website (Short)",
"Year (Short)",
]
_DATAMAP += [
(ACT, _("Act"), "Act"),
(ACT_SHORT_VERSION, _("Act (Short)"), "Act (Short)"),
(ADDRESS, _("Address"), "Address"),
(AFFILIATION, _("Affiliation"), "Affiliation"),
(AUTHOR, _("Author"), "Author"),
(AUTHOR_LOCATION, _("Author location"), "Author location"),
(AUTHOR_SHORT_VERSION, _("Author (Short)"), "Author (Short)"),
(BOOK, _("Book"), "Book"),
(BOOK_SHORT_VERSION, _("Book (Short)"), "Book (Short)"),
(CASE, _("Case"), "Case"),
(CASE_SHORT_VERSION, _("Case (Short)"), "Case (Short)"),
(CEMETERY, _("Cemetery"), "Cemetery"),
(CEMETERY_SHORT_VERSION, _("Cemetery (Short)"), "Cemetery (Short)"),
(CHAPTER, _("Chapter"), "Chapter"),
(CHAPTER_PAGES, _("Chapter pages"), "Chapter pages"),
(COLLECTION, _("Collection"), "Collection"),
(COLLECTION_SHORT_VERSION, _("Collection (Short)"), "Collection (Short)"),
(COLUMN, _("Column"), "Column"),
(COLUMN_SHORT_VERSION, _("Column (Short)"), "Column (Short)"),
(COMPILER, _("Compiler"), "Compiler"),
(COMPILER_SHORT_VERSION, _("Compiler (Short)"), "Compiler (Short)"),
(CREATION_DATE, _("Creation date"), "Creation date"),
(CREATION_DATE_SHORT_VERSION, _("Creation date (Short)"), "Creation date (Short)"),
(CREATOR, _("Creator"), "Creator"),
(CREATOR_SHORT_VERSION, _("Creator (Short)"), "Creator (Short)"),
(CREDIT_LINE, _("Credit line"), "Credit line"),
(DATE_ACCESSED, _("Date accessed"), "Date accessed"),
(DATE_RANGE, _("Date range"), "Date range"),
(DATE_SHORT_VERSION, _("Date (Short)"), "Date (Short)"),
(DESCRIPTION, _("Description"), "Description"),
(DISTRICT, _("District"), "District"),
(DISTRICT_SHORT_VERSION, _("District (Short)"), "District (Short)"),
(DIVISION, _("Division"), "Division"),
(DIVISION_SHORT_VERSION, _("Division (Short)"), "Division (Short)"),
(EDITION, _("Edition"), "Edition"),
(EDITOR, _("Editor"), "Editor"),
(EDITOR_SHORT_VERSION, _("Editor (Short)"), "Editor (Short)"),
(FILE, _("File"), "File"),
(FILE_DATE, _("File date"), "File date"),
(FILE_DATE_SHORT_VERSION, _("File date (Short)"), "File date (Short)"),
(FILE_LOCATION, _("File location"), "File location"),
(FILE_NO, _("File no."), "File no."),
(FILE_NO_SHORT_VERSION, _("File no. (Short)"), "File no. (Short)"),
(FILE_SHORT_VERSION, _("File (Short)"), "File (Short)"),
(FILE_UNIT, _("File unit"), "File unit"),
(FILE_UNIT_SHORT_VERSION, _("File unit (Short)"), "File unit (Short)"),
(FILM_ID, _("Film id"), "Film id"),
(FILM_PUBLICATION_PLACE, _("Film publication place"), "Film publication place"),
(FILM_PUBLISHER, _("Film publisher"), "Film publisher"),
(FILM_TYPE, _("Film type"), "Film type"),
(FORMAT, _("Format"), "Format"),
(FRAME, _("Frame"), "Frame"),
(GROUP, _("Group"), "Group"),
(GROUP_SHORT_VERSION, _("Group (Short)"), "Group (Short)"),
(HOUSEHOLD, _("Household"), "Household"),
(HOUSEHOLD_SHORT_VERSION, _("Household (Short)"), "Household (Short)"),
(ID, _("Id"), "Id"),
(ID_SHORT_VERSION, _("Id (Short)"), "Id (Short)"),
(INSTITUTION, _("Institution"), "Institution"),
(INSTITUTION_SHORT_VERSION, _("Institution (Short)"), "Institution (Short)"),
(INTERVIEWER, _("Interviewer"), "Interviewer"),
(ISSUE_DATE, _("Issue date"), "Issue date"),
(ISSUE_DATE_SHORT_VERSION, _("Issue date (Short)"), "Issue date (Short)"),
(ISSUE_RANGE, _("Issue range"), "Issue range"),
(ITEM_OF_INTEREST, _("Item of interest"), "Item of interest"),
(ITEM_OF_INTEREST_SHORT_VERSION, _("Item of interest (Short)"), "Item of interest (Short)"),
(JURISDICTION, _("Jurisdiction"), "Jurisdiction"),
(JURISDICTION_SHORT_VERSION, _("Jurisdiction (Short)"), "Jurisdiction (Short)"),
(LOCATION, _("Location"), "Location"),
(LOCATION_SHORT_VERSION, _("Location (Short)"), "Location (Short)"),
(NUMBER, _("Number"), "Number"),
(NUMBER_6TOTAL9, _("Number (total)"), "Number (total)"),
(NUMBER_SHORT_VERSION, _("Number (Short)"), "Number (Short)"),
(ORIGINAL_REPOSITORY, _("Original repository"), "Original repository"),
(ORIGINAL_REPOSITORY_LOCATION, _("Original repository location"), "Original repository location"),
(ORIGINAL_YEAR, _("Original year"), "Original year"),
(PAGE, _("Page"), "Page"),
(PAGE_RANGE, _("Page range"), "Page range"),
(PAGE_SHORT_VERSION, _("Page (Short)"), "Page (Short)"),
(PART, _("Part"), "Part"),
(PLACE_CREATED, _("Place created"), "Place created"),
(POSITION, _("Position"), "Position"),
(POSITION_SHORT_VERSION, _("Position (Short)"), "Position (Short)"),
(POSTING_DATE, _("Posting date"), "Posting date"),
(PROFESSIONAL_CREDENTIALS, _("Professional credentials"), "Professional credentials"),
(PROVENANCE, _("Provenance"), "Provenance"),
(PUBLICATION_FORMAT, _("Publication format"), "Publication format"),
(PUBLICATION_PLACE, _("Publication place"), "Publication place"),
(PUBLICATION_TITLE, _("Publication title"), "Publication title"),
(PUBLICATION_TITLE_SHORT_VERSION, _("Publication title (Short)"), "Publication title (Short)"),
(PUBLICATION_YEAR, _("Publication year"), "Publication year"),
(PUBLICATION_YEAR_SHORT_VERSION, _("Publication year (Short)"), "Publication year (Short)"),
(PUBLISHER, _("Publisher"), "Publisher"),
(PUB_INFO, _("Pub_info"), "Pub_info"),
(RECIPIENT, _("Recipient"), "Recipient"),
(RECIPIENT_SHORT_VERSION, _("Recipient (Short)"), "Recipient (Short)"),
(RELATIONSHIP, _("Relationship"), "Relationship"),
(REPORT_DATE, _("Report date"), "Report date"),
(REPORT_DATE_SHORT_VERSION, _("Report date (Short)"), "Report date (Short)"),
(RESEARCH_COMMENT, _("Research comment"), "Research comment"),
(RESEARCH_COMMENT_SHORT_VERSION, _("Research comment (Short)"), "Research comment (Short)"),
(RESEARCH_PROJECT, _("Research project"), "Research project"),
(ROLL, _("Roll"), "Roll"),
(ROLL_SHORT_VERSION, _("Roll (Short)"), "Roll (Short)"),
(SCHEDULE, _("Schedule"), "Schedule"),
(SCHEDULE_SHORT_VERSION, _("Schedule (Short)"), "Schedule (Short)"),
(SECTION, _("Section"), "Section"),
(SECTION_SHORT_VERSION, _("Section (Short)"), "Section (Short)"),
(SERIES, _("Series"), "Series"),
(SERIES_NO, _("Series no."), "Series no."),
(SERIES_NO_SHORT_VERSION, _("Series no. (Short)"), "Series no. (Short)"),
(SERIES_SHORT_VERSION, _("Series (Short)"), "Series (Short)"),
(SESSION, _("Session"), "Session"),
(SESSION_SHORT_VERSION, _("Session (Short)"), "Session (Short)"),
(SHEET_NO, _("Sheet no."), "Sheet no."),
(SHEET_NO_SHORT_VERSION, _("Sheet no. (Short)"), "Sheet no. (Short)"),
(SUBJECT, _("Subject"), "Subject"),
(SUBJECT_SHORT_VERSION, _("Subject (Short)"), "Subject (Short)"),
(SUBSERIES, _("Subseries"), "Subseries"),
(SUBSERIES_SHORT_VERSION, _("Subseries (Short)"), "Subseries (Short)"),
(SUBTITLE, _("Subtitle"), "Subtitle"),
(TERM, _("Term"), "Term"),
(TERM_SHORT_VERSION, _("Term (Short)"), "Term (Short)"),
(TIMESTAMP, _("Timestamp"), "Timestamp"),
(TIMESTAMP_SHORT_VERSION, _("Timestamp (Short)"), "Timestamp (Short)"),
(TITLE, _("Title"), "Title"),
(TITLE_SHORT_VERSION, _("Title (Short)"), "Title (Short)"),
(TRANSLATION, _("Translation"), "Translation"),
(TYPE, _("Type"), "Type"),
(TYPE_SHORT_VERSION, _("Type (Short)"), "Type (Short)"),
(URL_6DIGITAL_LOCATION9, _("Url (digital location)"), "Url (digital location)"),
(VOLUME, _("Volume"), "Volume"),
(VOLUME_INFO, _("Volume info"), "Volume info"),
(VOLUME_SHORT_VERSION, _("Volume (Short)"), "Volume (Short)"),
(WEBSITE, _("Website"), "Website"),
(WEBSITE_CREATOR_OR_OWNER, _("Website creator/owner"), "Website creator/owner"),
(WEBSITE_SHORT_VERSION, _("Website (Short)"), "Website (Short)"),
(YEAR, _("Year"), "Year"),
(YEAR_ACCESSED, _("Year accessed"), "Year accessed"),
(YEAR_SHORT_VERSION, _("Year (Short)"), "Year (Short)"),
]
_DEFAULT_HINTS = {
ACT: _("Public Law 12-98"),
ADDRESS: _("Broadway Avenue, New York"),
AFFILIATION: _("Agent of Gramps Software"),
AUTHOR: _("Doe, D.P. & Cameron, E."),
AUTHOR_LOCATION: _("Chicago"),
BOOK: _("The big example Gramps manual"),
CASE: _("B. Malengier versus N. Hall"),
CEMETERY: _("Greenwich Cemetery Office"),
CHAPTER: _("The first office of T. Rooseveld"),
CHAPTER_PAGES: _("24-55"),
COLLECTION: _("Bruges Lace Collection"),
COLUMN: _("col. 3"),
COMPILER: _("T. Da Silva"),
CREATION_DATE: _("13 Aug 1965"),
CREATOR: _("P. Picasso"),
CREDIT_LINE: _("Based on unnamed document lost in fire"),
DATE: _("17 Sep 1745"),
DATE_ACCESSED: _("18 Jun 2013"),
DATE_RANGE: _("2003-6"),
DESCRIPTION: _("The lace has inscriptions with names of nobility"),
DISTRICT: _("Enumeration district (ED) 14"),
DIVISION: _("Peterburg Post Office, or Portland, ward 4"),
EDITION: _("Second Edition"),
EDITOR: _("Hoover, J.E."),
FILE: _("Membership application J. Rapinat"),
FILE_DATE: _("15 Jan 1870"),
FILE_LOCATION: _("Accession 7, Box 3"),
FILE_NO: _("1243-EB-98"),
FILE_UNIT: _("Letters to George Washington"),
FILM_ID: _("T345"),
FILM_PUBLICATION_PLACE: _("Kansas City"),
FILM_PUBLISHER: _("NY Genealogy Association"),
FILM_TYPE: _("FHL microfilm"),
FORMAT: _("Digital Images, or Database, or Cards, ..."),
FRAME: _("frames 387-432"),
GROUP: _("Miami Patent Office"),
HOUSEHOLD: _("dwelling 345, family 654"),
ID: _("I50-68, or 1910 U.S. census, or ..."),
INSTITUTION: _("Sorbonne University"),
INTERVIEWER: _("Materley, B."),
ISSUE_DATE: _("Jun 2004"),
ISSUE_RANGE: _("145-394, scattered issues"),
ITEM_OF_INTEREST: _("entry for G. Galileo, or Doe Household, or A. Einstein Grave ..."),
JURISDICTION: _("Jackson County, Alabama"),
LOCATION: _("Istanbul"),
NUMBER: _("2, or Record Group 34, or ..."),
NUMBER_6TOTAL9: _("5"),
ORIGINAL_REPOSITORY: _("National Archives"),
ORIGINAL_REPOSITORY_LOCATION: _("Washington, D.C."),
ORIGINAL_YEAR: _("1966"),
PAGE: _("5; or 4,6-8, ..."),
PAGE_RANGE: _("1-13"),
PART: _("Part 3"),
PLACE_CREATED: _("London"),
POSITION: _("written in the left margin, or second row, 3th line"),
POSTING_DATE: _("5 Jul 1799"),
PROFESSIONAL_CREDENTIALS: _("Prof.; or Dr. ..."),
PROVENANCE: _("add provenance of the material"),
PUBLICATION_FORMAT: _("CD-ROM or eprint or ..."),
PUBLICATION_PLACE: _("Berlin"),
PUBLICATION_TITLE: _("Title of Blog, Newsletter, DVD, ..."),
PUBLICATION_YEAR: _("2014"),
PUBLISHER: _("Springer"),
PUB_INFO: _("Springer, Berlin, 2014"),
RECIPIENT: _("J. Ralls"),
RELATIONSHIP: _("Paul's uncle and brother of Erik"),
REPORT_DATE: _("3 May 1999"),
RESEARCH_COMMENT: _("Descriptive detail or provenance or research analysis conclusion, ..."),
RESEARCH_PROJECT: _("Tahiti Natives"),
ROLL: _("176, or rolls 145-160"),
SCHEDULE: _("population schedule or slave schedule or ..."),
SECTION: _("1890 section or ER patients or ..."),
SERIES: _("Carnival County Records"),
SERIES_NO: _("series 34-38"),
SESSION: _("2nd session"),
SHEET_NO: _("sheet 13-C"),
SUBJECT: _("D. Copernicus and close family"),
SUBTITLE: _("Subtitle of article or magazine ..."),
TERM: _("June Term 1934 or 13th Congress or Reagan Office or ..."),
TIMESTAMP: _("min. 34-36"),
TITLE: _("Diary Title, Message Title, Bible Name, Article Title, ..."),
TRANSLATION: _("A translated version, typically of the title"),
TYPE: _("Letter"),
URL_6DIGITAL_LOCATION9: _("http://gramps-project.org/blog"),
VOLUME: _("4"),
VOLUME_INFO: _("5 volumes"),
WEBSITE: _("gramps-project.org"),
WEBSITE_CREATOR_OR_OWNER: _("Family Historians Inc"),
YEAR: _("1888"),
YEAR_ACCESSED: _("2013"),
}
_DEFAULT_TOOLTIPS = {
ACT: _("A statute or law name passed by a legislature"),
ADDRESS: _("Store address information. Set Private if needed! Give information from lowest to highest level separated by comma's"),
AFFILIATION: _("A relevant affiliation that might influence data in the source"),
AUTHOR: _("Give names in following form: 'FirstAuthorSurname, Given Names & SecondAuthorSurname, Given Names'. Like this Gramps can parse the name and shorten as needed."),
AUTHOR_LOCATION: _("City where author resides or wrote."),
BOOK: _("Title of the Book"),
CASE: _("Dispute between opposing parties in a court of law."),
CEMETERY: _("Name of cemetery or cemetery office with sources."),
CHAPTER_PAGES: _("The pages in the chapter."),
COMPILER: _("The name of the person who compiled the source."),
CREATOR: _("The name of the creator of the artifact."),
CREDIT_LINE: _("Acknowledgement of writers and contributors"),
DATE_RANGE: _("The range of years which are present in the source."),
DESCRIPTION: _("Some important detail of the source."),
DISTRICT: _("District as handled by Census"),
DIVISION: _("The subdivision of a larger group that is handled in the source."),
EDITOR: _("The Editor of a multi-author book."),
FILE: _("The title of a specific file in a source."),
FILE_DATE: _("Date of submitting the document to a clerk or court."),
FILE_LOCATION: _("Accession method to the file"),
FILE_NO: _("Number to indicate a file"),
FILE_UNIT: _("A grouping unit for a number of files in a source."),
FILM_ID: _("ID of a Microfilm."),
FILM_TYPE: _("The type of the microfilm."),
FORMAT: _("The format of the source."),
FRAME: _("What frames in the source are relevant."),
GROUP: _("A larger grouping to which the source belongs."),
HOUSEHOLD: _("Household of interest on a census."),
ID: _("ID to identify the source or citation part"),
INSTITUTION: _("Institution that issued the source."),
ISSUE_DATE: _("Date the source was issued."),
ISSUE_RANGE: _("A range of magazine, journal, ... issues covered in the source"),
ITEM_OF_INTEREST: _("Specific part, item, or person of interest in the source"),
JURISDICTION: _("Area with a set of laws under the control of a system of courts or government entity. Enter this from lowest to highest relevant jurisdiction, separated by comma's."),
LOCATION: _("City that is relevant."),
NUMBER: _("A number."),
NUMBER_6TOTAL9: _("The maximum of entities available."),
ORIGINAL_REPOSITORY: _("Name of the repository where the original is stored."),
ORIGINAL_REPOSITORY_LOCATION: _("Address or only city of the repository where the original is stored."),
ORIGINAL_YEAR: _("Year the original source was published/created"),
PAGE: _("The page or page(s) relevant for the citation"),
PAGE_RANGE: _("The range of the pages in the source. The page given for a citation must be in this range."),
POSITION: _("Where in or on the source the citation piece can be found."),
PROVENANCE: _("Where the material originated from."),
PUB_INFO: _("Publication Information, such as city and year of publication, name of publisher, ..."),
RECIPIENT: _("The person to who the letter is addressed."),
RELATIONSHIP: _("The relationship of the author to the person of interest that is the subject."),
REPORT_DATE: _("Date the report was written/submitted."),
RESEARCH_COMMENT: _("Descriptive detail or provenance or research analysis conclusion, ..."),
RESEARCH_PROJECT: _("The genealogical or scientific research project."),
ROLL: _("The Microfilm role."),
SCHEDULE: _("The census schedule (the type of census table) used, eg population schedule or slave schedule. or ..."),
SECTION: _("The section or subgroup under which filed, eg 'Diplomatic correspondance, 1798-1810'"),
SESSION: _("The number of the meeting or series of connected meetings devoted by a legislature to a single order of business, program, agenda, or announced purpose."),
SHEET_NO: _("Number of a census sheet."),
TERM: _("Reference to the time a person/group/parliament is in office or session."),
TIMESTAMP: _("Indication of the time in audio or video where the relevant fragment can be found."),
TRANSLATION: _("A translated version, typically of the title"),
URL_6DIGITAL_LOCATION9: _("Detailed internet address of the content"),
VOLUME_INFO: _("Information about the volumes, eg the amount of volumes."),
WEBSITE: _("The main internet address."),
WEBSITE_CREATOR_OR_OWNER: _("Organization or person behind a website."),
}
def __init__(self, value=None):
GrampsType.__init__(self, value)
def short_version(self, sattrtype):
"""
Method that returns the type which is the short version type of the given type
"""
sattrt = SrcAttributeType(sattrtype)
if sattrt.xml_str().lower().endswith(' (short)'):
return sattrtype
return SrcAttributeType(sattrt.xml_str() +' (Short)')
@staticmethod
def get_default_hint(sattrtype):
index = int(SrcAttributeType(sattrtype))
return SrcAttributeType._DEFAULT_HINTS.get(index) or ""
@staticmethod
def get_default_tooltip(sattrtype):
index = int(SrcAttributeType(sattrtype))
return SrcAttributeType._DEFAULT_TOOLTIPS.get(index) or ""
def get_ignore_list(self, exception=None):
"""
Return a list of the types to ignore and not include in default lists.

View File

@ -0,0 +1,226 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
SrcTemplate class for GRAMPS.
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from __future__ import print_function
from collections import defaultdict
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
LOG = logging.getLogger('.template')
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from .tableobj import TableObject
from .handle import Handle
from ..constfunc import cuni
from .templateelement import TemplateElement
#-------------------------------------------------------------------------
#
# SrcTemplate class
#
#-------------------------------------------------------------------------
class SrcTemplate(TableObject):
"""
Sources conform to a certain template, which governs their styling when
used in reports.
The SrcTemplate object holds all the logic to do the actual styling.
Predefined templates themself are stored in SrcAttributeType, or in extra
xml files with defenitions
The structure typically is a dictionary as follows:
{
REF_TYPE_L: [
('', AUTHOR, '.', EMPTY, False, False, EMPTY, GED_AUTHOR, 'hint', 'tooltip'),
('', TITLE, '.', STYLE_QUOTE, False, False, EMPTY, GED_TITLE, '', ''),
('', PUB_INFO, '', EMPTY, False, False, EMPTY, GED_PUBINF, '', ''),
],
REF_TYPE_F: [
('', AUTHOR, ',', EMPTY, False, False, EMPTY, EMPTY, '', ''),
('', TITLE, ',', STYLE_QUOTE, False, False, EMPTY, EMPTY, '', ''),
('', PUB_INFO, '.', EMPTY, False, False, EMPTY, EMPTY, '', ''),
('', DATE, ' -', EMPTY, False, False, EMPTY, EMPTY, '', ''),
('', PAGE6S9, '.', EMPTY, False, False, EMPTY, EMPTY, '', ''),
],
REF_TYPE_S: [
('', AUTHOR, ',', EMPTY, False, False, EMPTY, EMPTY, '', ''),
('', DATE, ' -', EMPTY, False, False, EMPTY, EMPTY, '', ''),
('', PAGE6S9, '.', EMPTY, False, False, EMPTY, EMPTY, '', ''),
],
}
This defines the 3 source reference types. A reference type consists of
a list of tuples with fieldsdescriptions.
A fielddescription consists of the columns:
0/ left delimiter
1/ field, this is a SrcAttributeType
2/ right delimiter
3/ style to use
4/ bool: if field should be private by default on creation
5/ bool: if optional field
6/ shortening algorithm to use, EMPTY indicates no transformation
7/ the REF_TYPE_L reference maps to GEDCOM fields on export via
this column. GEDCOM contains Title, Author and Pub.Info field
"""
def __init__(self, template_key=None):
"""
Create a new Template instance.
After initialization, most data items have empty or null values,
including the database handle.
"""
TableObject.__init__(self)
self.handle = ""
self.name = ""
self.descr = ""
self.template_element_list = []
self.mapdict = defaultdict(str)
def serialize(self):
"""
Convert the data held in the Template to a Python tuple that
represents all the data elements.
This method is used to convert the object into a form that can easily
be saved to a database.
These elements may be primitive Python types (string, integers),
complex Python types (lists or tuples, or Python objects. If the
target database cannot handle complex types (such as objects or
lists), the database is responsible for converting the data into
a form that it can use.
:returns: Returns a python tuple containing the data that should
be considered persistent.
:rtype: tuple
"""
return (
self.handle,
self.name,
self.descr,
[template_element.serialize() for template_element in self.template_element_list],
self.mapdict
)
def to_struct(self):
"""
Convert the data held in this object to a structure (eg,
struct) that represents all the data elements.
This method is used to recursively convert the object into a
self-documenting form that can easily be used for various
purposes, including diffs and queries.
These structures may be primitive Python types (string,
integer, boolean, etc.) or complex Python types (lists,
tuples, or dicts). If the return type is a dict, then the keys
of the dict match the fieldname of the object. If the return
struct (or value of a dict key) is a list, then it is a list
of structs. Otherwise, the struct is just the value of the
attribute.
:returns: Returns a struct containing the data of the object.
:rtype: dict
"""
return {"handle": Handle("Srctemplate", self.handle),
"name": cuni(self.name),
"descr": cuni(self.descr),
"elements": [e.to_struct() for e in self.template_element_list],
"mapdict" : {'dict': self.mapdict}
}
def unserialize(self, data):
"""
Convert the data held in a tuple created by the serialize method
back into the data in a SrcTemplate object.
:param data: tuple containing the persistent data associated the
SrcTemplate object
:type data: tuple
"""
(self.handle,
self.name,
self.descr,
template_element_list,
self.mapdict,
) = data
self.template_element_list = [TemplateElement().unserialize(te)
for te in template_element_list]
return self
def get_name(self):
return self.name
def set_name(self, name):
self.name = name
def get_descr(self):
return self.descr
def set_descr(self, descr):
self.descr = descr
def get_map_dict(self):
"""Return the map for the template"""
return self.mapdict
def set_map_dict(self, templmap):
"""Set the map for the template"""
self.mapdict = templmap
def set_map_element(self, key, value):
self.mapdict[key] = value
def get_map_element(self, key):
return self.mapdict[key]
def get_template_element_list(self):
return self.template_element_list
def set_template_element_list(self, template_element_list):
self.template_element_list = template_element_list
def add_template_element(self, template_element):
self.template_element_list.append(template_element)

View File

@ -0,0 +1,244 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
SrcTemplate class for GRAMPS.
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from __future__ import print_function
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
LOG = logging.getLogger('.template')
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from .secondaryobj import SecondaryObject
from ..constfunc import cuni
#-------------------------------------------------------------------------
#
# TemplateElement class
#
#-------------------------------------------------------------------------
class TemplateElement(SecondaryObject):
"""
TemplateEelement class.
This class is for keeping information about each template-element.
TemplateElement:
- template_element_name - English name of the element exactly as it appears
in Yates e.g. [WRITER FIRST]
- name to be displayed in the user interface e.g. 'Name of the first
author'
- hint e.g. "Doe, D.P. & Cameron, E."
- tooltip e.g. "Give names in following form: 'FirstAuthorSurname, Given
Names & SecondAuthorSurname, Given Names'. Like this Gramps can parse the
name and shorten as needed."
- citation - True if this element appears in a citation (false for a source
element)
- short - True if this element is an optional short element
- short_alg - algorithm to shorten the field.
- list of Mappings - there would always be a GEDCOM mapping. Also we would
expect a CSL mapping
"""
def __init__(self, source=None):
"""
Create a new TemplateEelement instance, copying from the source if present.
"""
if source:
self.name = source.name
self.display = source.display
self.hint = source.hint
self.tooltip = source.tooltip
self.citation = source.citation
self.short - source.short
self.short_alg = source.short_alg
else:
self.name = ""
self.display = ""
self.hint = ""
self.tooltip = ""
self.citation = False
self.short = False
self.short_alg = ""
def serialize(self):
"""
Convert the object to a serialized tuple of data.
"""
return (self.name,
self.display,
self.hint,
self.tooltip,
self.citation,
self.short,
self.short_alg
)
def to_struct(self):
"""
Convert the data held in this object to a structure (eg,
struct) that represents all the data elements.
This method is used to recursively convert the object into a
self-documenting form that can easily be used for various
purposes, including diffs and queries.
These structures may be primitive Python types (string,
integer, boolean, etc.) or complex Python types (lists,
tuples, or dicts). If the return type is a dict, then the keys
of the dict match the fieldname of the object. If the return
struct (or value of a dict key) is a list, then it is a list
of structs. Otherwise, the struct is just the value of the
attribute.
:returns: Returns a struct containing the data of the object.
:rtype: dict
"""
return {"name": cuni(self.name),
"display": cuni(self.display),
"hint": cuni(self.hint),
"tooltip": cuni(self.tooltip),
"citation": cuni(self.citation),
"short": cuni(self.short),
"short_alg": cuni(self.short_alg),
}
def unserialize(self, data):
"""
Convert a serialized tuple of data to an object.
"""
(self.name, self.display, self.hint, self.tooltip, self.citation,
self.short, self.short_alg) = data
return self
def get_name(self):
"""
Return the name for the Template element.
"""
return self.name
def set_name(self, name):
"""
Set the name for the Template element according to the given argument.
"""
self.name = name
def get_hint(self):
"""
Return the hint for the Template element.
"""
return self.hint
def set_hint(self, hint):
"""
Set the hint for the Template element according to the given argument.
"""
self.hint = hint
def get_display(self):
"""
Return the display form for the Template element.
"""
return self.display
def set_display(self, display):
"""
Set the display form for the Template element according to the given
argument.
"""
self.display = display
def get_tooltip(self):
"""
Return the tooltip for the Template element.
"""
return self.tooltip
def set_tooltip(self, tooltip):
"""
Set the tooltip for the Template element according to the given argument.
"""
self.tooltip = tooltip
def get_citation(self):
"""
Return the citation for the Template element.
"""
return self.citation
def set_citation(self, citation):
"""
Set the citation for the Template element according to the given argument.
"""
self.citation = citation
def get_short(self):
"""
Return the short for the Template element.
"""
return self.short
def set_short(self, short):
"""
Set the short for the Template element according to the given argument.
"""
self.short = short
def get_short_alg(self):
"""
Return the short_alg for the Template element.
"""
return self.short_alg
def set_short_alg(self, short_alg):
"""
Set the short_alg for the Template element according to the given argument.
"""
self.short_alg = short_alg

View File

@ -66,7 +66,7 @@ class CitationBaseTest:
def test_citation_merge(self):
citation = Citation()
citation.set_reference_handle('123456')
citation.set_page('p.10')
citation.set_name('p.10')
self.titanic.add_citation(citation.handle)
self.ref_obj.add_citation(citation.handle)
self.phoenix.merge(self.titanic)
@ -385,10 +385,10 @@ class EventRefCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
attr1.set_value(10)
citation1 = Citation()
citation1.set_reference_handle('123456')
citation1.set_page('p.10')
citation1.set_name('p.10')
citation2 = Citation()
citation2.set_reference_handle('234567')
citation2.set_page('p.20')
citation2.set_name('p.20')
attr1.add_citation(citation1.handle)
attr1.add_citation(citation2.handle)
attr2 = Attribute()
@ -396,10 +396,10 @@ class EventRefCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
attr2.set_value(10)
citation3 = Citation()
citation3.set_reference_handle('123456')
citation3.set_page('p.10')
citation3.set_name('p.10')
citation4 = Citation()
citation4.set_reference_handle('654321')
citation4.set_page('p.20')
citation4.set_name('p.20')
attr2.add_citation(citation3.handle)
attr2.add_citation(citation4.handle)
self.phoenix.add_attribute(attr1)
@ -1539,11 +1539,11 @@ class SourceCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
MediaBaseTest):
def setUp(self):
self.phoenix = Source()
self.phoenix.set_title("Source 1")
self.phoenix.set_name("Source 1")
self.titanic = Source()
self.titanic.set_title("Source 1")
self.titanic.set_name("Source 1")
self.ref_obj = Source()
self.ref_obj.set_title("Source 1")
self.ref_obj.set_name("Source 1")
def todo_test_replace(self):
pass
@ -1701,7 +1701,7 @@ class CitationBaseCheck(unittest.TestCase):
def test_replace_newpresent(self):
citation = Citation()
citation.set_reference_handle('654321')
citation.set_page('p.10')
citation.set_name('p.10')
citation2 = Citation()
citation2.set_reference_handle('234567')
self.phoenix.add_citation(citation.handle)
@ -1738,13 +1738,13 @@ class CitationCheck(unittest.TestCase, PrivacyBaseTest, MediaBaseTest,
def setUp(self):
self.phoenix = Citation()
self.phoenix.set_reference_handle('123456')
self.phoenix.set_page('p.10')
self.phoenix.set_name('p.10')
self.titanic = Citation()
self.titanic.set_reference_handle('123456')
self.titanic.set_page('p.10')
self.titanic.set_name('p.10')
self.ref_obj = Citation()
self.ref_obj.set_reference_handle('123456')
self.ref_obj.set_page('p.10')
self.ref_obj.set_name('p.10')
def test_merge_confidence(self):
known_values = ( (0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 3, 0), (0, 4, 0),

View File

@ -386,6 +386,16 @@ class BasePluginManager(object):
"""
return self.__pgr.sidebar_plugins()
def get_reg_srctemplates(self):
""" Return list of registered sidebars. Only non-hidden templates
are returned, as srctemplate plugins can redifine templates of other
plugins. By setting hidden, user can select style he wants
"""
#sr
hidden_plugins = set(config.get('plugin.hiddenplugins'))
return [plg for plg in self.__pgr.srctemplate_plugins()
if plg.id not in hidden_plugins]
def get_external_opt_dict(self):
""" Return the dictionary of external options. """
return self.__external_opt_dict

View File

@ -74,8 +74,9 @@ VIEW = 8
RELCALC = 9
GRAMPLET = 10
SIDEBAR = 11
SRCTEMPLATE = 12
PTYPE = [REPORT , QUICKREPORT, TOOL, IMPORT, EXPORT, DOCGEN, GENERAL,
MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR]
MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR, SRCTEMPLATE]
PTYPE_STR = {
REPORT: _('Report') ,
QUICKREPORT: _('Quickreport'),
@ -89,6 +90,7 @@ PTYPE_STR = {
RELCALC: _('Relationships'),
GRAMPLET: _('Gramplet'),
SIDEBAR: _('Sidebar'),
SRCTEMPLATE: _('Source Templates'),
}
#possible report categories
@ -990,6 +992,7 @@ def make_environment(**kwargs):
'RELCALC': RELCALC,
'GRAMPLET': GRAMPLET,
'SIDEBAR': SIDEBAR,
'SRCTEMPLATE': SRCTEMPLATE,
'CATEGORY_TEXT': CATEGORY_TEXT,
'CATEGORY_DRAW': CATEGORY_DRAW,
'CATEGORY_CODE': CATEGORY_CODE,
@ -1262,6 +1265,11 @@ class PluginRegister(object):
"""
return self.type_plugins(SIDEBAR)
def srctemplate_plugins(self):
"""Return a list of PluginData that are of type SRCTEMPLATE
"""
return self.type_plugins(SRCTEMPLATE)
def filter_load_on_reg(self):
"""Return a list of PluginData that have load_on_reg == True
"""

View File

@ -32,6 +32,8 @@ from ...lib import NoteType, Citation
from ...const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from ...utils.string import confidence
from gramps.gen.utils.citeref import (get_gedcom_title, get_gedcom_author,
get_gedcom_pubinfo, get_gedcom_page)
def add_endnote_styles(style_sheet):
"""
@ -141,7 +143,7 @@ def write_endnotes(bibliography, database, doc, printnotes=False, links=False,
first = True
doc.start_paragraph('Endnotes-Source', "%d." % cindex)
doc.write_text(_format_source_text(source), links=links)
doc.write_text(_format_source_text(database, source), links=links)
doc.end_paragraph()
if printnotes:
@ -149,29 +151,29 @@ def write_endnotes(bibliography, database, doc, printnotes=False, links=False,
for key, ref in citation.get_ref_list():
doc.start_paragraph('Endnotes-Ref', "%s:" % key)
doc.write_text(_format_ref_text(ref, key, elocale), links=links)
doc.write_text(_format_ref_text(database, ref, key, elocale), links=links)
doc.end_paragraph()
if printnotes:
_print_notes(ref, database, doc, 'Endnotes-Ref-Notes', links)
def _format_source_text(source):
def _format_source_text(database, source):
if not source: return ""
src_txt = ""
if source.get_author():
src_txt += source.get_author()
if get_gedcom_author(database, source):
src_txt += get_gedcom_author(database, source)
if source.get_title():
if get_gedcom_title(database, source):
if src_txt:
src_txt += ", "
src_txt += '"%s"' % source.get_title()
src_txt += '"%s"' % get_gedcom_title(database, source)
if source.get_publication_info():
if get_gedcom_pubinfo(database, source):
if src_txt:
src_txt += ", "
src_txt += source.get_publication_info()
src_txt += get_gedcom_pubinfo(database, source)
if source.get_abbreviation():
if src_txt:
@ -180,7 +182,7 @@ def _format_source_text(source):
return src_txt
def _format_ref_text(ref, key, elocale):
def _format_ref_text(database, ref, key, elocale):
if not ref: return ""
ref_txt = ""
@ -190,12 +192,13 @@ def _format_ref_text(ref, key, elocale):
if date is not None and not date.is_empty():
datepresent = True
if datepresent:
if ref.get_page():
ref_txt = "%s - %s" % (ref.get_page(), elocale.get_date(date))
if get_gedcom_page(database, ref):
ref_txt = "%s - %s" % (get_gedcom_page(database, ref),
elocale.get_date(date))
else:
ref_txt = elocale.get_date(date)
else:
ref_txt = ref.get_page()
ref_txt = get_gedcom_page(database, ref)
# Print only confidence level if it is not Normal
if (ref.get_confidence_level() != Citation.CONF_NORMAL

View File

@ -234,7 +234,28 @@ def get_address_str(addr):
else:
str = "%s, %s" % (str, info)
return str
def get_address_ref_str(addr):
"""
Return a string that combines the elements of an address without county,
postal_code and phone, for typical use in references
@param addr: the GRAMPS address instance
"""
str = ""
elems = [ addr.get_street(),
addr.get_locality(),
addr.get_city(),
addr.get_state(),
addr.get_country(), ]
for info in elems:
if info:
if str == "":
str = info
else:
str = "%s, %s" % (str, info)
return str
#-------------------------------------------------------------------------
#
# People Filters

View File

@ -762,7 +762,7 @@ def sanitize_citation(db, citation):
"""
new_citation = Citation()
new_citation.set_date_object(citation.get_date_object())
new_citation.set_page(citation.get_page())
new_citation.set_name(citation.get_name())
new_citation.set_confidence_level(citation.get_confidence_level())
new_citation.set_reference_handle(citation.get_reference_handle())
new_citation.set_gramps_id(citation.get_gramps_id())
@ -906,9 +906,8 @@ def sanitize_source(db, source):
"""
new_source = Source()
new_source.set_author(source.get_author())
new_source.set_title(source.get_title())
new_source.set_publication_info(source.get_publication_info())
new_source.set_name(source.get_name())
new_source.set_template(source.get_template())
new_source.set_abbreviation(source.get_abbreviation())
new_source.set_gramps_id(source.get_gramps_id())
new_source.set_handle(source.get_handle())

View File

@ -40,6 +40,8 @@ from ..config import config
from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from ..constfunc import STRTYPE
from gramps.gen.utils.citeref import (get_gedcom_title, get_gedcom_author,
get_gedcom_pubinfo)
#-------------------------------------------------------------------------
#
@ -846,7 +848,7 @@ class SimpleAccess(object):
"""
assert(source is None or isinstance(source, Source))
if source:
return source.get_title()
return get_gedcom_title(self.dbase, source)
return ''
def page(self, citation):
@ -860,7 +862,7 @@ class SimpleAccess(object):
"""
assert(citation is None or isinstance(citation, Citation))
if citation:
return citation.get_page()
return get_gedcom_page(self.dbase, citation)
return ''
def author(self, source):
@ -874,7 +876,7 @@ class SimpleAccess(object):
"""
assert(source is None or isinstance(source, Source))
if source:
return source.get_author()
return get_gedcom_author(self.dbase, source)
return ''
def person(self, handle):

457
gramps/gen/utils/citeref.py Normal file
View File

@ -0,0 +1,457 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Utility functions to create citation references for Gramps Sources and
Citations.
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from __future__ import print_function
from collections import defaultdict, OrderedDict
import sys
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from gramps.gen.lib.srcattrtype import SrcAttributeType
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
LOG = logging.getLogger('.template')
#-------------------------------------------------------------------------
#
# The functions are passed either a Source object or a Citation object or both.
# They call set_input_dict_and_template to construct a dictionary of template input elements
# to values. This dictionary includes the Date value and any Repository values
# although these are not stored as attributes.
#
# For the GEDCOM fields, the mapping is done immediately. For the bibliographic
# items, 'reference' is called to construct the various citation references.
#
#-------------------------------------------------------------------------
# The predefined template mappings are given names starting with underscore so
# they can be distinguished from CSL mappings.
REF_TYPE_F = "_full" # Full footnote citation to a source
REF_TYPE_S = "_subsequent" # Short footnote citation to a source
REF_TYPE_L = "_bibliography" # Listed reference of the source (no citation info)
GED_AUTHOR = "_GEDCOM_A"
GED_TITLE = "_GEDCOM_T"
GED_PUBINF = "_GEDCOM_P"
GED_DATE = "_GEDCOM_D"
GED_PAGE = "_GEDCOM_PAGE"
refL = None
refF = None
refS = None
input_dict = defaultdict(str)
template_cache = None
def reference_L(db, source=None):
"""
Return the list reference (bibliography entry) based on the passed source
If source is None, the same input_dict as before is used.
"""
global refL, template_cache
if source:
set_input_dict_and_template(db, source)
if refL is not None:
return refL
if template_cache is None:
return ""
refL = _reference(db, REF_TYPE_L)
return refL
def reference_S(db, source=None, citation=None):
"""
Return the short reference based on the passed source and/or citation
If both source and citation are None, the same list as before is used.
"""
global refS, template_cache
if source or citation:
set_input_dict_and_template(db, source, citation)
if refS is not None:
return refS
if template_cache is None:
return ""
refS = _reference(db, REF_TYPE_S)
return refS
def reference_F(db, source=None, citation=None):
"""
Return the full reference based on the passed source and/or citation
If both source and citation are None, the same list as before is used.
"""
global refF, template_cache
if source or citation:
set_input_dict_and_template(db, source, citation)
if refF is not None:
return refF
if template_cache is None:
return ""
refF = _reference(db, REF_TYPE_F)
return refF
def get_gedcom_title(db, source=None):
global template_cache, source_cache
if source:
set_input_dict_and_template(db, source)
if template_cache is None:
if source:
return source.get_name()
else:
return source_cache.get_name()
return (template_cache.get_map_element(GED_TITLE) %
DefaultBlank(input_dict)) or ""
def get_gedcom_author(db, source=None):
global template_cache, source_cache
if source:
set_input_dict_and_template(db, source)
if template_cache is None:
return ""
return (template_cache.get_map_element(GED_AUTHOR) %
DefaultBlank(input_dict)) or ""
def get_gedcom_pubinfo(db, source=None):
global template_cache, source_cache
if source:
set_input_dict_and_template(db, source)
if template_cache is None:
return ""
return (template_cache.get_map_element(GED_PUBINF) %
DefaultBlank(input_dict)) or ""
def get_gedcom_page(db, citation=None):
global template_cache
if citation:
set_input_dict_and_template(db, source=None, citation=citation)
if template_cache is None:
return ""
return (template_cache.get_map_element(GED_PAGE) %
DefaultBlank(input_dict)) or ""
# http://bugs.python.org/issue6081
class DefaultBlank(dict):
def __missing__(self, key):
return ""
class DefaultKey(dict):
def __missing__(self, key):
return "[" + key + "]"
def empty():
"""
remove all computed data
"""
global refL, refF, refS, input_dict, template_cache, source_cache
refL = None
refF = None
refS = None
input_dict = defaultdict(str)
template_cache = None
source_cache = None
def set_input_dict_and_template(db, source=None, citation=None):
"""
Set the attribute dictionary of this template. Setting once for different
references saves some time.
attr_list should be the source attribute list
If citation given, citation attributes overrule source attributes for
the Full and Short references
The citation date is not stored as attribute, so pass Date() object via
date_citation if a date is known.
"""
global refL, refF, refS, input_dict, template_cache, source_cache
empty()
# Find the template
if not source and not citation:
# No source and no citation
raise NotImplementedError
elif not source:
# Citation and no source
# citation will be used to obtain the source
source_handle = citation.get_reference_handle()
source_cache = db.get_source_from_handle(source_handle)
template_handle = source_cache.get_template()
if template_handle is None:
template_cache = None
return
template_cache = db.get_template_from_handle(template_handle)
attr_list = source_cache.get_attribute_list() + citation.get_attribute_list()
date_citation = citation.get_date_object()
elif citation:
#source and citation are given
source_cache = source
# FIXME: as both a source and a citation have been given, they should be
# connected, so a check for that should be made here. However, in
# editsource, the 'refernce_handle' for a new citation to an existing
# source is only set in __base_save when data is saved to the database.
# Hence the check cannot be done at the moment.
# if not (citation.get_reference_handle() == source_cache.handle):
# raise Exception('Citation must be a Citation of the Source being cited')
template_handle = source_cache.get_template()
if template_handle is None:
template_cache = None
return
template_cache = db.get_template_from_handle(template_handle)
attr_list = source_cache.get_attribute_list() + citation.get_attribute_list()
date_citation = citation.get_date_object()
else:
# Source and no citation
source_cache = source
template_handle = source_cache.get_template()
if template_handle is None:
template_cache = None
return
template_cache = db.get_template_from_handle(template_handle)
attr_list = source_cache.get_attribute_list()
date_citation = None
# -----------------------------------------------------------------
# Construct the input dictionary
# First pre-load the dictionary with default settings for citations
if not citation:
for te in [x for x in template_cache.get_template_element_list()
if x.get_citation()]:
name = str(SrcAttributeType(te.get_name())).upper().replace(' ', '_')
if te.get_display():
val = te.get_display().upper().replace(' ', '_')
else:
val = name
input_dict[name] = "[" + val + "]"
# Now get the actual attribute values. store attributes in a dict last
# to first. this overwrites data so first attribute will be the one
# taken if duplicates are present
for input_attr in attr_list[::-1]:
typ = input_attr.get_type()
if typ.is_custom():
name = str(typ).upper().replace(' ', '_')
else:
name = typ.xml_str().upper().replace(' ', '_')
input_dict[name] = input_attr.get_value()
# if we haven't already got a value for the short attribute, we
# store the long attribute in the short attribute
if not name.endswith("(SHORT)"):
short_name = name + "_(SHORT)"
if input_dict.get(short_name) is None or \
(input_dict.get(short_name) and \
input_dict[short_name] == ("[" + short_name + "]")):
input_dict[short_name] = input_dict[name]
if date_citation and (not date_citation.is_empty()):
#we store the date of the citation
name = SrcAttributeType.DATE.upper().replace(' ', '_')
txt = str(date_citation)
input_dict[name] = txt
short_name = name + "_(SHORT)"
if input_dict.get(short_name) is None or \
(input_dict.get(short_name) and \
input_dict[short_name] == ("[" + short_name + "]")):
input_dict[short_name] = txt
# FIXME: REPOSITORY, REPOSITORY_ADDRESS and REPOSITORY_CALL_NUMBER all
# need to be added to the input_dict. See srctemplatetab.py
# _add_repo_entry()
def _reference(self, reftype):
"""
Compute the reference based on data present.
"""
global refL, refF, refS, input_dict, template_cache
if template_cache is None:
return ""
use_CSL = False
try:
import citeproc
if sys.version_info[0] >= 3:
use_CSL = True
except:
pass
if use_CSL:
# -----------------------------------------------------------------
# Construct the standard output-elements
self.output_dict = OrderedDict()
LOG.debug(self.get_map_dict())
LOG.debug("input_attributes \n" +
"".join(("%s: %s\n" % item) for item in list(input_dict.items())))
for key, val in list(self.get_map_dict().items()):
if not key.startswith("_"):
try:
self.output_dict[key] = val % DefaultBlank(input_dict)
except:
LOG.warn("key error with key %s; val %s; input_dict %s" %
(key, val, input_dict))
self.output_dict[key] = ""
LOG.debug("CSL_attributes \n" +
"".join(("%s: %s\n" % item) for item in list(self.output_dict.items())))
# Temporary fix for not implemented yet templates
if len(self.output_dict) == 0:
return ""
# Now fix CSL attributes that need special sub-elements
for name in ["author", "container_author", "some other name"]:
if name in self.output_dict:
self.output_dict[name] = [{"family": self.output_dict[name],
"given": ""}]
# -----------------------------------------------------------------
# Modify the output-elements to allow the standard Chicago style to
# format the citations close to Evidence Style
# literal dates are not specially treated. Date accessed is converted to
# a literal publication date to conform to how ESM formats the accessed
# date
if "accessed" in self.output_dict:
self.output_dict["issued"] = {'literal' : "accessed " + self.output_dict['accessed']}
del self.output_dict['accessed']
# Website is rendered as publisher_place to conform to how ESM renders
# it.
if "url" in self.output_dict:
self.output_dict["publisher_place"] = \
self.output_dict["publisher_place"] if "publisher_place" in self.output_dict \
else "" + self.output_dict["url"]
LOG.debug("self.output_dictibutes modified \n" +
"".join((" %s: %s\n" % item) for item in self.output_dict.items()))
try:
(refF, refS, refL) = self.get_CSL_references(self.output_dict)
if reftype == REF_TYPE_F:
return refF
elif reftype == REF_TYPE_S:
return refS
else:
return refL
except:
print(sys.exc_info()[0], sys.exc_info()[1])
return ""
else:
# -----------------------------------------------------------------
# Construct the standard output-elements
return (template_cache.get_map_element(reftype) %
DefaultKey(input_dict)) or ""
def get_CSL_references(self, CSL_attributes):
# Import the citeproc-py classes we'll use below.
from citeproc import CitationStylesStyle, CitationStylesBibliography
from citeproc import Citation, CitationItem
from citeproc import formatter, Locator
from citeproc.source.json import CiteProcJSON
# Process the JSON data to generate a citeproc-py BibliographySource.
if 'locator' in CSL_attributes:
loc = Locator("page", CSL_attributes["locator"])
import copy
c1 = copy.deepcopy(CSL_attributes)
c2 = copy.deepcopy(CSL_attributes)
bib_source = {"full": c1, "subs" : c2}
bib_source = {"full": c1}
# for key, entry in bib_source.items():
# print(key)
# for name, value in entry.items():
# print(' {}: {}'.format(name, value))
# load a CSL style (from the current directory)
bib_style = CitationStylesStyle('chicago-fullnote-bibliography-no-ibid.csl')
# Create the citeproc-py bibliography, passing it the:
# * CitationStylesStyle,
# * BibliographySource (CiteProcJSON in this case), and
# * a formatter (plain, html, or you can write a custom formatter)
bibliography = CitationStylesBibliography(bib_style, bib_source, formatter.plain)
# Processing citations in a document need to be done in two passes as for some
# CSL styles, a citation can depend on the order of citations in the
# bibliography and thus on citations following the current one.
# For this reason, we first need to register all citations with the
# CitationStylesBibliography.
if loc:
citation1 = Citation([CitationItem('full', locator=loc)])
citation2 = Citation([CitationItem('subs', locator=loc)])
else:
citation1 = Citation([CitationItem('full')])
citation2 = Citation([CitationItem('subs')])
citation1 = Citation([CitationItem('full')])
bibliography.register(citation1)
bibliography.register(citation2)
# In the second pass, CitationStylesBibliography can generate citations.
# CitationStylesBibliography.cite() requires a callback function to be passed
# along to be called in case a CitationItem's key is not present in the
# bilbiography.
def warn(citation_item):
print("WARNING: Reference with key '{}' not found in the bibliography."
.format(citation_item.key))
print('Citations')
print('---------')
print(bibliography.cite(citation1, warn))
print(bibliography.cite(citation2, warn))
# And finally, the bibliography can be rendered.
print('')
print('Bibliography')
print('------------')
print(bibliography.bibliography())
return(bibliography.cite(citation1, warn),
bibliography.cite(citation2, warn),
bibliography.bibliography())

View File

@ -348,14 +348,14 @@ def navigation_label(db, nav_type, handle):
elif nav_type == 'Source':
obj = db.get_source_from_handle(handle)
if obj:
label = obj.get_title()
label = obj.get_name()
elif nav_type == 'Citation':
obj = db.get_citation_from_handle(handle)
if obj:
label = obj.get_page()
label = obj.get_name()
src = db.get_source_from_handle(obj.get_reference_handle())
if src:
label = src.get_title() + " " + label
label = src.get_name() + " " + label
elif nav_type == 'Repository':
obj = db.get_repository_from_handle(handle)
if obj:

View File

@ -508,9 +508,9 @@ class ClipCitation(ClipHandleWrapper):
citation.get_note_list()))
srctxtlist = [note for note in notelist
if note.get_type() == NoteType.SOURCE_TEXT]
page = citation.get_page()
if not page:
page = _('not available|NA')
cname = citation.get_name()
if not cname:
cname = _('not available|NA')
text = ""
if len(srctxtlist) > 0:
text = " ".join(srctxtlist[0].get().split())
@ -519,8 +519,8 @@ class ClipCitation(ClipHandleWrapper):
text = cuni(text)
if len(text) > 60:
text = text[:60]+"..."
self._value = _("Volume/Page: %(pag)s -- %(sourcetext)s") % {
'pag' : page,
self._value = _("Citation Name: %(name)s -- %(sourcetext)s") % {
'name' : cname,
'sourcetext' : text,
}
@ -774,7 +774,7 @@ class ClipSourceLink(ClipHandleWrapper):
source = self._db.get_source_from_handle(self._handle)
if source:
self._title = source.get_gramps_id()
self._value = source.get_title()
self._value = source.get_name()
def is_valid(self):
data = pickle.loads(self._obj)

View File

@ -39,6 +39,7 @@ from .embeddedlist import EmbeddedList, TEXT_COL, MARKUP_COL, ICON_COL
from .addrembedlist import AddrEmbedList
from .attrembedlist import AttrEmbedList
from .backreflist import BackRefList
from .citedintab import CitedInTab
from .eventbackreflist import EventBackRefList
from .eventembedlist import EventEmbedList
from .familyattrembedlist import FamilyAttrEmbedList
@ -60,4 +61,5 @@ from .repoembedlist import RepoEmbedList
from .surnametab import SurnameTab
from .sourcebackreflist import SourceBackRefList
from .srcattrembedlist import SrcAttrEmbedList
from .srctemplatetab import SrcTemplateTab
from .webembedlist import WebEmbedList

View File

@ -65,10 +65,10 @@ class BackRefList(EmbeddedList):
def __init__(self, dbstate, uistate, track, obj, refmodel, callback=None):
self.obj = obj
self.connectid = None
EmbeddedList.__init__(self, dbstate, uistate, track,
_('_References'), refmodel)
self._callback = callback
self.connectid = self.model.connect('row-inserted', self.update_label)
self.track_ref_for_deletion("model")
def update_label(self, *obj):
@ -124,6 +124,12 @@ class BackRefList(EmbeddedList):
def get_data(self):
return self.obj
def _set_data(self, new_backref_list):
"""
Reset data associated with display tab. Only called in rebuild_callback!
"""
self.obj = new_backref_list
def column_order(self):
return ((1, 0), (1, 1), (1, 2))
@ -137,8 +143,7 @@ class BackRefList(EmbeddedList):
def edit_button_clicked(self, obj):
from .. import EditEvent, EditPerson, EditFamily, EditSource, \
EditPlace, EditMedia, EditRepository, \
EditCitation
EditPlace, EditMedia, EditRepository
(reftype, ref) = self.find_node()
if reftype == 'Person':
@ -162,7 +167,9 @@ class BackRefList(EmbeddedList):
elif reftype == 'Citation':
try:
citation = self.dbstate.db.get_citation_from_handle(ref)
EditCitation(self.dbstate, self.uistate, [], citation)
EditSource(self.dbstate, self.uistate, [],
self.dbstate.db.get_source_from_handle(
citation.get_reference_handle()), citation)
except WindowActiveError:
"""
Return the text used when citation cannot be edited
@ -206,3 +213,13 @@ class BackRefList(EmbeddedList):
EditRepository(self.dbstate, self.uistate, [], repo)
except WindowActiveError:
pass
def rebuild(self):
"""
Rebuild the view. This remakes the model, so we need to reconnect the
signal
"""
if not self.connectid is None:
self.model.disconnect(self.connectid)
EmbeddedList.rebuild(self)
self.connectid = self.model.connect('row-inserted', self.update_label)

View File

@ -97,14 +97,14 @@ class BackRefModel(Gtk.ListStore):
continue
gid = p.gramps_id
handle = p.handle
name = p.get_title()
name = p.get_name()
elif dtype == 'Citation':
p = self.db.get_citation_from_handle(ref[1])
if not p:
continue
gid = p.gramps_id
handle = p.handle
name = p.get_page()
name = p.get_name()
elif dtype == 'Event':
p = self.db.get_event_from_handle(ref[1])
if not p:

View File

@ -80,9 +80,9 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
#index = column in model. Value =
# (name, sortcol in model, width, markup/text, weigth_col
_column_names = [
(_('Title'), 0, 200, TEXT_COL, -1, None),
(_('Source Name'), 0, 200, TEXT_COL, -1, None),
(_('Author'), 1, 125, TEXT_COL, -1, None),
(_('Page'), 2, 100, TEXT_COL, -1, None),
(_('Citation Name'), 2, 140, TEXT_COL, -1, None),
(_('ID'), 3, 75, TEXT_COL, -1, None),
(_('Private'), 4, 30, ICON_COL, -1, 'gramps-lock')
]
@ -128,7 +128,7 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
def add_button_clicked(self, obj):
"""
Create a new Citation instance and call the EditCitation editor with
Create a new Citation instance and call the EditSource editor with
the new citation.
Called when the Add button is clicked.
@ -136,9 +136,9 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
This prevents the dialog from coming up twice on the same object.
"""
try:
from .. import EditCitation
EditCitation(self.dbstate, self.uistate, self.track,
Citation(), Source(),
from .. import EditSource
EditSource(self.dbstate, self.uistate, self.track,
Source(), Citation(),
self.add_callback, self.callertitle)
except WindowActiveError:
pass
@ -164,9 +164,9 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
if object:
if isinstance(object, Source):
try:
from .. import EditCitation
EditCitation(self.dbstate, self.uistate, self.track,
Citation(), object,
from .. import EditSource
EditSource(self.dbstate, self.uistate, self.track,
object, Citation(),
callback=self.add_callback,
callertitle=self.callertitle)
except WindowActiveError:
@ -175,10 +175,12 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
self.__blocked_text())
elif isinstance(object, Citation):
try:
from .. import EditCitation
EditCitation(self.dbstate, self.uistate, self.track,
object, callback=self.add_callback,
callertitle=self.callertitle)
from .. import EditSource
EditSource(self.dbstate, self.uistate, self.track,
self.dbstate.db.get_source_from_handle(
object.get_reference_handle()), object,
callback=self.add_callback,
callertitle=self.callertitle)
except WindowActiveError:
from ...dialog import WarningDialog
WarningDialog(_("Cannot share this reference"),
@ -198,7 +200,7 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
def edit_button_clicked(self, obj):
"""
Get the selected Citation instance and call the EditCitation editor
Get the selected Citation instance and call the EditSource editor
with the citation.
Called when the Edit button is clicked.
@ -209,9 +211,11 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
if handle:
citation = self.dbstate.db.get_citation_from_handle(handle)
try:
from .. import EditCitation
EditCitation(self.dbstate, self.uistate, self.track, citation,
callertitle = self.callertitle)
from .. import EditSource
EditSource(self.dbstate, self.uistate, self.track,
self.dbstate.db.get_source_from_handle(
citation.get_reference_handle()), citation,
callertitle = self.callertitle)
except WindowActiveError:
pass
@ -248,10 +252,12 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
object = self.dbstate.db.get_citation_from_handle(handle)
if isinstance(object, Citation):
try:
from .. import EditCitation
EditCitation(self.dbstate, self.uistate, self.track,
object, callback=self.add_callback,
callertitle=self.callertitle)
from .. import EditSource
EditSource(self.dbstate, self.uistate, self.track,
self.dbstate.db.get_source_from_handle(
object.get_reference_handle()),
object, callback=self.add_callback,
callertitle=self.callertitle)
except WindowActiveError:
from ...dialog import WarningDialog
WarningDialog(_("Cannot share this reference"),
@ -267,11 +273,11 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
object = self.dbstate.db.get_source_from_handle(handle)
if isinstance(object, Source):
try:
from .. import EditCitation
EditCitation(self.dbstate, self.uistate, self.track,
Citation(), object,
callback=self.add_callback,
callertitle=self.callertitle)
from .. import EditSource
EditSource(self.dbstate, self.uistate, self.track,
object, Citation(),
callback=self.add_callback,
callertitle=self.callertitle)
except WindowActiveError:
from ...dialog import WarningDialog
WarningDialog(_("Cannot share this reference"),

View File

@ -28,6 +28,14 @@
#-------------------------------------------------------------------------
from gi.repository import Gtk
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gramps.gen.utils.citeref import get_gedcom_author
#-------------------------------------------------------------------------
#
# CitationModel
@ -41,6 +49,6 @@ class CitationRefModel(Gtk.ListStore):
for handle in citation_list:
citation = self.db.get_citation_from_handle(handle)
src = self.db.get_source_from_handle(citation.get_reference_handle())
self.append(row=[src.title, src.author, citation.page,
self.append(row=[src.get_name(), get_gedcom_author(self.db, src), citation.get_name(),
citation.gramps_id, citation.get_privacy(),
handle, ])

View File

@ -0,0 +1,603 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
from __future__ import print_function
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
import sys
#-------------------------------------------------------------------------
#
# GTK libraries
#
#-------------------------------------------------------------------------
from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import Gtk
#-------------------------------------------------------------------------
#
# Gramps libraries
#
#-------------------------------------------------------------------------
from gramps.gen.errors import WindowActiveError
from gramps.gen.display.name import displayer as _nd
from gramps.gen.utils.db import (get_citation_referents, family_name,
get_participant_from_event)
from .grampstab import GrampsTab
from ...widgets import SimpleButton
_KP_ENTER = Gdk.keyval_from_name("KP_Enter")
_RETURN = Gdk.keyval_from_name("Return")
#-------------------------------------------------------------------------
#
# Classes
#
#-------------------------------------------------------------------------
class CitedInTab(GrampsTab):
"""
This class provides the tabpage for overview of where a source is
cited.
It shows these objects in a treeviewl and allows to load citations in the
top part of the source editor.
"""
def __init__(self, dbstate, uistate, track, src, cite_apply_callback,
cite_add_callback):
"""
@param dbstate: The database state. Contains a reference to
the database, along with other state information. The GrampsTab
uses this to access the database and to pass to and created
child windows (such as edit dialogs).
@type dbstate: DbState
@param uistate: The UI state. Used primarily to pass to any created
subwindows.
@type uistate: DisplayState
@param track: The window tracking mechanism used to manage windows.
This is only used to pass to generted child windows.
@type track: list
@param src: source which we manage in this tab
@type src: gen.lib.Source
"""
self.src = src
self.readonly = dbstate.db.readonly
self.srtdata = []
self.cite_apply_callback = cite_apply_callback
self.cite_add_callback = cite_add_callback
self.dirty_selection = False
GrampsTab.__init__(self, dbstate, uistate, track, _("Cited In"))
self._set_label()
def build_interface(self):
"""
method called in init of GrampsTab
"""
self.generate_data()
self.build_model()
self.setup_interface()
self.show_all()
self._selection_changed()
def get_icon_name(self):
return 'gramps-citation'
def is_empty(self):
"""
Return True if there is no data to show
"""
return len(self.srtdata) == 0
def setup_interface(self):
"""
Set all information on the widgets
* button tabs to load citation
* treeview in scrollable with info
"""
##print (self.srtdata)
##print(self.obj2citemap)
#create the load button, add it to a hbox, and add that box to the
#tab page
self.load_btn = SimpleButton(Gtk.STOCK_APPLY, self.apply_button_clicked)
self.load_btn.set_label(_("Load Citation"))
self.load_btn.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_APPLY,
Gtk.IconSize.BUTTON))
#self.load_btn.set_always_show_image(True)
self.load_btn.set_tooltip_text(_("Apply a selected citation so as to"
" edit it in the top part of this interface"))
self.add_btn = SimpleButton(Gtk.STOCK_ADD, self.add_button_clicked)
self.add_btn.set_label(_("Add New Cition"))
self.add_btn.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_ADD,
Gtk.IconSize.BUTTON))
self.add_btn.set_tooltip_text(_("Add a new citation to this source"))
self.edit_btn = SimpleButton(Gtk.STOCK_EDIT, self.edit_button_clicked)
self.edit_btn.set_label(_("Edit Cited In"))
self.edit_btn.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_EDIT,
Gtk.IconSize.BUTTON))
self.edit_btn.set_tooltip_text(_("Edit the object containing the"
" selected citation"))
hbox = Gtk.HBox()
hbox.set_spacing(6)
hbox.pack_start(self.load_btn, False, True, 0)
hbox.pack_start(self.add_btn, False, True, 0)
hbox.pack_start(self.edit_btn, False, True, 0)
hbox.show_all()
self.pack_start(hbox, False, True, 0)
if self.dbstate.db.readonly:
self.load_btn.set_sensitive(False)
# create the tree, turn on rule hinting and connect the
# button press to the double click function.
self.tree = Gtk.TreeView()
self.tree.set_rules_hint(True)
self.tree.connect('button_press_event', self.double_click)
self.tree.connect('key_press_event', self.key_pressed)
self.make_columns()
self.tree.set_model(self.model)
self.selection = self.tree.get_selection()
self.selection.connect('changed', self._selection_changed)
# create the scrolled window, and attach the treeview
scroll = Gtk.ScrolledWindow()
scroll.set_shadow_type(Gtk.ShadowType.IN)
scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scroll.add(self.tree)
#add this to the tab
self.pack_start(scroll, True, True, 0)
def generate_data(self):
"""
Obtain all objects this source is cited in
"""
self.srtdata = []
self.obj2citemap = {}
if not self.src.handle:
#new object
return
db = self.dbstate.db
#we don't nest calls to find_backlink_handles, so obtain first for
#the source, then in loop for citations
listtopobj = [x for x in db.find_backlink_handles(self.src.handle)]
for (cobjclass, chandle) in listtopobj:
#this will only be citations!
##print ('t1', cobjclass, chandle)
if cobjclass == 'Citation':
cite = db.get_citation_from_handle(chandle)
has_backlink = False
for (objclass, handle) in db.find_backlink_handles(chandle):
##print ('t2', objclass, handle)
has_backlink = True
if objclass == 'Person':
ref = db.get_person_from_handle(handle)
self.__add_person(ref, cite)
elif objclass == 'Family':
ref = db.get_family_from_handle(handle)
self.__add_family(ref, cite)
elif objclass == 'Event':
ref = db.get_event_from_handle(handle)
self.__add_event(ref, cite)
elif objclass == 'Place':
ref = db.get_place_from_handle(handle)
self.__add_place(ref, cite)
elif objclass == 'Repository':
ref = db.get_repository_from_handle(handle)
self.__add_repo(ref, cite)
elif objclass in ['MediaObject', 'Media']:
ref = db.get_object_from_handle(handle)
self.__add_media(ref, cite)
else:
#most strange, not possible for citation there!
print ("Error in citedintab.py: citation referenced "
"outside citation. Run rebuild reference tables")
if not has_backlink:
self.__add_cite(cite)
else:
#most strange, not possible !
print ("Error in citedintab.py: source referenced "
"outside citation. Run rebuild reference tables")
self.srtdata = sorted(self.srtdata, key=lambda x: glocale.sort_key(x[0]))
def __add_object(self, obj, cite, descr_obj, shortdescr, objname):
"""
obtain citation data of the object and store here so it can be shown
in a treeview. If obj=None, an unused citation...
"""
if obj is None:
#adding of a citation which is part of not a singel object. The
#citation is added under None.
if not None in self.obj2citemap:
self.obj2citemap[None] = {'prim': [], 'sec': [], 'subsec': []}
#add for sorting in the treeview to map
self.srtdata.append((descr_obj, None, shortdescr, objname))
#add this citation
self.obj2citemap[None]['prim'].append(cite.handle)
return
if not obj.handle in self.obj2citemap:
self.obj2citemap[obj.handle] = {'prim': [], 'sec': [], 'subsec': []}
#add for sorting in the treeview to map
self.srtdata.append((descr_obj, obj.handle, shortdescr, objname))
#we analyse the object to determine where the citation is used.
if hasattr(obj, 'get_citation_list'):
for citehandle in obj.get_citation_list():
##print ('t4', citehandle)
if cite.handle == citehandle:
self.obj2citemap[obj.handle]['prim'].append(cite.handle)
#now search the citation in secondary objects. This can maximally be
# 2 levels deep, eg citation in attribute of eventref
for objsec in obj.get_citation_child_list():
##print ('t5', objsec)
if hasattr(objsec, 'get_citation_list'):
for citehandle in objsec.get_citation_list():
##print ('t6', citehandle)
if cite.handle == citehandle:
self.obj2citemap[obj.handle]['sec'].append(
(cite.handle, self.format_sec_obj(objsec)))
if hasattr(objsec, 'get_citation_child_list'):
for objsubsec in objsec.get_citation_child_list():
##print ('t7', objsubsec)
#eg attribute of eventref of person
for citehandle in objsubsec.get_citation_list():
if cite.handle == citehandle:
self.obj2citemap[obj.handle]['subsec'].append(
(cite.handle,
_('%(first)s -> %(sec)s') % {
'first': self.format_sec_obj(objsec),
'sec' : self.format_sec_obj(objsubsec)}))
def __add_person(self, obj, cite):
"""
see __add_object
"""
name = _nd.display_name(obj.get_primary_name())
self.__add_object(obj, cite, _("Person %(id)s: %(descr)s") % {
'id': obj.get_gramps_id(),
'descr': name}, _("Cited in Person"), "Person")
def __add_family(self, obj, cite):
"""
see __add_object
"""
name = family_name(obj, self.dbstate.db, _("Unknown Family"))
self.__add_object(obj, cite, _("Family %(id)s: %(descr)s") % {
'id': obj.get_gramps_id(),
'descr': name}, _("Cited in Family"), "Family")
def __add_event(self, obj, cite):
"""
see __add_object
"""
who = get_participant_from_event(self.dbstate.db, obj.handle)
desc = obj.get_description()
event_name = obj.get_type()
if desc:
event_name = '%s - %s' % (event_name, desc)
if who:
event_name = '%s - %s' % (event_name, who)
name = _('Event %(id)s: %(descr)s') % {
'id': obj.get_gramps_id(),
'descr': event_name}
self.__add_object(obj, cite, name, _("Cited in Event"), "Event")
def __add_place(self, obj, cite):
"""
see __add_object
"""
self.__add_object(obj, cite, _('Place %(id)s: %(descr)s') % {
'id': obj.get_gramps_id(),
'descr': obj.get_title()}, _("Cited in Place"), "Place")
def __add_repo(self, obj, cite):
"""
see __add_object
"""
self.__add_object(obj, cite, _('Repository %(id)s: %(descr)s') % {
'id': obj.get_gramps_id(),
'descr': obj.get_name()}, _("Cited in Repository"), "Repository")
def __add_media(self, obj, cite):
"""
see __add_object
"""
name = obj.get_description().strip()
if not name:
name = obj.get_path()
if not name:
name = obj.get_mime_type()
self.__add_object(obj, cite, _('Media %(id)s: %(descr)s') % {
'id': obj.get_gramps_id(),
'descr': name}, _("Cited in Media"), "Media")
def __add_cite(self, cite):
"""
see __add_object
"""
self.__add_object(None, cite, _('Unused Citations'),
_('Unused Citation'), "Citation")
def format_sec_obj(self, objsec):
"""
text for treeview on citation in secondary object
"""
classname = objsec.__class__.__name__
classobj = classname
descr = '' #TODO TO SET THIS !!
if classname == "Address":
descr = objsec.get_street()
classobj = _("Address")
elif classname == "Attribute":
descr = str(objsec.get_type())
classobj = _("Attribute")
elif classname == "ChildRef":
ref = objsec.get_reference_handle()
person = self.dbstate.db.get_person_from_handle(ref)
descr = _nd.display_name(person.get_primary_name())
classobj = _("Child")
elif classname == "EventRef":
ref = objsec.get_reference_handle()
event = self.dbstate.db.get_event_from_handle(ref)
descr = str(event.get_type())
classobj = _("Event Reference")
elif classname == "LdsOrd":
descr = objsec.type2str()
classobj = _("LDS Ordinance")
elif classname == "MediaRef":
ref = objsec.get_reference_handle()
obj = self.dbstate.db.get_object_from_handle(ref)
descr = obj.get_description().strip()
if not descr:
descr = obj.get_path()
if not descr:
descr = obj.get_mime_type()
classobj = _("Media Reference")
elif classname == "Name":
descr = _nd.display_name(objsec)
classobj = _("Name")
elif classname == "PersonRef":
ref = objsec.get_reference_handle()
person = self.dbstate.db.get_person_from_handle(ref)
if person is None:
descr = ref
else:
descr = _nd.display_name(person.get_primary_name())
descr = _("%(secobj)s: %(descr)s") % {
'secobj': classobj,
'descr' : descr}
return descr
def double_click(self, obj, event):
"""
Handles the double click on list. If the double click occurs,
the apply button handler is called
"""
if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1:
self.apply_button_clicked(obj)
def key_pressed(self, obj, event):
"""
Handles the return key being pressed on list. If the key is pressed,
the Load button handler is called
"""
if event.type == Gdk.EventType.KEY_PRESS:
#print 'key pressed', event.keyval, event.get_state(), _ADD
if event.keyval in (_RETURN, _KP_ENTER):
self.apply_button_clicked(obj)
return True
else:
return GrampsTab.key_pressed(self, obj, event)
return False
def apply_button_clicked(self, obj):
"""
Function called with the Load button is clicked.
"""
sel = self.get_selected()
if sel[0]:
self.cite_apply_callback(sel[0])
def add_button_clicked(self, obj):
"""
Function called with the Add button is clicked. This function
should be overridden by the derived class.
"""
self.cite_add_callback()
def edit_button_clicked(self, obj):
"""
Function called with the Edit button is clicked.
"""
sel = self.get_selected()
ref = sel[1]
reftype = sel[2]
if not ref:
return
from .. import (EditEvent, EditPerson, EditFamily, EditPlace,
EditMedia, EditRepository)
if reftype == 'Person':
try:
person = self.dbstate.db.get_person_from_handle(ref)
EditPerson(self.dbstate, self.uistate, [], person)
except WindowActiveError:
pass
elif reftype == 'Family':
try:
family = self.dbstate.db.get_family_from_handle(ref)
EditFamily(self.dbstate, self.uistate, [], family)
except WindowActiveError:
pass
elif reftype == 'Place':
try:
place = self.dbstate.db.get_place_from_handle(ref)
EditPlace(self.dbstate, self.uistate, [], place)
except WindowActiveError:
pass
elif reftype == 'Media':
try:
obj = self.dbstate.db.get_object_from_handle(ref)
EditMedia(self.dbstate, self.uistate, [], obj)
except WindowActiveError:
pass
elif reftype == 'Event':
try:
event = self.dbstate.db.get_event_from_handle(ref)
EditEvent(self.dbstate, self.uistate, [], event)
except WindowActiveError:
pass
elif reftype == 'Repository':
try:
repo = self.dbstate.db.get_repository_from_handle(ref)
EditRepository(self.dbstate, self.uistate, [], repo)
except WindowActiveError:
pass
def build_model(self):
"""
set up the model the treeview will use based on the data
"""
# store (citationhandle, primobjhandle, name, citationgid, index, classname)
# here, depending on the leve, name will be primobjname, secobjname, or
# subsecobjname
# citationhandle will be '' for rows which create sublevels
self.model = Gtk.TreeStore(str, str, str, str, int, str)
if sys.version_info[0] < 3:
self.idle = GObject.idle_add(self.load_model().next)
else:
self.idle = GObject.idle_add(self.load_model().__next__)
def load_model(self):
"""
To make sure source editor is responsive, we use idle_add to
build the model.
WARNING: a consequence of above is that loading can still be happening
while the GUI using this model is no longer used. Disconnect any
methods before closing the GUI.
"""
for (descr, primhandle, shortdescr, objname) in self.srtdata:
data = self.obj2citemap[primhandle]
#top level node
iter = self.model.append(None, ['', primhandle, descr, '', -1, objname])
for ind, chandle in enumerate(data['prim']):
citation = self.dbstate.db.get_citation_from_handle(chandle)
self.model.append(iter, [chandle, primhandle, shortdescr,
citation.get_gramps_id(), ind, objname])
base = len(data['prim'])
for ind, val in enumerate(data['sec']):
chandle, secdescr = val
citation = self.dbstate.db.get_citation_from_handle(chandle)
self.model.append(iter, [chandle, primhandle, secdescr,
citation.get_gramps_id(), base+ind, objname])
base += len(data['sec'])
for ind, val in enumerate(data['subsec']):
chandle, subsecdescr = val
citation = self.dbstate.db.get_citation_from_handle(chandle)
self.model.append(iter, [chandle, primhandle, subsecdescr,
citation.get_gramps_id(), base+ind, objname])
yield True
#only now can we expand all nodes:
self.tree.expand_all()
yield False
def make_columns(self):
#make the columns in the treeview
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(_("Cited in"), renderer, text=2)
self.tree.append_column(column)
column = Gtk.TreeViewColumn(_("Citation"), renderer, text=3)
self.tree.append_column(column)
def get_selected(self):
"""
Return the (citation_handle, primary_object_handle, classname_prim_obj)
associated with the selected row in the model.
If no selection has been made, None is returned.
If not on a citation, citation_handle will be empty string ''
"""
(model, iter) = self.selection.get_selected()
# store contains: (citationhandle, primobjhandle, name, citationgid, index)
if iter:
return (model.get_value(iter, 0), model.get_value(iter, 1),
model.get_value(iter, 5))
return None
def _selection_changed(self, obj=None):
"""
Attached to the selection's 'changed' signal.
Should we ever want to (in)activate the buttons depending on what is
selected, we should do it here
"""
# This method is called as callback on change, and can be called
# explicitly, dirty_selection must make sure they do not interact
if self.dirty_selection:
return
if self.get_selected() is not None:
#change what buttons are possible
self.load_btn.set_sensitive(True)
self.edit_btn.set_sensitive(True)
else:
self.load_btn.set_sensitive(False)
self.edit_btn.set_sensitive(False)
def rebuild(self):
"""
Rebuilds the data in the tab by creating a new model,
using the build_model function
"""
offset = self.tree.get_visible_rect()
#during rebuild, don't do _selection_changed
self.dirty_selection = True
(model, node) = self.selection.get_selected()
selectedpath = None
if node:
selectedpath = model.get_path(node)
self.tree.set_model(None)
if self.model and hasattr(self.model, 'destroy'):
self.model.destroy()
#actually rebuild things
self.generate_data()
self.build_model()
self.tree.set_model(self.model)
#reset previous select
if not selectedpath is None:
self.selection.select_path(selectedpath)
#model and tree are reset, allow _selection_changed again, and force it
self.dirty_selection = False
self._selection_changed()
if self.tree.get_realized():
GObject.idle_add(self.tree.scroll_to_point, offset.x, offset.y)

View File

@ -448,6 +448,17 @@ class EmbeddedList(ButtonTab):
"""
raise NotImplementedError
def _set_data(self):
"""
Reset the data associated with the list. This is typically
a list of objects.
This should be overridden in the derived classes. This method should
only be given if it is needed to call rebuild_callback with new_list
parameter. Don't use it otherwise!
"""
raise NotImplementedError
def column_order(self):
"""
Specifies the column order for the columns. This should be
@ -526,7 +537,7 @@ class EmbeddedList(ButtonTab):
column = Gtk.TreeViewColumn(name, self.pb_renderer)
column.set_cell_data_func(self.pb_renderer, self.icon_func, pair[1])
else:
raise NotImplementedError, 'Unknown column type'
raise NotImplementedError('Unknown column type')
if col_icon is not None:
image = Gtk.Image()
image.set_from_stock(col_icon, Gtk.IconSize.MENU)
@ -609,13 +620,15 @@ class EmbeddedList(ButtonTab):
@type prebuildpath: tree path
"""
pass
def rebuild_callback(self):
def rebuild_callback(self, new_list=None):
"""
The view must be remade when data changes outside this tab.
Use this method to connect to after a db change. It makes sure the
data is obtained again from the present object and the db what is not
present in the obj, and the view rebuild
"""
if new_list is not None:
self._set_data(new_list)
self.changed = True
self.rebuild()

View File

@ -365,6 +365,18 @@ class GalleryTab(ButtonTab, DbGUIElement):
"""
self.rebuild()
def rebuild_callback(self, new_list=None):
"""
The view must be remade when data changes outside this tab.
Use this method to connect to after a db change. It makes sure the
data is obtained again from the present object and the db what is not
present in the obj, and the view rebuild
"""
if new_list is not None:
self.media_list = new_list
self.changed = True
self.rebuild()
def media_delete(self, del_media_handle_list):
"""
Outside of this tab media objects have been deleted. Check if tab

View File

@ -118,8 +118,8 @@ class GrampsTab(Gtk.VBox):
else:
func = Gtk.Image.new_from_stock
name = icon
self.tab_image = func(name, Gtk.IconSize.MENU)
self.tab_image = func(name, Gtk.IconSize.MENU)
self.track_ref_for_deletion("tab_image")
self.label = Gtk.Label(label=self.tab_name)
self.track_ref_for_deletion("label")

View File

@ -81,10 +81,11 @@ class NoteTab(EmbeddedList, DbGUIElement):
]
def __init__(self, dbstate, uistate, track, data, callertitle=None,
notetype=None):
notetype=None, callback_notebase_changed=None):
self.data = data
self.callertitle = callertitle
self.notetype = notetype
self.callback_notebase_changed = callback_notebase_changed
EmbeddedList.__init__(self, dbstate, uistate, track,
_("_Notes"), NoteModel, share_button=True,
move_buttons=True)
@ -114,6 +115,12 @@ class NoteTab(EmbeddedList, DbGUIElement):
"""
return self.data
def _set_data(self, new_data):
"""
Reset data associated with display tab. Only called in rebuild_callback!
"""
self.data = new_data
def column_order(self):
"""
Return the column order of the columns in the display tab.
@ -150,6 +157,8 @@ class NoteTab(EmbeddedList, DbGUIElement):
self.changed = True
self.rebuild()
GObject.idle_add(self.tree.scroll_to_cell, len(data) - 1)
if self.callback_notebase_changed:
self.callback_notebase_changed()
def edit_button_clicked(self, obj):
"""

View File

@ -91,6 +91,12 @@ class SrcAttrEmbedList(EmbeddedList):
def get_data(self):
return self.data
def _set_data(self, new_data):
"""
Reset data associated with display tab. Only called in rebuild_callback!
"""
self.data = new_data
def column_order(self):
return ((1, 2), (1, 0), (1, 1))

View File

@ -0,0 +1,472 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# GTK libraries
#
#-------------------------------------------------------------------------
from gi.repository import Gdk
from gi.repository import Gtk
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
LOG = logging.getLogger('.template')
#-------------------------------------------------------------------------
#
# Gramps libraries
#
#-------------------------------------------------------------------------
from gramps.gen.lib.srcattrtype import SrcAttributeType
from gramps.gen.lib import SrcAttribute, SrcTemplate
from gramps.gen.plug.report.utils import get_address_ref_str
from ...autocomp import StandardCustomSelector
from ...widgets.srctemplatetreeview import SrcTemplateTreeView
from ...widgets import (UndoableEntry, MonitoredEntryIndicator, MonitoredDate,
ValidatableMaskedEntry)
from .grampstab import GrampsTab
from gramps.gen.constfunc import STRTYPE
from gramps.gen.utils.citeref import get_gedcom_title
#-------------------------------------------------------------------------
#
# Classes
#
#-------------------------------------------------------------------------
class SrcTemplateTab(GrampsTab):
"""
This class provides the tabpage for template generation of attributes.
"""
def __init__(self, dbstate, uistate, track, src, glade,
callback_src_changed):
"""
@param dbstate: The database state. Contains a reference to
the database, along with other state information. The GrampsTab
uses this to access the database and to pass to and created
child windows (such as edit dialogs).
@type dbstate: DbState
@param uistate: The UI state. Used primarily to pass to any created
subwindows.
@type uistate: DisplayState
@param track: The window tracking mechanism used to manage windows.
This is only used to pass to generted child windows.
@type track: list
@param src: source which we manage in this tab
@type src: gen.lib.Source
@param glade: glade objects with the needed widgets
"""
self.src = src
self.glade = glade
self.callback_src_changed = callback_src_changed
self.readonly = dbstate.db.readonly
self.db = dbstate.db
self.autoset_title = False
GrampsTab.__init__(self, dbstate, uistate, track, _("Source Template"))
eventbox = Gtk.EventBox()
widget = self.glade.get_object('gridtemplate')
eventbox.add(widget)
self.pack_start(eventbox, True, True, 0)
self._set_label(show_image=False)
widget.connect('key_press_event', self.key_pressed)
self.tmplfields = TemplateFields(self.dbstate.db, self.uistate,
self.track, self.glade.get_object('gridfields'),
self.src, None, self.callback_src_changed, None)
self.autotitle = self.glade.get_object("autotitle_checkbtn")
#self.vbox_fields_label = self.glade.get_object('fields_01')
#self.vbox_fields_input = self.glade.get_object('fields_02')
self.setup_interface(self.glade.get_object('scrolledtemplates'))
self.show_all()
def make_active(self):
"""
Called by using editor to focus on correct field in the tab
"""
self.temp_tv.grab_focus()
def is_empty(self):
"""
Override base class
"""
return False
def setup_interface(self, scrolled):
"""
Set all information on the widgets
* template selection
* setting attribute fields
:param scrolled: GtkScrolledWindow to which to add treeview with templates
"""
templ = self.src.get_template()
self.temp_tv = SrcTemplateTreeView(templ, self.db,
sel_callback=self.on_template_selected)
scrolled.add(self.temp_tv)
#autotitle checkbox
self.autotitle.set_active(self.autotitle_get_orig_val())
self.autotitle.set_sensitive(not self.dbstate.db.readonly)
self.autotitle.connect('toggled', self.autotitle_on_toggle)
def autotitle_get_orig_val(self):
"""
If title of the source is what we would set with autotitle, we set
the checkbox to true. Otherwise to False
"""
title = get_gedcom_title(self.dbstate.db, self.src)
if self.src.get_title() == title:
self.autoset_title = True
else:
self.autoset_title = False
return self.autoset_title
def autotitle_on_toggle(self, obj):
""" the autoset_title attribute will be used in editsource to
determine that title must be set
"""
self.autoset_title = obj.get_active()
#it might be that the title must be changed, so we trigger the callback
# which will update the title in the source object
self.callback_src_changed()
def on_template_selected(self, key):
"""
Selected template changed, we save this and update interface
"""
self.src.set_template(key)
self.callback_src_changed(templatechanged=True)
#a predefined template,
self.tmplfields.reset_template_fields(key)
#-------------------------------------------------------------------------
#
# TemplateFields Class
#
#-------------------------------------------------------------------------
class TemplateFields(object):
"""
Class to manage fields of a source template.
Can be used on source and on citation level.
"""
def __init__(self, db, uistate, track, grid, src, cite,
callback_src_changed, callback_cite_changed):
"""
grid: The Gtk.Grid that should hold the fields
src : The source to which the fields belong
cite: The citation to which the fields belong (set None if only source)
"""
self.gridfields = grid
self.db = db
self.uistate = uistate
self.track = track
self.src = src
self.cite = cite
self.callback_src_changed = callback_src_changed
self.callback_cite_changed = callback_cite_changed
#storage
self.lbls = []
self.inpts = []
self.btns = []
self.monentry = []
def reset_template_fields(self, handle):
"""
Method that constructs the actual fields where user can enter data.
handle is the handle of the template.
"""
show_default_cite_fields = False #we don't do this for now
if handle:
template = self.db.get_template_from_handle(handle)
telist = template.get_template_element_list()
else:
LOG.warn("template not defined %s" % handle)
return
# first remove old fields
for lbl in self.lbls:
self.gridfields.remove(lbl)
for inpt in self.inpts:
self.gridfields.remove(inpt)
for mon in self.monentry:
del mon
for btn in self.btns:
self.gridfields.remove(btn)
self.lbls = []
self.inpts = []
self.monentry = []
self.btns = []
row = 1
# now add new fields
long_source_fields = [x for x in telist
if not x.get_short() and not x.get_citation()]
short_source_fields = [x for x in telist
if x.get_short() and not x.get_citation()]
long_citation_fields = [x for x in telist
if not x.get_short() and x.get_citation()]
short_citation_fields = [x for x in telist
if x.get_short() and x.get_citation()]
if self.cite is None:
# source long fileds
for te in long_source_fields:
self._add_entry(row, te.get_name(), _(te.get_display()),
_(te.get_hint()), _(te.get_tooltip()))
row += 1
# now add short source fields (if any)
if short_source_fields:
self.gridfields.insert_row(row)
lbl = Gtk.Label('')
lbl.set_markup(_("<b>Optional Short Versions:</b>"))
lbl.set_halign(Gtk.Align.START)
self.gridfields.attach(lbl, 0, row-1, 2, 1)
self.lbls.append(lbl)
row += 1
for te in short_source_fields:
self._add_entry(row, te.get_name(), _(te.get_display()),
_(te.get_hint()), _(te.get_tooltip()))
row += 1
# At source level add a header for the default citation values
if (long_citation_fields+short_citation_fields) and \
show_default_cite_fields:
self.gridfields.insert_row(row)
lbl = Gtk.Label('')
lbl.set_markup(_("<b>Optional Default Citation Fields:</b>"))
lbl.set_halign(Gtk.Align.START)
self.gridfields.attach(lbl, 0, row-1, 2, 1)
self.lbls.append(lbl)
row += 1
# Either show citation fields or at source level the default values
if show_default_cite_fields or (not self.cite is None):
for te in long_citation_fields:
self._add_entry(row, te.get_name(), _(te.get_display()),
_(te.get_hint()), _(te.get_tooltip()))
row += 1
# Finally the short citation fields (if any)
if not self.cite is None:
#we indicate with a text these are the short versions
if short_citation_fields:
self.gridfields.insert_row(row)
lbl = Gtk.Label('')
lbl.set_markup(_("<b>Optional Short Versions:</b>"))
lbl.set_halign(Gtk.Align.START)
self.gridfields.attach(lbl, 0, row-1, 2, 1)
self.lbls.append(lbl)
row += 1
if show_default_cite_fields or (not self.cite is None):
for te in short_citation_fields:
self._add_entry(row, te.get_name(), _(te.get_display()),
_(te.get_hint()), _(te.get_tooltip()))
row += 1
self.gridfields.show_all()
def _add_entry(self, row, srcattrtype, alt_label, hint=None, tooltip=None):
"""
Add an entryfield to the grid of fields at row row, to edit the given
srcattrtype value. Use alt_label if given to indicate the field
(otherwise the srcattrtype string description is used)
Note srcattrtype should actually be the English name of the type!
"""
self.gridfields.insert_row(row)
#setup label
if alt_label:
label = _(alt_label)
else:
label = _(srcattrtype)
lbl = Gtk.Label(_("%s:") % label)
lbl.set_halign(Gtk.Align.START)
self.gridfields.attach(lbl, 0, row-1, 1, 1)
self.lbls.append(lbl)
if srcattrtype in [SrcAttributeType.REPOSITORY,
SrcAttributeType.REPOSITORY_ADDRESS,
SrcAttributeType.REPOSITORY_CALL_NUMBER]:
self._add_repo_entry(srcattrtype, row)
elif self.cite and \
srcattrtype == SrcAttributeType.DATE:
#the DATE on level citation is not an attribute but stored
#as date in the citation
self._add_cite_date(row)
else:
#setup entry
self._add_normal_entry(srcattrtype, row, hint, tooltip)
def _add_normal_entry(self, srcattrtype, row, hint, tooltip):
"""
add an entryfield that sets the required SrcAttribute
"""
inpt = UndoableEntry()
inpt.set_halign(Gtk.Align.FILL)
inpt.set_hexpand(True)
if tooltip:
inpt.set_tooltip_text(_(tooltip))
self.gridfields.attach(inpt, 1, row-1, 1, 1)
self.inpts.append(inpt)
if self.cite:
MonitoredEntryIndicator(inpt, self.set_cite_field, self.get_cite_field,
_(hint or ""),
read_only=self.db.readonly,
parameter=_(srcattrtype))
else:
MonitoredEntryIndicator(inpt, self.set_src_field, self.get_src_field,
_(hint or ""),
read_only=self.db.readonly,
parameter=_(srcattrtype))
def _add_cite_date(self, row):
"""
Add the entry corresponding to the date field on citation level
"""
inpt = ValidatableMaskedEntry()
inpt.set_halign(Gtk.Align.FILL)
inpt.set_hexpand(True)
inpt.set_tooltip_text("The date of the entry in the source you are"
" referencing with this citation. E.g. the date a house was visited"
" during a census , or the date an entry was made in a"
" birth log/registry")
self.gridfields.attach(inpt, 1, row-1, 1, 1)
self.inpts.append(inpt)
btn = self.make_btn('gramps-date')
self.gridfields.attach(btn, 2, row-1, 1, 1)
self.btns.append(btn)
MonitoredDate(
inpt,
btn,
self.cite.get_date_object(),
self.uistate,
self.track,
self.db.readonly)
def _add_repo_entry(self, srcattrtype, row):
"""
Add a field that obtains info from repository
"""
repo_list = self.src.get_reporef_list()
if repo_list:
reporef = repo_list[0]
repo = self.db.get_repository_from_handle(reporef.get_reference_handle())
else:
reporef = None
repo = None
if not reporef:
lbl = Gtk.Label("")
lbl.set_markup(_("<i>No repository added to the source</i>"))
lbl.set_halign(Gtk.Align.START)
self.gridfields.attach(lbl, 1, row-1, 1, 1)
self.lbls.append(lbl)
else:
#we show the data as defined by the field
if srcattrtype == SrcAttributeType.REPOSITORY:
text = repo.get_name()
elif srcattrtype == SrcAttributeType.REPOSITORY_ADDRESS:
text = _("<i>No Address attached to the repository</i>")
addrlist = repo.get_address_list()
if addrlist:
text = get_address_ref_str(addrlist[0])
elif srcattrtype == SrcAttributeType.REPOSITORY_CALL_NUMBER:
text = reporef.get_call_number().strip()
if not text:
text = _("<i>No call number given in the repository reference</i>")
lbl = Gtk.Label("")
lbl.set_markup(text)
lbl.set_halign(Gtk.Align.START)
self.gridfields.attach(lbl, 1, row-1, 1, 1)
self.lbls.append(lbl)
def make_btn(self, stockid):
"""
Create a button for use with a stock image
"""
image = Gtk.Image.new_from_stock('gramps-date', Gtk.IconSize.MENU)
btn = Gtk.Button()
btn.set_image(image)
btn.set_always_show_image(True)
return btn
def get_src_field(self, srcattrtype):
return self.__get_field(srcattrtype, self.src)
def get_cite_field(self, srcattrtype):
return self.__get_field(srcattrtype, self.cite)
def __get_field(self, srcattrtype, obj):
"""
Obtain srcattribute with type srcattrtype, where srcattrtype is the
English name of the attribute!
"""
val = ''
for attr in obj.attribute_list:
if attr.get_type() == srcattrtype:
val = attr.get_value()
break
return val
def set_src_field(self, value, srcattrtype):
self.__set_field(value, srcattrtype, self.src)
#indicate source object changed
self.callback_src_changed()
def set_cite_field(self, value, srcattrtype):
self.__set_field(value, srcattrtype, self.cite)
#indicate source object changed
self.callback_cite_changed()
def __set_field(self, value, srcattrtype, obj):
"""
Set attribute of source of type srcattrtype (which is the English name)
to value. If not present, create attribute. If value == '', remove
"""
value = value.strip()
foundattr = None
for attr in obj.attribute_list:
if attr.get_type() == srcattrtype:
attr.set_value(value)
foundattr = attr
break
if foundattr and value == '':
obj.remove_attribute(foundattr)
if foundattr is None and value != '':
foundattr = SrcAttribute()
foundattr.set_type(srcattrtype)
foundattr.set_value(value)
obj.add_attribute(foundattr)

View File

@ -102,8 +102,10 @@ class EditAttributeRoot(EditSecondary):
self.top.get_object("private"),
self.obj, self.db.readonly)
attrcmb = self.top.get_object("attr_menu")
attrcmb.set_wrap_width(2)
self.type_selector = MonitoredDataType(
self.top.get_object("attr_menu"),
attrcmb,
self.obj.set_type,
self.obj.get_type,
self.db.readonly,

View File

@ -58,8 +58,31 @@ from ..glade import Glade
# EditCitationclass
#
#-------------------------------------------------------------------------
class EditCitation(EditPrimary):
"""
Create an Editor for Citation object. This actually opens the source!
This class is called both to edit the Citation Primary object
and to edit references from other objects to citations.
@param callertitle: Text passed by calling object to add to title
@type callertitle: str
"""
def __init__(self, dbstate, uistate, track, citation, callback=None,
callertitle = None):
from .editsource import EditSource
if citation.handle:
EditSource(dbstate, uistate, track, dbstate.db.get_source_from_handle(
citation.get_reference_handle()), citation,
callback, callertitle)
else:
#we don't allow this, caller should be changed to call EditSource
#directly !
raise NotImplementedError("Depracated call")
class EditCitationOld(EditPrimary):
"""
Create an EditCitation window. Associate a citation with the window.
@ -298,7 +321,7 @@ class EditCitation(EditPrimary):
self.db.readonly)
self.author = MonitoredEntry(
self.glade.get_object('author'), self.source.set_author,
self.glade.get_object('author'), self.eat_it,
self.source.get_author,self.db.readonly)
self.gid = MonitoredEntry(
@ -323,9 +346,15 @@ class EditCitation(EditPrimary):
self.source.get_abbreviation,self.db.readonly)
self.pubinfo = MonitoredEntry(
self.glade.get_object('pub_info'), self.source.set_publication_info,
self.glade.get_object('pub_info'), self.eat_it,
self.source.get_publication_info,self.db.readonly)
def eat_it(self, *pars):
"""
TODO: remove this method again, for prototype only
"""
pass
def _create_tabbed_pages(self):
"""
Create the notebook tabs and inserts them into the main

View File

@ -82,8 +82,8 @@ class EditPrimary(ManagedWindow, DbGUIElement):
self._local_init()
self._set_size()
self._create_tabbed_pages()
self._setup_fields()
self._create_tabbed_pages()
self._connect_signals()
#if the database is changed, all info shown is invalid and the window
# should close

View File

@ -3,7 +3,7 @@
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2009 Gary Burton
# Copyright (C) 2011 Tim G L Lyons
# Copyright (C) 2011-2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -30,30 +30,41 @@
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
import logging
log = logging.getLogger(".")
LOG = logging.getLogger(".citation")
LOG = logging.getLogger(".template")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
from gi.repository import Gtk
from gi.repository import Gtk, Gdk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.lib import NoteType, Source
from gramps.gen.lib import NoteType, Source, Citation
from gramps.gen.db import DbTxn
from gramps.gen.utils.file import media_path_full
from ..thumbnails import get_thumbnail_image
from .editprimary import EditPrimary
from .editreference import RefTab
from .editmediaref import EditMediaRef
from .displaytabs import (NoteTab, GalleryTab, SrcAttrEmbedList,
SrcTemplateTab, CitedInTab,
CitationBackRefList, RepoEmbedList)
from ..widgets import MonitoredEntry, PrivacyButton, MonitoredTagList
from ..dialog import ErrorDialog
from .displaytabs.srctemplatetab import TemplateFields
from ..widgets import (MonitoredEntry, PrivacyButton, MonitoredTagList,
MonitoredMenu)
from ..dialog import ErrorDialog, QuestionDialog2
from ..utils import is_right_click, open_file_with_default_application
from ..glade import Glade
from gramps.gen.utils.citeref import (set_input_dict_and_template, reference_L,
reference_S, reference_F,
get_gedcom_title, get_gedcom_author,
get_gedcom_pubinfo, get_gedcom_page)
#-------------------------------------------------------------------------
#
@ -63,21 +74,78 @@ from ..glade import Glade
class EditSource(EditPrimary):
def __init__(self, dbstate, uistate, track, source):
def __init__(self, dbstate, uistate, track, source, citation=None,
callback=None,
callertitle = None):
"""
Editor for source and citations of that source
If source is not given, citation must be given, and the source of the
citation will be used
callback: function to call on save with the loaded citation handle. If
no citation is loaded, None will be used as handle. Caller
must handle this (corresponds to closing the editor with
nothing made!)
"""
self.db = dbstate.db
self.citation = citation
self.template_tab = None
self.citn_attr_tab = None
self.src_attr_tab = None
self.citation_loaded = True
if not source and not citation:
raise NotImplementedError
elif not source:
#citation will be used to obtain the source
hsource = citation.get_reference_handle()
source = dbstate.db.get_source_from_handle(hsource)
elif citation:
#source and citation are given, they MUST be connected or citation
#must be a new object
if citation.get_reference_handle() and \
not (citation.get_reference_handle() == source.handle):
raise Exception('Citation must be a Citation of the Source edited')
if source.get_template() is None:
source.set_template(dbstate.db.get_GEDCOM_template_handle())
else:
#no citation given.
self.citation_loaded = False
#we put an empty base citation ready.
self.citation = Citation()
if source.get_template() is None:
source.set_template(dbstate.db.get_GEDCOM_template_handle())
self.callertitle = callertitle
self.citation_ready = False
EditPrimary.__init__(self, dbstate, uistate, track, source,
dbstate.db.get_source_from_handle,
dbstate.db.get_source_from_gramps_id)
dbstate.db.get_source_from_gramps_id, callback)
def empty_object(self):
return Source()
def get_menu_title(self):
title = self.obj.get_title()
if title:
title = get_gedcom_title(self.db, self.obj)
if self.obj.get_handle():
title = _('Source') + ": " + title
else:
title = _('New Source')
if self.citation_loaded:
citeid = self.citation.get_gramps_id()
if self.citation.get_handle():
if self.callertitle:
title = _('Citation: %(id)s - %(context)s' % {
'id' : citeid,
'context' : self.callertitle
}) + ' ' + title
else:
title = _('Citation') + ": " + citeid + ' ' + title
else:
if self.callertitle:
title = _('New Citation - %(context)s' % {
'context' : self.callertitle
}) + ' ' + title
else:
title = _('New Citation') + ' ' + title
return title
def _local_init(self):
@ -89,29 +157,125 @@ class EditSource(EditPrimary):
self.set_window(self.glade.toplevel, None,
self.get_menu_title())
self.obj_photo = self.glade.get_object("sourcePix")
self.frame_photo = self.glade.get_object("frame5")
self.eventbox = self.glade.get_object("eventbox1")
self.notebook_ref = self.glade.get_object('notebook_citation')
self.cinf = self.glade.get_object("cite_info_lbl")
self.btnclose_cite = self.glade.get_object("btnclose_cite")
self.tmplfields = None
self.define_warn_box2(self.glade.get_object("warn_box2"))
def _post_init(self):
"""
Handle any initialization that needs to be done after the interface is
brought up.
Post initalization function.
This is called by _EditPrimary's init routine, and overridden in the
derived class (this class).
"""
if not self.citation_loaded:
self.unload_citation()
self.load_source_image()
if not self.obj.handle:
#new source, open on template view, and focus there.
self.notebook_src.set_current_page(self.template_page_nr)
self.template_tab.make_active()
elif self.citation_loaded:
#there is a citation!
if self.citation.handle:
#existing citation!
self.notebook_ref.grab_focus()
else:
#new citation!
self.notebook_ref.grab_focus()
else:
#existing source, no citation
self.title.grab_focus()
def load_source_image(self):
"""
Load the primary image into the main form if it exists.
Used as callback on Gallery Tab too.
"""
media_list = self.obj.get_media_list()
if media_list:
ref = media_list[0]
handle = ref.get_reference_handle()
obj = self.dbstate.db.get_object_from_handle(handle)
if obj is None :
#notify user of error
from ..dialog import RunDatabaseRepair
RunDatabaseRepair(
_('Non existing media found in the Gallery'))
else:
self.load_photo(ref, obj)
else:
self.obj_photo.hide()
self.frame_photo.hide()
def load_photo(self, ref, obj):
"""
Load the source's main photo using the Thumbnailer.
"""
pixbuf = get_thumbnail_image(
media_path_full(self.dbstate.db, obj.get_path()),
obj.get_mime_type(),
ref.get_rectangle())
self.obj_photo.set_from_pixbuf(pixbuf)
self.obj_photo.show()
self.frame_photo.show_all()
def _connect_signals(self):
self.define_ok_button(self.glade.get_object('ok'),self.save)
self.define_ok_button(self.glade.get_object('ok'), self.save)
self.define_cancel_button(self.glade.get_object('cancel'))
self.define_help_button(self.glade.get_object('help'))
self.btnclose_cite.connect('clicked', self.close_citation)
self.eventbox.connect('button-press-event',
self._image_button_press)
def _connect_db_signals(self):
"""
Connect any signals that need to be connected.
Called by the init routine of the base class (_EditPrimary).
"""
self._add_db_signal('citation-rebuild', self._do_close)
self._add_db_signal('citation-delete', self.check_for_close_cite)
self._add_db_signal('source-rebuild', self._do_close)
self._add_db_signal('source-delete', self.check_for_close)
self._add_db_signal('note-delete', self.update_notes)
self._add_db_signal('note-update', self.update_notes)
self._add_db_signal('note-add', self.update_notes)
self._add_db_signal('note-rebuild', self.update_notes)
def check_for_close_cite(self, handles):
"""
Callback method for delete signals.
If there is a delete signal of the citation object we are
editing, the
editor (and all child windows spawned) should be closed
"""
#citation, we only close if that citation is open
if self.citation and self.citation.get_handle() in handles:
self._do_close()
def _setup_fields(self):
self.author = MonitoredEntry(self.glade.get_object("author"),
self.obj.set_author, self.obj.get_author,
self.db.readonly)
self.pubinfo = MonitoredEntry(self.glade.get_object("pubinfo"),
self.obj.set_publication_info,
self.obj.get_publication_info,
self.db.readonly)
#reference info fields of source
self.refL = self.glade.get_object("refL")
self.refF = self.glade.get_object("refF")
self.refS = self.glade.get_object("refS")
self.author = self.glade.get_object("author")
self.pubinfo = self.glade.get_object("pubinfo")
self.source_text = self.glade.get_object("source_text")
#editable source fields
self.gid = MonitoredEntry(self.glade.get_object("gid"),
self.obj.set_gramps_id,
self.obj.get_gramps_id, self.db.readonly)
@ -133,70 +297,377 @@ class EditSource(EditPrimary):
self.db.readonly)
self.title = MonitoredEntry(self.glade.get_object("source_title"),
self.obj.set_title, self.obj.get_title,
self.obj.set_name, self.obj.get_name,
self.db.readonly)
#editable citation fields
self._setup_citation_fields()
#trigger updates of read only fields
self.update_attr()
self.update_notes()
def _setup_citation_fields(self):
if self.citation_ready:
raise Exception
self.cname = MonitoredEntry(
self.glade.get_object('cname'), self.citation.set_name,
self.citation.get_name, self.db.readonly)
self.gid2 = MonitoredEntry(
self.glade.get_object('gid2'), self.citation.set_gramps_id,
self.get_citation_gramps_id, self.db.readonly)
self.type_mon = MonitoredMenu(
self.glade.get_object('confidence'),
self.citation.set_confidence_level,
self.citation.get_confidence_level, [
(_('Very Low'), Citation.CONF_VERY_LOW),
(_('Low'), Citation.CONF_LOW),
(_('Normal'), Citation.CONF_NORMAL),
(_('High'), Citation.CONF_HIGH),
(_('Very High'), Citation.CONF_VERY_HIGH)],
self.db.readonly)
self.tags2 = MonitoredTagList(
self.glade.get_object("tag_label2"),
self.glade.get_object("tag_button2"),
self.citation.set_tag_list,
self.citation.get_tag_list,
self.db,
self.uistate, self.track,
self.db.readonly)
self.ref_privacy = PrivacyButton(
self.glade.get_object('privacy'), self.citation, self.db.readonly)
def get_citation_gramps_id(self):
"""
Monitered entry on None does nothing, while get_gramps_id returns None
for empty string! We convert here
"""
val = self.citation.get_gramps_id()
if val is None:
return ''
else:
return val
def update_attr(self):
"""
Reaction to update on attributes
"""
if self.citation_loaded:
citation = self.citation
else:
citation = None
set_input_dict_and_template(self.db, self.obj, citation)
#set fields with the template
self.refL.set_markup(reference_L(self.db))
self.refF.set_markup(reference_F(self.db))
self.refS.set_markup(reference_S(self.db))
self.author.set_markup(get_gedcom_author(self.db))
self.pubinfo.set_markup(get_gedcom_pubinfo(self.db))
if self.template_tab and self.template_tab.autoset_title:
title = get_gedcom_title(self.db)
self.obj.set_name(title)
self.title.update()
#lastly update the window title
self.update_title(self.get_menu_title())
def update_template_data(self, templatechanged=False):
"""
Change in the template tab of source must be reflected in other places.
If template itself changed, templatechanged==True must be passed
"""
if templatechanged and self.tmplfields:
#the citation template fields must be changed!
self.tmplfields.reset_template_fields(self.obj.get_template())
if self.citn_attr_tab:
self.citn_attr_tab.rebuild_callback()
if self.src_attr_tab:
self.src_attr_tab.rebuild_callback()
self.update_attr()
def callback_cite_changed(self):
"""
Change in the citation part might lead to changes needed in the src GUI
section
"""
self.update_template_data(False)
def update_notes(self, *par):
"""
Change the source text on the overview page when notebase of the source
changed
"""
note_list = [ self.db.get_note_from_handle(h)
for h in self.obj.get_note_list() ]
note_list = [ n for n in note_list
if n.get_type() == NoteType.SOURCE_TEXT]
ref_text = ""
for note in note_list:
ref_text += note_list[0].get() + "\n"
self.source_text.get_buffer().set_text(ref_text)
def _create_tabbed_pages(self):
notebook = Gtk.Notebook()
self.notebook_src = self.glade.get_object('notebook')
notebook = self.notebook_src
gridsrc = self.glade.get_object('gridsrc')
#recreate start page as GrampsTab
notebook.remove_page(1)
notebook.remove_page(0)
self.overviewtab = RefTab(self.dbstate, self.uistate, self.track,
_('Overview'), gridsrc)
self._add_tab(notebook, self.overviewtab)
#recreate second page as GrampsTab
self.template_page_nr = 1
self.template_tab = SrcTemplateTab(self.dbstate, self.uistate,
self.track, self.obj, self.glade,
self.update_template_data
)
self._add_tab(notebook, self.template_tab)
self.track_ref_for_deletion("template_tab")
self.note_tab = NoteTab(self.dbstate,
self.uistate,
self.track,
self.obj.get_note_list(),
self.get_menu_title(),
NoteType.SOURCE)
NoteType.SOURCE,
callback_notebase_changed=self.update_notes)
self._add_tab(notebook, self.note_tab)
self.track_ref_for_deletion("note_tab")
self.gallery_tab = GalleryTab(self.dbstate,
self.uistate,
self.track,
self.obj.get_media_list())
self.obj.get_media_list(),
self.load_source_image)
self._add_tab(notebook, self.gallery_tab)
self.track_ref_for_deletion("gallery_tab")
self.attr_tab = SrcAttrEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_attribute_list())
self._add_tab(notebook, self.attr_tab)
self.track_ref_for_deletion("attr_tab")
self.repo_tab = RepoEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_reporef_list())
self._add_tab(notebook, self.repo_tab)
self.track_ref_for_deletion("repo_tab")
self.backref_list = CitationBackRefList(self.dbstate,
self.uistate,
self.track,
self.db.find_backlink_handles(self.obj.handle))
self.backref_tab = self._add_tab(notebook, self.backref_list)
self.track_ref_for_deletion("backref_tab")
self.track_ref_for_deletion("backref_list")
self.src_attr_tab = SrcAttrEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_attribute_list())
self._add_tab(notebook, self.src_attr_tab)
self.track_ref_for_deletion("src_attr_tab")
self.citedin_tab = CitedInTab(self.dbstate, self.uistate,
self.track, self.obj, self.cite_apply_callback,
self.cite_add_callback)
self._add_tab(notebook, self.citedin_tab)
self.track_ref_for_deletion("citedin_tab")
## self.backref_list = CitationBackRefList(self.dbstate,
## self.uistate,
## self.track,
## self.db.find_backlink_handles(self.obj.handle))
## self.backref_tab = self._add_tab(notebook, self.backref_list)
## self.track_ref_for_deletion("backref_tab")
## self.track_ref_for_deletion("backref_list")
self._setup_notebook_tabs(notebook)
notebook.show_all()
self.glade.get_object('vbox').pack_start(notebook, True, True, 0)
#now create citation tabbed pages
self._create_citation_tabbed_pages()
def _create_citation_tabbed_pages(self):
if self.citation_ready:
raise Exception
self.citation_ready = True
tblref = self.glade.get_object('grid1')
notebook_ref = self.notebook_ref
#recreate start page as GrampsTab
notebook_ref.remove_page(0)
self.reftab = RefTab(self.dbstate, self.uistate, self.track,
_('General'), tblref)
self._add_tab(notebook_ref, self.reftab)
self.track_ref_for_deletion("reftab")
#reftab contains the citation template fields
self.tmplfields = TemplateFields(self.dbstate.db, self.uistate,
self.track, self.glade.get_object('grid_citefields'),
self.obj, self.citation, None, self.callback_cite_changed)
self.tmplfields.reset_template_fields(self.obj.get_template())
self.comment_tab = NoteTab(self.dbstate, self.uistate, self.track,
self.citation.get_note_list(), self.get_menu_title(),
notetype=NoteType.CITATION)
self._add_tab(notebook_ref, self.comment_tab)
self.track_ref_for_deletion("comment_tab")
self.gallery_tab = GalleryTab(self.dbstate, self.uistate, self.track,
self.citation.get_media_list())
self._add_tab(notebook_ref, self.gallery_tab)
self.track_ref_for_deletion("gallery_tab")
self.citn_attr_tab = SrcAttrEmbedList(self.dbstate, self.uistate, self.track,
self.citation.get_attribute_list())
self._add_tab(notebook_ref, self.citn_attr_tab)
self.track_ref_for_deletion("citn_attr_tab")
self.citationref_list = CitationBackRefList(self.dbstate, self.uistate,
self.track,
self.db.find_backlink_handles(self.citation.handle),
self.enable_warnbox2)
self._add_tab(notebook_ref, self.citationref_list)
self.track_ref_for_deletion("citationref_list")
def define_warn_box2(self, box):
self.warn_box2 = box
def enable_warnbox2(self):
self.warn_box2.show()
def build_menu_names(self, source):
return (_('Edit Source'), self.get_menu_title())
def save(self, *obj):
def _image_button_press(self, obj, event):
"""
Button press event that is caught when a button has been pressed while
on the image on the main form.
This does not apply to the images in galleries, just the image on the
main form.
"""
if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1:
media_list = self.obj.get_media_list()
if media_list:
media_ref = media_list[0]
object_handle = media_ref.get_reference_handle()
media_obj = self.db.get_object_from_handle(object_handle)
try:
EditMediaRef(self.dbstate, self.uistate, self.track,
media_obj, media_ref, self.load_photo)
except WindowActiveError:
pass
elif is_right_click(event):
media_list = self.obj.get_media_list()
if media_list:
photo = media_list[0]
self._show_popup(photo, event)
#do not propagate further:
return True
def _show_popup(self, photo, event):
"""
Look for right-clicks on a picture and create a popup menu of the
available actions.
"""
self.imgmenu = Gtk.Menu()
menu = self.imgmenu
menu.set_title(_("Media Object"))
obj = self.db.get_object_from_handle(photo.get_reference_handle())
if obj:
add_menuitem(menu, _("View"), photo,
self._popup_view_photo)
add_menuitem(menu, _("Edit Object Properties"), photo,
self._popup_change_description)
menu.popup(None, None, None, None, event.button, event.time)
def _popup_view_photo(self, obj):
"""
Open this picture in the default picture viewer.
"""
media_list = self.obj.get_media_list()
if media_list:
photo = media_list[0]
object_handle = photo.get_reference_handle()
ref_obj = self.db.get_object_from_handle(object_handle)
photo_path = media_path_full(self.db, ref_obj.get_path())
open_file_with_default_application(photo_path)
def _popup_change_description(self, obj):
"""
Bring up the EditMediaRef dialog for the image on the main form.
"""
media_list = self.obj.get_media_list()
if media_list:
media_ref = media_list[0]
object_handle = media_ref.get_reference_handle()
media_obj = self.db.get_object_from_handle(object_handle)
EditMediaRef(self.dbstate, self.uistate, self.track,
media_obj, media_ref, self.load_photo)
def close_citation(self, *obj):
"""
Callback on close citation button clicked
"""
if not self.citation_loaded:
return
self.ok_button.set_sensitive(False)
self.btnclose_cite.set_sensitive(False)
#ask if ok to save the citation if needed
save_citation = False
if not self.citation.get_handle():
#new citation, ask if we should save.
qd = QuestionDialog2(_("Closing New Citation"),
_("Should the new citation be saved to your family tree?"),
_("Save Citation"),
_("Don't Save Citation"), parent=self.window)
ok = qd.run()
if ok:
save_citation = True
elif self.citation_data_has_changed():
#if citation changed, ask if user does not want to save it first
qd = QuestionDialog2(_('Save Changes?'),
_('If you close without saving, the changes you '
'have made will be lost'),
_("Save Citation"),
_("Don't Save Citation"), parent=self.window)
ok = qd.run()
if ok:
save_citation = True
if save_citation:
#we save the citation. If new source, this means the source must
#be saved too!
res = self.__base_save_source_test()
if not res:
return
res = self.__base_save_citation_test()
if not res:
return
self.__base_save(only_cite=True)
#as a citation changed, we need to update some fields in source
#section
self.citedin_tab.rebuild()
#now close the citation part
self.unload_citation()
#make safe button active again
self.ok_button.set_sensitive(True)
def __base_save_source_test(self):
if self.object_is_empty():
ErrorDialog(_("Cannot save source"),
_("No data exists for this source. Please "
"enter data or cancel the edit."))
self.ok_button.set_sensitive(True)
return
if self.citation_loaded:
self.btnclose_cite.set_sensitive(True)
return False
(uses_dupe_id, id) = self._uses_duplicate_id()
if uses_dupe_id:
prim_object = self.get_from_gramps_id(id)
name = prim_object.get_title()
name = get_gedcom_title(self.db, prim_object)
msg1 = _("Cannot save source. ID already exists.")
msg2 = _("You have attempted to use the existing Gramps ID with "
"value %(id)s. This value is already used by '"
@ -205,21 +676,203 @@ class EditSource(EditPrimary):
'id' : id, 'prim_object' : name }
ErrorDialog(msg1, msg2)
self.ok_button.set_sensitive(True)
return
if self.citation_loaded:
self.btnclose_cite.set_sensitive(True)
return False
return True
def __base_save_citation_test(self):
#tests on the citation if needed:
if self.citation_loaded:
(uses_dupe_id, gramps_id) = self._citation_uses_duplicate_id(
self.citation)
if uses_dupe_id:
prim_object = self.db.get_citation_from_gramps_id(gramps_id)
name = get_gedcom_page(self.db, prim_object)
msg1 = _("Cannot save citation. ID already exists.")
msg2 = _("You have attempted to use the existing Gramps ID with "
"value %(gramps_id)s. This value is already used by '"
"%(prim_object)s'. Please enter a different ID or leave "
"blank to get the next available ID value.") % {
'gramps_id' : gramps_id, 'prim_object' : name }
ErrorDialog(msg1, msg2)
self.ok_button.set_sensitive(True)
if self.citation_loaded:
self.btnclose_cite.set_sensitive(True)
return False
return True
def __base_save(self, only_cite=False):
"""
Save to database. If only_cite, the idea is to only save the citation
part. If the source does not exist, sourse will be saved anyway
"""
with DbTxn('', self.db) as trans:
# First commit the Source Primary object
if not self.obj.get_handle():
self.db.add_source(self.obj, trans)
msg = _("Add Source (%s)") % self.obj.get_title()
else:
msg = _("Add Source (%s)") % get_gedcom_title(self.db, self.obj)
elif not only_cite:
#a changed source is not saved if only_cite
if not self.obj.get_gramps_id():
self.obj.set_gramps_id(self.db.find_next_source_gramps_id())
self.db.commit_source(self.obj, trans)
msg = _("Edit Source (%s)") % self.obj.get_title()
msg = _("Edit Source (%s)") % get_gedcom_title(self.db, self.obj)
else:
msg = ''
# Make sure citation references this source
if self.citation:
self.citation.set_reference_handle(self.obj.handle)
# Now commit the Citation Primary object if needed
if self.citation_loaded:
if not self.citation.get_handle():
self.db.add_citation(self.citation, trans)
msg += "\n" + _("Add Citation (%s)") % get_gedcom_page(self.db, self.citation)
else:
if not self.citation.get_gramps_id():
self.citation.set_gramps_id(
self.db.find_next_citation_gramps_id())
self.db.commit_citation(self.citation, trans)
msg += "\n" + _("Edit Citation (%s)") % get_gedcom_page(self.db, self.citation)
# set transaction description
trans.set_description(msg)
def save(self, *obj):
self.ok_button.set_sensitive(False)
self.btnclose_cite.set_sensitive(False)
res = self.__base_save_source_test()
if not res:
return
res = self.__base_save_citation_test()
if not res:
return
self.__base_save()
if self.callback and self.citation_loaded:
#callback only returns the citation handle. Source can be determined
# of this if needed.
self.callback(self.citation.get_handle())
self.close()
def _citation_uses_duplicate_id(self, obj):
"""
Check whether a changed or added GRAMPS ID already exists in the DB.
Return True if a duplicate GRAMPS ID has been detected.
"""
original = self.db.get_citation_from_handle(obj.get_handle())
if original and original.get_gramps_id() == obj.get_gramps_id():
#id did not change, so all is good
return (False, 0)
else:
idval = obj.get_gramps_id()
if self.db.get_citation_from_gramps_id(idval):
return (True, idval)
return (False, 0)
# CITATION PART
def cite_apply_callback(self, citation_handle):
if self.citation_loaded:
self.close_citation()
self.load_citation(citation_handle)
def cite_add_callback(self):
"""
User wants to add a new citation to the source.
"""
if self.citation_loaded:
self.close_citation()
self.load_citation(None)
def unload_citation(self):
self.cinf.set_visible(False)
self.btnclose_cite.set_sensitive(False)
self.notebook_ref.set_visible(False)
self.citation_loaded = False
if self.citation:
#there is a citation, we clear it
self.citation.unserialize(Citation().serialize())
def load_citation(self, chandle):
"""
Loading a citation in the top view
"""
#we switch current citatoin for the new one
if not self.citation:
#there is no citation yet, put an empty one
self.citation = Citation()
if chandle:
newcite = self.db.get_citation_from_handle(chandle)
else:
newcite = Citation()
if not newcite:
#error in database, link to citation handle that does not exist
raise Exception
self.citation.unserialize(newcite.serialize())
#we have a citation:
self.citation_loaded = True
if not self.citation_ready:
self._setup_citation_fields()
self._create_citation_tabbed_pages()
else:
self.citation_changed()
#the citation template fields must be changed!
self.tmplfields.reset_template_fields(self.obj.get_template())
self.cinf.set_visible(True)
self.btnclose_cite.set_sensitive(True)
self.notebook_ref.set_visible(True)
def citation_changed(self):
"""
The citation part of the editor changed, we need to update all
GUI fields showing data of it
"""
#update source part that uses citation
self.update_attr()
#trigger update of the monitored fields
for field in [self.gid2, self.type_mon, self.tags2, self.ref_privacy]:
field.update()
#trigger update of the tab fields
self.comment_tab.rebuild_callback(self.citation.get_note_list())
self.gallery_tab.rebuild_callback(self.citation.get_media_list())
self.citn_attr_tab.rebuild_callback(self.citation.get_attribute_list())
self.citationref_list.rebuild_callback(
self.db.find_backlink_handles(self.citation.handle))
def data_has_changed(self):
return self.citation_data_has_changed() or \
EditPrimary.data_has_changed(self)
def citation_data_has_changed(self):
"""
This checks whether the citation data has changed
A date comparison can fail incorrectly because we have made the
decision to store entered text in the date. However, there is no
entered date when importing from a XML file, so we can get an
incorrect fail.
"""
if not self.citation_loaded:
return False
if self.db.readonly:
return False
if self.citation.handle:
orig = self.db.get_citation_from_handle(self.citation.handle)
if orig:
cmp_obj = orig
else:
cmp_obj = Citation()
return cmp_obj.serialize(True)[1:] != self.citation.serialize(True)[1:]
else:
cmp_obj = Citation()
return cmp_obj.serialize(True)[1:] != self.citation.serialize()[1:]
class DeleteSrcQuery(object):
def __init__(self, dbstate, uistate, source, the_lists):
self.source = source
@ -228,7 +881,7 @@ class DeleteSrcQuery(object):
self.the_lists = the_lists
def query_response(self):
with DbTxn(_("Delete Source (%s)") % self.source.get_title(),
with DbTxn(_("Delete Source (%s)") % get_gedcom_title(self.db, self),
self.db) as trans:
self.db.disable_signals()

View File

@ -347,10 +347,10 @@ class MyID(Gtk.Box):
name = place.get_title()
elif self.namespace == 'Source':
source = self.db.get_source_from_gramps_id(gramps_id)
name = source.get_title()
name = source.get_name()
elif self.namespace == 'Citation':
citation = self.db.get_citation_from_gramps_id(gramps_id)
name = citation.get_page()
name = citation.get_name()
elif self.namespace == 'Media':
obj = self.db.get_object_from_gramps_id(gramps_id)
name = obj.get_path()
@ -951,11 +951,11 @@ class ShowResults(ManagedWindow):
gid = event.get_gramps_id()
elif self.namespace == 'Source':
source = self.db.get_source_from_handle(handle)
name = source.get_title()
name = source.get_name()
gid = source.get_gramps_id()
elif self.namespace == 'Citation':
citation = self.db.get_citation_from_handle(handle)
name = citation.get_page()
name = citation.get_name()
gid = citation.get_gramps_id()
elif self.namespace == 'Place':
place = self.db.get_place_from_handle(handle)
@ -987,9 +987,9 @@ class ShowResults(ManagedWindow):
elif self.namespace == 'Event':
sortname = self.db.get_event_from_handle(handle).get_description()
elif self.namespace == 'Source':
sortname = self.db.get_source_from_handle(handle).get_title()
sortname = self.db.get_source_from_handle(handle).get_name()
elif self.namespace == 'Citation':
sortname = self.db.get_citation_from_handle(handle).get_page()
sortname = self.db.get_citation_from_handle(handle).get_name()
elif self.namespace == 'Place':
sortname = self.db.get_place_from_handle(handle).get_title()
elif self.namespace == 'Media':

View File

@ -41,7 +41,7 @@ from gi.repository import Gtk
# GRAMPS modules
#
#-------------------------------------------------------------------------
from ...widgets import MonitoredMenu
from ...widgets import MonitoredMenu, BasicEntry
from gramps.gen.lib import Citation
from .. import build_filter_model
from . import SidebarFilter
@ -49,7 +49,8 @@ from gramps.gen.constfunc import cuni
from gramps.gen.filters import GenericFilterFactory, rules
from gramps.gen.filters.rules.citation import (RegExpIdOf, HasIdOf, HasCitation,
HasNoteMatchingSubstringOf,
HasNoteRegexp, MatchesFilter, HasTag)
HasNoteRegexp, MatchesFilter, HasTag,
HasSource, RegExpSourceIdOf)
from gramps.gen.utils.string import confidence
GenericCitationFilter = GenericFilterFactory('Citation')
#-------------------------------------------------------------------------
@ -61,6 +62,12 @@ class CitationSidebarFilter(SidebarFilter):
def __init__(self, dbstate, uistate, clicked):
self.clicked_func = clicked
self.filter_src_id = BasicEntry()
self.filter_src_title = BasicEntry()
self.filter_src_author = BasicEntry()
self.filter_src_abbr = BasicEntry()
self.filter_src_pub = BasicEntry()
self.filter_src_note = BasicEntry()
self.filter_id = Gtk.Entry()
self.filter_page = Gtk.Entry()
self.filter_date = Gtk.Entry()
@ -101,16 +108,28 @@ class CitationSidebarFilter(SidebarFilter):
self.tag.pack_start(cell, True)
self.tag.add_attribute(cell, 'text', 0)
self.add_text_entry(_('ID'), self.filter_id)
self.add_text_entry(_('Volume/Page'), self.filter_page)
self.add_text_entry(_('Date'), self.filter_date)
self.add_entry(_('Minimum Confidence|Min. Conf.'), self.filter_conf)
self.add_text_entry(_('Note'), self.filter_note)
self.add_text_entry(_('Source: ID'), self.filter_src_id)
self.add_text_entry(_('Source: Title'), self.filter_src_title)
self.add_text_entry(_('Source: Author'), self.filter_src_author)
self.add_text_entry(_('Source: Abbreviation'), self.filter_src_abbr)
self.add_text_entry(_('Source: Publication'), self.filter_src_pub)
self.add_text_entry(_('Source: Note'), self.filter_src_note)
self.add_text_entry(_('Citation: ID'), self.filter_id)
self.add_text_entry(_('Citation: Volume/Page'), self.filter_page)
self.add_text_entry(_('Citation: Date'), self.filter_date)
self.add_entry(_('Citation: Minimum Confidence|Min. Conf.'), self.filter_conf)
self.add_text_entry(_('Citation: Note'), self.filter_note)
self.add_entry(_('Tag'), self.tag)
self.add_filter_entry(_('Custom filter'), self.generic)
self.add_entry(None, self.filter_regex)
def clear(self, obj):
self.filter_src_id.set_text('')
self.filter_src_title.set_text('')
self.filter_src_author.set_text('')
self.filter_src_abbr.set_text('')
self.filter_src_pub.set_text('')
self.filter_src_note.set_text('')
self.filter_id.set_text('')
self.filter_page.set_text('')
self.filter_date.set_text('')
@ -120,6 +139,15 @@ class CitationSidebarFilter(SidebarFilter):
self.generic.set_active(0)
def get_filter(self):
src_id = unicode(self.filter_src_id.get_text()).strip()
src_title = unicode(self.filter_src_title.get_text()).strip()
src_author = unicode(self.filter_src_author.get_text()).strip()
src_abbr = unicode(self.filter_src_abbr.get_text()).strip()
src_pub = unicode(self.filter_src_pub.get_text()).strip()
src_note = unicode(self.filter_src_note.get_text()).strip()
gid = unicode(self.filter_id.get_text()).strip()
page = unicode(self.filter_page.get_text()).strip()
date = unicode(self.filter_date.get_text()).strip()
gid = cuni(self.filter_id.get_text()).strip()
page = cuni(self.filter_page.get_text()).strip()
date = cuni(self.filter_date.get_text()).strip()
@ -137,7 +165,9 @@ class CitationSidebarFilter(SidebarFilter):
tag = self.tag.get_active() > 0
gen = self.generic.get_active() > 0
empty = not (gid or page or date or conf or note or regex or tag or gen)
empty = not (src_id or src_title or src_author or src_abbr or src_pub or
src_note or
gid or page or date or conf or note or regex or gen)
if empty:
generic_filter = None
else:
@ -152,6 +182,14 @@ class CitationSidebarFilter(SidebarFilter):
rule = HasCitation([page, date, conf], use_regex=regex)
generic_filter.add_rule(rule)
if src_id:
rule = RegExpSourceIdOf([src_id], use_regex=regex)
generic_filter.add_rule(rule)
rule = HasSource([src_title, src_author, src_abbr, src_pub],
use_regex=regex)
generic_filter.add_rule(rule)
if note:
if regex:
rule = HasNoteRegexp([note])

View File

@ -15,6 +15,7 @@
<object class="GtkBox" id="dialog-vbox17">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area17">
<property name="visible">True</property>
@ -23,12 +24,10 @@
<child>
<object class="GtkButton" id="help">
<property name="label">gtk-help</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -40,12 +39,10 @@
<child>
<object class="GtkButton" id="cancel">
<property name="label">gtk-cancel</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -57,12 +54,10 @@
<child>
<object class="GtkButton" id="ok">
<property name="label">gtk-ok</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -128,18 +123,16 @@
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="date_stat">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="has_tooltip">True</property>
<property name="tooltip_text" translatable="yes">Invoke date editor</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<accelerator key="d" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="accessible">
@ -164,7 +157,7 @@
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -179,7 +172,7 @@
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -196,7 +189,7 @@
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -213,7 +206,7 @@
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -239,7 +232,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -252,7 +245,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -297,7 +290,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -352,7 +345,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -368,16 +361,14 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="privacy">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="accessible">
@ -403,17 +394,15 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"></property>
<property name="y_options"></property>
<property name="x_options"/>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="tag_button2">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<property name="xalign">0</property>
</object>
@ -422,8 +411,8 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"></property>
<property name="y_options"></property>
<property name="x_options"/>
<property name="y_options"/>
</packing>
</child>
</object>
@ -481,7 +470,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -498,7 +487,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -516,7 +505,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -533,7 +522,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -548,7 +537,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -593,7 +582,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -608,7 +597,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -623,7 +612,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -639,7 +628,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -706,7 +695,7 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -719,16 +708,14 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="private">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child internal-child="accessible">
<object class="AtkObject" id="private-atkobject">
@ -753,17 +740,15 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"></property>
<property name="y_options"></property>
<property name="x_options"/>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="tag_button">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -771,8 +756,8 @@ Very High =Direct and primary evidence used, or by dominance of the evidence </p
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options"></property>
<property name="y_options"></property>
<property name="x_options"/>
<property name="y_options"/>
</packing>
</child>
</object>

File diff suppressed because it is too large Load Diff

View File

@ -19,12 +19,10 @@
<child>
<object class="GtkButton" id="citation_cancel">
<property name="label">gtk-cancel</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -36,12 +34,10 @@
<child>
<object class="GtkButton" id="citation_ok">
<property name="label">gtk-ok</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -53,12 +49,10 @@
<child>
<object class="GtkButton" id="citation_help">
<property name="label">gtk-help</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -111,11 +105,9 @@ primary data for the merged citation.</property>
<property name="can_focus">False</property>
<child>
<object class="GtkRadioButton" id="handle_btn1">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<child>
@ -135,11 +127,9 @@ primary data for the merged citation.</property>
</child>
<child>
<object class="GtkRadioButton" id="handle_btn2">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<property name="group">handle_btn1</property>
@ -206,7 +196,7 @@ primary data for the merged citation.</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -222,17 +212,15 @@ primary data for the merged citation.</property>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="page_btn1">
<property name="label" translatable="yes">Volume/Page:</property>
<property name="use_action_appearance">False</property>
<object class="GtkRadioButton" id="name_btn1">
<property name="label" translatable="yes">Name:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -241,21 +229,19 @@ primary data for the merged citation.</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="page_btn2">
<property name="label" translatable="yes">Volume/Page:</property>
<property name="use_action_appearance">False</property>
<object class="GtkRadioButton" id="name_btn2">
<property name="label" translatable="yes">Name:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<property name="group">page_btn1</property>
<property name="group">name_btn1</property>
</object>
<packing>
<property name="left_attach">2</property>
@ -263,17 +249,15 @@ primary data for the merged citation.</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="date_btn1">
<property name="label" translatable="yes">Date:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -282,17 +266,15 @@ primary data for the merged citation.</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="date_btn2">
<property name="label" translatable="yes">Date:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -304,17 +286,15 @@ primary data for the merged citation.</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="confidence_btn1">
<property name="label" translatable="yes">Confidence:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -323,17 +303,15 @@ primary data for the merged citation.</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="confidence_btn2">
<property name="label" translatable="yes">Confidence:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -345,17 +323,15 @@ primary data for the merged citation.</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="gramps_btn1">
<property name="label" translatable="yes">Gramps ID:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -364,17 +340,15 @@ primary data for the merged citation.</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="gramps_btn2">
<property name="label" translatable="yes">Gramps ID:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -386,11 +360,11 @@ primary data for the merged citation.</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="page1">
<object class="GtkEntry" id="name1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@ -400,11 +374,11 @@ primary data for the merged citation.</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="page2">
<object class="GtkEntry" id="name2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@ -414,7 +388,7 @@ primary data for the merged citation.</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -428,7 +402,7 @@ primary data for the merged citation.</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -442,7 +416,7 @@ primary data for the merged citation.</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -456,7 +430,7 @@ primary data for the merged citation.</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -470,7 +444,7 @@ primary data for the merged citation.</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -484,7 +458,7 @@ primary data for the merged citation.</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -501,7 +475,7 @@ primary data for the merged citation.</property>
<property name="right_attach">4</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>

View File

@ -19,12 +19,10 @@
<child>
<object class="GtkButton" id="source_cancel">
<property name="label">gtk-cancel</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -36,12 +34,10 @@
<child>
<object class="GtkButton" id="source_ok">
<property name="label">gtk-ok</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -53,12 +49,10 @@
<child>
<object class="GtkButton" id="source_help">
<property name="label">gtk-help</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -111,11 +105,9 @@ primary data for the merged source.</property>
<property name="can_focus">False</property>
<child>
<object class="GtkRadioButton" id="handle_btn1">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<child>
@ -135,11 +127,9 @@ primary data for the merged source.</property>
</child>
<child>
<object class="GtkRadioButton" id="handle_btn2">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<property name="group">handle_btn1</property>
@ -194,7 +184,7 @@ primary data for the merged source.</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -210,17 +200,15 @@ primary data for the merged source.</property>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="title_btn1">
<property name="label" translatable="yes">Title:</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Name:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -229,17 +217,15 @@ primary data for the merged source.</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="title_btn2">
<property name="label" translatable="yes">Title:</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Name:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -251,40 +237,36 @@ primary data for the merged source.</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="author_btn1">
<property name="label" translatable="yes">Author:</property>
<property name="use_action_appearance">False</property>
<object class="GtkRadioButton" id="template_btn1">
<property name="label" translatable="yes">Template:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="author_btn2">
<property name="label" translatable="yes">Author:</property>
<property name="use_action_appearance">False</property>
<object class="GtkRadioButton" id="template_btn2">
<property name="label" translatable="yes">Template:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<property name="group">author_btn1</property>
<property name="group">template_btn1</property>
</object>
<packing>
<property name="left_attach">2</property>
@ -292,17 +274,15 @@ primary data for the merged source.</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="abbrev_btn1">
<property name="label" translatable="yes">Abbreviation:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -311,17 +291,15 @@ primary data for the merged source.</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="abbrev_btn2">
<property name="label" translatable="yes">Abbreviation:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -333,77 +311,32 @@ primary data for the merged source.</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="pub_btn1">
<property name="label" translatable="yes">Publication:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="pub_btn2">
<property name="label" translatable="yes">Publication:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<property name="group">pub_btn1</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="gramps_btn1">
<property name="label" translatable="yes">Gramps ID:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="gramps_btn2">
<property name="label" translatable="yes">Gramps ID:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -412,10 +345,10 @@ primary data for the merged source.</property>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -429,7 +362,7 @@ primary data for the merged source.</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -443,11 +376,11 @@ primary data for the merged source.</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="author1">
<object class="GtkEntry" id="template1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@ -457,11 +390,11 @@ primary data for the merged source.</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="author2">
<object class="GtkEntry" id="template2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@ -471,7 +404,7 @@ primary data for the merged source.</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -485,7 +418,7 @@ primary data for the merged source.</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -499,35 +432,7 @@ primary data for the merged source.</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkEntry" id="pub1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkEntry" id="pub2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -539,9 +444,9 @@ primary data for the merged source.</property>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -556,14 +461,26 @@ primary data for the merged source.</property>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"/>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>

View File

@ -71,14 +71,14 @@ class MergeCitation(ManagedWindow):
_("Merge Citations"))
# Detailed Selection widgets
page1 = self.citation1.get_page()
page2 = self.citation2.get_page()
entry1 = self.get_widget("page1")
entry2 = self.get_widget("page2")
entry1.set_text(page1)
entry2.set_text(page2)
name1 = self.citation1.get_name()
name2 = self.citation2.get_name()
entry1 = self.get_widget("name1")
entry2 = self.get_widget("name2")
entry1.set_text(name1)
entry2.set_text(name2)
if entry1.get_text() == entry2.get_text():
for widget_name in ('page1', 'page2', 'page_btn1', 'page_btn2'):
for widget_name in ('name1', 'name2', 'name_btn1', 'name_btn2'):
self.get_widget(widget_name).set_sensitive(False)
entry1 = self.get_widget("date1")
@ -126,12 +126,12 @@ class MergeCitation(ManagedWindow):
def on_handle1_toggled(self, obj):
"""first chosen citation changes"""
if obj.get_active():
self.get_widget("page_btn1").set_active(True)
self.get_widget("name_btn1").set_active(True)
self.get_widget("date_btn1").set_active(True)
self.get_widget("confidence_btn1").set_active(True)
self.get_widget("gramps_btn1").set_active(True)
else:
self.get_widget("page_btn2").set_active(True)
self.get_widget("name_btn2").set_active(True)
self.get_widget("date_btn2").set_active(True)
self.get_widget("confidence_btn2").set_active(True)
self.get_widget("gramps_btn2").set_active(True)
@ -157,8 +157,8 @@ class MergeCitation(ManagedWindow):
self.uistate.viewmanager.active_page.get_history().push(
phoenix.get_handle())
if self.get_widget("page_btn1").get_active() ^ use_handle1:
phoenix.set_page(titanic.get_page())
if self.get_widget("name_btn1").get_active() ^ use_handle1:
phoenix.set_name(titanic.get_name())
if self.get_widget("date_btn1").get_active() ^ use_handle1:
phoenix.set_date_object(titanic.get_date_object())
if self.get_widget("confidence_btn1").get_active() ^ use_handle1:

View File

@ -70,8 +70,8 @@ class MergeSource(ManagedWindow):
_("Merge Sources"))
# Detailed Selection widgets
title1 = self.src1.get_title()
title2 = self.src2.get_title()
title1 = self.src1.get_name()
title2 = self.src2.get_name()
entry1 = self.get_widget("title1")
entry2 = self.get_widget("title2")
entry1.set_text(title1)
@ -80,13 +80,13 @@ class MergeSource(ManagedWindow):
for widget_name in ('title1', 'title2', 'title_btn1', 'title_btn2'):
self.get_widget(widget_name).set_sensitive(False)
entry1 = self.get_widget("author1")
entry2 = self.get_widget("author2")
entry1.set_text(self.src1.get_author())
entry2.set_text(self.src2.get_author())
entry1 = self.get_widget("template1")
entry2 = self.get_widget("template2")
entry1.set_text(self.src1.get_template())
entry2.set_text(self.src2.get_template())
if entry1.get_text() == entry2.get_text():
for widget_name in ('author1', 'author2', 'author_btn1',
'author_btn2'):
for widget_name in ('template1', 'template2', 'template_btn1',
'template_btn2'):
self.get_widget(widget_name).set_sensitive(False)
entry1 = self.get_widget("abbrev1")
@ -98,14 +98,6 @@ class MergeSource(ManagedWindow):
'abbrev_btn2'):
self.get_widget(widget_name).set_sensitive(False)
entry1 = self.get_widget("pub1")
entry2 = self.get_widget("pub2")
entry1.set_text(self.src1.get_publication_info())
entry2.set_text(self.src2.get_publication_info())
if entry1.get_text() == entry2.get_text():
for widget_name in ('pub1', 'pub2', 'pub_btn1', 'pub_btn2'):
self.get_widget(widget_name).set_sensitive(False)
gramps1 = self.src1.get_gramps_id()
gramps2 = self.src2.get_gramps_id()
entry1 = self.get_widget("gramps1")
@ -134,15 +126,13 @@ class MergeSource(ManagedWindow):
"""first chosen source changes"""
if obj.get_active():
self.get_widget("title_btn1").set_active(True)
self.get_widget("author_btn1").set_active(True)
self.get_widget("template_btn1").set_active(True)
self.get_widget("abbrev_btn1").set_active(True)
self.get_widget("pub_btn1").set_active(True)
self.get_widget("gramps_btn1").set_active(True)
else:
self.get_widget("title_btn2").set_active(True)
self.get_widget("author_btn2").set_active(True)
self.get_widget("template_btn2").set_active(True)
self.get_widget("abbrev_btn2").set_active(True)
self.get_widget("pub_btn2").set_active(True)
self.get_widget("gramps_btn2").set_active(True)
def cb_help(self, obj):
@ -167,13 +157,11 @@ class MergeSource(ManagedWindow):
phoenix.get_handle())
if self.get_widget("title_btn1").get_active() ^ use_handle1:
phoenix.set_title(titanic.get_title())
if self.get_widget("author_btn1").get_active() ^ use_handle1:
phoenix.set_author(titanic.get_author())
phoenix.set_name(titanic.get_name())
if self.get_widget("template_btn1").get_active() ^ use_handle1:
phoenix.set_template(titanic.get_template())
if self.get_widget("abbrev_btn1").get_active() ^ use_handle1:
phoenix.set_abbreviation(titanic.get_abbreviation())
if self.get_widget("pub_btn1").get_active() ^ use_handle1:
phoenix.set_publication_info(titanic.get_publication_info())
if self.get_widget("gramps_btn1").get_active() ^ use_handle1:
phoenix.set_gramps_id(titanic.get_gramps_id())

View File

@ -60,7 +60,7 @@ from gramps.gen.errors import WindowActiveError
from ...widgets.multitreeview import MultiTreeView
from ...ddtargets import DdTargets
from ..quick import run_quick_report_by_name
from ...editors import (EditPerson, EditEvent, EditFamily, EditCitation,
from ...editors import (EditPerson, EditEvent, EditFamily,
EditSource, EditPlace, EditRepository, EditNote,
EditMedia)
@ -216,9 +216,11 @@ class QuickTable(SimpleTable):
elif objclass == 'Citation':
ref = self.access.dbase.get_citation_from_handle(handle)
if ref:
dbstate = self.simpledoc.doc.dbstate
try:
EditCitation(self.simpledoc.doc.dbstate,
self.simpledoc.doc.uistate, [], ref)
EditSource(dbstate, self.simpledoc.doc.uistate, [],
dbstate.db.get_source_from_handle(
ref.get_reference_handle()), ref)
return True # handled event
except WindowActiveError:
pass

View File

@ -317,4 +317,10 @@ class GuiPluginManager(Callback):
def get_reg_general(self, category=None):
return [plg for plg in self.basemgr.get_reg_general(category)
if plg.id not in self.__hidden_plugins]
def get_reg_srctemplates(self):
"""
Obtain registered SrcTemplates
Srctemplates are already filtered on hidden in the base manager
"""
return self.basemgr.get_reg_srctemplates()

View File

@ -64,7 +64,7 @@ class SelectCitation(BaseSelector):
def get_column_titles(self):
return [
(_('Page'), 350, BaseSelector.TEXT, 0),
(_('Name'), 350, BaseSelector.TEXT, 0),
(_('ID'), 75, BaseSelector.TEXT, 1)
]

View File

@ -308,6 +308,13 @@ class ListView(NavigationView):
NavigationView.set_inactive(self)
self.uistate.viewmanager.tags.tag_disable()
def grab_focus(self):
"""
Inherit this method to indicate where to put focus if there is no
specific handle in focus
"""
self.list.grab_focus()
def __build_tree(self):
profile(self._build_tree)

View File

@ -196,11 +196,21 @@ class NavigationView(PageView):
self.navigation_group())
if active_handle:
self.goto_handle(active_handle)
else:
#make the pageview the object with focus, so moving arrow works
self.grab_focus()
hobj = self.get_history()
self.fwd_action.set_sensitive(not hobj.at_end())
self.back_action.set_sensitive(not hobj.at_front())
def grab_focus(self):
"""
Inherit this method to indicate where to put focus if there is no
specific handle in focus
"""
pass
def get_active(self):
"""
Return the handle of the active object.

View File

@ -2,7 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2011 Tim G L Lyons, Nick Hall
# Copyright (C) 2011-2013 Tim G L Lyons, Nick Hall
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -45,6 +45,7 @@ from gramps.gen.utils.string import confidence
from gramps.gen.config import config
from gramps.gen.constfunc import cuni
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.utils.citeref import get_gedcom_author, get_gedcom_pubinfo
#-------------------------------------------------------------------------
#
@ -56,7 +57,7 @@ from gramps.gen.const import GRAMPS_LOCALE as glocale
COLUMN_HANDLE = 0
COLUMN_ID = 1
COLUMN_DATE = 2
COLUMN_PAGE = 3
COLUMN_NAME = 3
COLUMN_CONFIDENCE = 4
COLUMN_SOURCE = 5
COLUMN_CHANGE = 9
@ -66,13 +67,12 @@ COLUMN_PRIV = 11
# Data for the Source object
COLUMN2_HANDLE = 0
COLUMN2_ID = 1
COLUMN2_TITLE = 2
COLUMN2_AUTHOR = 3
COLUMN2_PUBINFO = 4
COLUMN2_ABBREV = 7
COLUMN2_CHANGE = 8
COLUMN2_TAGS = 11
COLUMN2_PRIV = 12
COLUMN2_NAME = 2
COLUMN2_TEMPLATE = 3
COLUMN2_ABBREV = 6
COLUMN2_CHANGE = 7
COLUMN2_TAGS = 10
COLUMN2_PRIV = 11
INVALID_DATE_FORMAT = config.get('preferences.invalid-date-format')
@ -112,8 +112,8 @@ class CitationBaseModel(object):
def citation_id(self, data):
return cuni(data[COLUMN_ID])
def citation_page(self, data):
return cuni(data[COLUMN_PAGE])
def citation_name(self, data):
return cuni(data[COLUMN_NAME])
def citation_confidence(self, data):
return cuni(confidence[data[COLUMN_CONFIDENCE]])
@ -160,7 +160,15 @@ class CitationBaseModel(object):
source_handle = data[COLUMN_SOURCE]
try:
source = self.db.get_source_from_handle(source_handle)
return cuni(source.get_title())
return cuni(source.get_name())
except:
return ''
def citation_src_template(self, data):
source_handle = data[COLUMN_SOURCE]
try:
source = self.db.get_source_from_handle(source_handle)
return cuni(source.get_template())
except:
return ''
@ -173,10 +181,11 @@ class CitationBaseModel(object):
return ''
def citation_src_auth(self, data):
return ''
source_handle = data[COLUMN_SOURCE]
try:
source = self.db.get_source_from_handle(source_handle)
return cuni(source.get_author())
return cuni(get_gedcom_author(self.db, source))
except:
return ''
@ -189,10 +198,11 @@ class CitationBaseModel(object):
return ''
def citation_src_pinfo(self, data):
return ''
source_handle = data[COLUMN_SOURCE]
try:
source = self.db.get_source_from_handle(source_handle)
return cuni(source.get_publication_info())
return cuni(get_gedcom_pubinfo(self.db, source))
except:
return ''
@ -228,19 +238,24 @@ class CitationBaseModel(object):
# Fields access when 'data' is a Source
def source_src_title(self, data):
return cuni(data[COLUMN2_TITLE])
return cuni(data[COLUMN2_NAME])
def source_src_template(self, data):
return cuni(data[COLUMN2_TEMPLATE])
def source_src_id(self, data):
return cuni(data[COLUMN2_ID])
def source_src_auth(self, data):
return cuni(data[COLUMN2_AUTHOR])
source = self.db.get_source_from_handle(data[COLUMN2_HANDLE])
return cuni(get_gedcom_author(self.db, source))
def source_src_abbr(self, data):
return cuni(data[COLUMN2_ABBREV])
def source_src_pinfo(self, data):
return cuni(data[COLUMN2_PUBINFO])
source = self.db.get_source_from_handle(data[COLUMN2_HANDLE])
return cuni(get_gedcom_pubinfo(self.db, source))
def source_src_private(self, data):
if data[COLUMN2_PRIV]:

View File

@ -62,7 +62,7 @@ class CitationListModel(CitationBaseModel, FlatBaseModel):
self.map = db.get_raw_citation_data
self.gen_cursor = db.get_citation_cursor
self.fmap = [
self.citation_page,
self.citation_name,
self.citation_id,
self.citation_date,
self.citation_confidence,
@ -71,15 +71,15 @@ class CitationListModel(CitationBaseModel, FlatBaseModel):
self.citation_change,
self.citation_src_title,
self.citation_src_id,
self.citation_src_auth,
#self.citation_src_auth,
self.citation_src_abbr,
self.citation_src_pinfo,
#self.citation_src_pinfo,
self.citation_src_private,
self.citation_src_chan,
self.citation_tag_color
]
self.smap = [
self.citation_page,
self.citation_name,
self.citation_id,
self.citation_sort_date,
self.citation_confidence,
@ -88,9 +88,9 @@ class CitationListModel(CitationBaseModel, FlatBaseModel):
self.citation_sort_change,
self.citation_src_title,
self.citation_src_id,
self.citation_src_auth,
#self.citation_src_auth,
self.citation_src_abbr,
self.citation_src_pinfo,
#self.citation_src_pinfo,
self.citation_src_private,
self.citation_src_chan,
self.citation_tag_color
@ -113,7 +113,7 @@ class CitationListModel(CitationBaseModel, FlatBaseModel):
"""
Return the color column.
"""
return 14
return 12
def on_get_n_columns(self):
return len(self.fmap)+1

View File

@ -82,6 +82,7 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
self.source_src_private, # COL_PRIV (both Source & Citation)
self.source_src_tags, # COL_TAGS (both Source & Citation)
self.source_src_chan, # COL_CHAN (both Source & Citation)
self.source_src_template,# COL_TEMPLATE (Source only)
self.source_src_auth, # COL_SRC_AUTH (Source only)
self.source_src_abbr, # COL_SRC_ABBR (Source only)
self.source_src_pinfo, # COL_SRC_PINFO (Source only)
@ -95,6 +96,7 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
self.source_src_private,
self.source_src_tags,
self.source_sort2_change,
self.source_src_template,
self.source_src_auth,
self.source_src_abbr,
self.source_src_pinfo,
@ -132,7 +134,7 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
self.map2 = self.db.get_raw_citation_data
self.gen_cursor2 = self.db.get_citation_cursor
self.fmap2 = [
self.citation_page,
self.citation_name,
self.citation_id,
self.citation_date,
self.citation_confidence,
@ -142,10 +144,11 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
None,
None,
None,
None,
self.citation_tag_color
]
self.smap2 = [
self.citation_page,
self.citation_name,
self.citation_id,
self.citation_sort_date,
self.citation_confidence,
@ -155,6 +158,7 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
self.dummy_sort_key,
self.dummy_sort_key,
self.dummy_sort_key,
self.dummy_sort_key,
self.citation_tag_color
]
@ -162,7 +166,7 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
"""
Return the color column.
"""
return 10
return 11
def get_tree_levels(self):
"""
@ -188,7 +192,20 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
data The object data.
"""
sort_key = self.sort_func2(data)
# If the source for this citation already exists (in the tree model) we
# add the citation as a child of the source. Otherwise we add the source
# first (because citations don't have any meaning without the associated
# source)
if self._get_node(data[5]):
# parent child sortkey handle
self.add_node(data[5], handle, sort_key, handle, secondary=True)
else:
# add the source node first
source_sort_key = self.sort_func(self.map(data[5]))
# parent child sortkey handle
self.add_node(None, data[5], source_sort_key, data[5])
# parent child sortkey handle
self.add_node(data[5], handle, sort_key, handle, secondary=True)
def on_get_n_columns(self):

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -43,6 +44,18 @@ from gramps.gen.datehandler import format_time
from gramps.gen.constfunc import cuni
from .flatbasemodel import FlatBaseModel
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.utils.citeref import (get_gedcom_title, get_gedcom_author,
get_gedcom_pubinfo)
COLUMN_HANDLE = 0
COLUMN_ID = 1
COLUMN_NAME = 2
COLUMN_TEMPLATE = 3
COLUMN_ABBREV = 6
COLUMN_CHANGE = 7
COLUMN_TAGS = 10
COLUMN_PRIV = 11
#-------------------------------------------------------------------------
#
@ -56,22 +69,24 @@ class SourceModel(FlatBaseModel):
self.map = db.get_raw_source_data
self.gen_cursor = db.get_source_cursor
self.fmap = [
self.column_title,
self.column_name,
self.column_id,
self.column_author,
self.column_abbrev,
self.column_pubinfo,
self.column_template,
self.column_private,
self.column_tags,
self.column_change,
self.column_tag_color
]
self.smap = [
self.column_title,
self.column_name,
self.column_id,
self.column_author,
self.column_abbrev,
self.column_pubinfo,
self.column_template,
self.column_private,
self.column_tags,
self.sort_change,
@ -95,38 +110,43 @@ class SourceModel(FlatBaseModel):
"""
Return the color column.
"""
return 8
return 9
def on_get_n_columns(self):
return len(self.fmap)+1
def column_title(self,data):
return cuni(data[2])
def column_name(self, data):
return cuni(data[COLUMN_NAME])
def column_author(self,data):
return cuni(data[3])
def column_author(self, data):
source = self.db.get_source_from_handle(data[COLUMN_HANDLE])
return cuni(get_gedcom_author(self.db, source))
def column_abbrev(self,data):
return cuni(data[7])
def column_template(self, data):
return cuni(data[COLUMN_TEMPLATE])
def column_id(self,data):
return cuni(data[1])
def column_abbrev(self, data):
return cuni(data[COLUMN_ABBREV])
def column_pubinfo(self,data):
return cuni(data[4])
def column_id(self, data):
return cuni(data[COLUMN_ID])
def column_pubinfo(self, data):
source = self.db.get_source_from_handle(data[COLUMN_HANDLE])
return cuni(get_gedcom_pubinfo(self.db, source))
def column_private(self, data):
if data[12]:
if data[COLUMN_PRIV]:
return 'gramps-lock'
else:
# There is a problem returning None here.
return ''
def column_change(self,data):
return format_time(data[8])
return format_time(data[COLUMN_CHANGE])
def sort_change(self,data):
return "%012x" % data[8]
return "%012x" % data[COLUMN_CHANGE]
def get_tag_name(self, tag_handle):
"""
@ -140,7 +160,7 @@ class SourceModel(FlatBaseModel):
"""
tag_color = "#000000000000"
tag_priority = None
for handle in data[11]:
for handle in data[COLUMN_TAGS]:
tag = self.db.get_tag_from_handle(handle)
if tag:
this_priority = tag.get_priority()
@ -153,5 +173,5 @@ class SourceModel(FlatBaseModel):
"""
Return the sorted list of tags.
"""
tag_list = list(map(self.get_tag_name, data[11]))
tag_list = list(map(self.get_tag_name, data[COLUMN_TAGS]))
return ', '.join(sorted(tag_list, key=glocale.sort_key))

View File

@ -342,7 +342,10 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
self.__displayed = 0
self.set_search(search)
self.rebuild_data(self.current_filter, skip)
if self.has_secondary:
self.rebuild_data(self.current_filter, self.current_filter2, skip)
else:
self.rebuild_data(self.current_filter, skip=skip)
_LOG.debug(self.__class__.__name__ + ' __init__ ' +
str(time.clock() - cput) + ' sec')
@ -362,7 +365,9 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
self.rebuild_data = None
self._build_data = None
self.search = None
self.search2 = None
self.current_filter = None
self.current_filter2 = None
self.clear_cache()
self.lru_data = None
@ -447,31 +452,56 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
if search[0] == 1: # Filter
#following is None if no data given in filter sidebar
self.search = search[1]
if self.has_secondary:
self.search2 = search[1]
_LOG.debug("search2 filter %s %s" % (search[0], search[1]))
self._build_data = self._rebuild_filter
elif search[0] == 0: # Search
if search[1]:
# we have search[1] = (index, text_unicode, inversion)
col, text, inv = search[1]
func = lambda x: self._get_value(x, col, store_cache=False) or ""
func = lambda x: self._get_value(x, col, secondary=False) or u""
if self.has_secondary:
func2 = lambda x: self._get_value(x, col, secondary=True) or u""
if search[2]:
self.search = ExactSearchFilter(func, text, inv)
if self.has_secondary:
self.search2 = ExactSearchFilter(func2, text, inv)
else:
self.search = SearchFilter(func, text, inv)
if self.has_secondary:
self.search2 = SearchFilter(func2, text, inv)
else:
self.search = None
if self.has_secondary:
self.search2 = None
_LOG.debug("search2 search with no data")
self._build_data = self._rebuild_search
else: # Fast filter
self.search = search[1]
if self.has_secondary:
self.search2 = search[2]
_LOG.debug("search2 fast filter")
self._build_data = self._rebuild_search
else:
self.search = None
if self.has_secondary:
self.search2 = search[2]
_LOG.debug("search2 no search parameter")
self._build_data = self._rebuild_search
self.current_filter = self.search
if self.has_secondary:
self.current_filter2 = self.search2
def rebuild_data(self, data_filter=None, skip=[]):
def rebuild_data(self, data_filter=None, data_filter2=None, skip=[]):
"""
Rebuild the data map.
When called externally (from listview), data_filter and data_filter2
should be None; set_search will already have been called to establish
the filter functions. When called internally (from __init__) both
data_filter and data_filter2 will have been set from set_search
"""
cput = time.clock()
self.clear_cache()
@ -481,16 +511,21 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
return
self.clear()
self._build_data(self.current_filter, skip)
if self.has_secondary:
self._build_data(self.current_filter, self.current_filter2, skip)
else:
self._build_data(self.current_filter, None, skip)
self._in_build = False
self.current_filter = data_filter
if self.has_secondary:
self.current_filter2 = data_filter2
_LOG.debug(self.__class__.__name__ + ' rebuild_data ' +
str(time.clock() - cput) + ' sec')
def _rebuild_search(self, dfilter, skip):
def _rebuild_search(self, dfilter, dfilter2, skip):
"""
Rebuild the data map where a search condition is applied.
"""
@ -498,12 +533,14 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
self.__displayed = 0
items = self.number_items()
_LOG.debug("rebuild search primary")
self.__rebuild_search(dfilter, skip, items,
self.gen_cursor, self.add_row)
if self.has_secondary:
_LOG.debug("rebuild search secondary")
items = self.number_items2()
self.__rebuild_search(dfilter, skip, items,
self.__rebuild_search(dfilter2, skip, items,
self.gen_cursor2, self.add_row2)
def __rebuild_search(self, dfilter, skip, items, gen_cursor, add_func):
@ -533,20 +570,27 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
if not status.was_cancelled():
status.end()
def _rebuild_filter(self, dfilter, skip):
def _rebuild_filter(self, dfilter, dfilter2, skip):
"""
Rebuild the data map where a filter is applied.
"""
self.__total = 0
self.__displayed = 0
items = self.number_items()
self.__rebuild_filter(dfilter, skip, items,
self.gen_cursor, self.map, self.add_row)
if self.has_secondary:
items = self.number_items2()
if not self.has_secondary:
# The tree only has primary data
items = self.number_items()
_LOG.debug("rebuild filter primary")
self.__rebuild_filter(dfilter, skip, items,
self.gen_cursor2, self.map2, self.add_row2)
self.gen_cursor, self.map, self.add_row)
else:
# The tree has both primary and secondary data. The navigation type
# (navtype) which governs the filters that are offered, is for the
# secondary data.
items = self.number_items2()
_LOG.debug("rebuild filter secondary")
self.__rebuild_filter(dfilter2, skip, items,
self.gen_cursor2, self.map2, self.add_row2)
def __rebuild_filter(self, dfilter, skip, items, gen_cursor, data_map,
add_func):
@ -578,6 +622,7 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
status.heartbeat()
if dfilter:
_LOG.debug("rebuild filter %s" % dfilter)
status_filter = progressdlg.LongOpStatus(msg=_("Applying filter"),
total_steps=items, interval=items//10)
pmon.add_op(status_filter)
@ -743,13 +788,14 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
if self._get_node(handle) is not None:
return # row already exists
cput = time.clock()
if not self.search or \
(self.search and self.search.match(handle, self.db)):
#row needs to be added to the model
data = self.map(handle)
if data:
data = self.map(handle)
if data:
if not self.search or \
(self.search and self.search.match(handle, self.db)):
self.add_row(handle, data)
else:
else:
if not self.search2 or \
(self.search2 and self.search2.match(handle, self.db)):
self.add_row2(handle, self.map2(handle))
_LOG.debug(self.__class__.__name__ + ' add_row_by_handle ' +
@ -916,6 +962,9 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
"""
Returns the contents of a given column of a gramps object
"""
if secondary is None:
raise NotImplementedError
if handle in self.lru_data:
data = self.lru_data[handle]
else:
@ -923,16 +972,20 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel):
data = self.map(handle)
else:
data = self.map2(handle)
if not self._in_build and store_cache:
self.lru_data[handle] = data
try:
if not secondary:
return self.fmap[col](data)
else:
return self.fmap2[col](data)
except:
return ''
if not self._in_build:
self.lru_data[handle] = data
if not secondary:
# None is used to indicate this column has no data
if self.fmap[col] is None:
return ''
value = self.fmap[col](data)
else:
if self.fmap2[col] is None:
return ''
value = self.fmap2[col](data)
return value
def do_get_iter(self, path):
"""

View File

@ -182,3 +182,7 @@ class PrivacyButton(object):
self.obj.set_privacy(False)
image.show()
obj.add(image)
def update(self):
""" force an update so as to correspond with the object monitored"""
self.set_active(self.obj.get_privacy())

View File

@ -107,20 +107,35 @@ class MonitoredCheckbox(object):
class MonitoredEntry(object):
def __init__(self, obj, set_val, get_val, read_only=False,
autolist=None, changed=None):
autolist=None, changed=None, parameter=None):
"""
A monitored entry field. On changes, set_val will be called. get_val is
used to obtain the data. set and get_val are passed parameter if it is
not None.
Use autolist to use autocompletion.
"""
self.obj = obj
self.set_val = set_val
self.get_val = get_val
self.__set_func(set_val, get_val, parameter)
self.changed = changed
if get_val():
self.obj.set_text(get_val())
gval = self.get_val(self.parameter)
if gval:
self.obj.set_text(gval)
self.obj.connect('changed', self._on_change)
self.obj.set_editable(not read_only)
if autolist:
fill_entry(obj, autolist)
def __set_func(self, set_val, get_val, parameter):
if parameter is not None:
self.set_val = lambda x: set_val(x, parameter)
self.get_val = lambda x: get_val(parameter)
else:
self.set_val = set_val
self.get_val = lambda x: get_val()
self.parameter = parameter
## def destroy(self):
## """
## Unset all elements that can prevent garbage collection
@ -129,9 +144,8 @@ class MonitoredEntry(object):
## self.get_val = None
## self.obj = None
def reinit(self, set_val, get_val):
self.set_val = set_val
self.get_val = get_val
def reinit(self, set_val, get_val, parameter=None):
self.__set_func(set_val, get_val, parameter)
self.update()
def set_text(self, text):
@ -163,8 +177,9 @@ class MonitoredEntry(object):
self.obj.grab_focus()
def update(self):
if self.get_val() is not None:
self.obj.set_text(self.get_val())
""" force an update so as to correspond with the object monitored"""
if self.get_val(None) is not None:
self.obj.set_text(self.get_val(None))
#-------------------------------------------------------------------------
#
@ -177,11 +192,11 @@ class MonitoredEntryIndicator(MonitoredEntry):
entry becomes active
"""
def __init__(self, obj, set_val, get_val, indicator, read_only=False,
autolist=None, changed=None):
autolist=None, changed=None, parameter=None):
MonitoredEntry.__init__(self, obj, set_val, get_val, read_only,
autolist, changed)
autolist, changed, parameter)
self.origcolor = obj.get_style_context().get_color(Gtk.StateType.NORMAL)
if get_val():
if self.get_val(None):
self.indicatorshown = False
else:
self.indicatorshown = True
@ -548,6 +563,9 @@ class MonitoredMenu(object):
if self.changed:
self.changed()
def update(self):
""" force an update so as to correspond with the object monitored"""
self.obj.set_active(self.data.get(self.get_val(), 0))
#-------------------------------------------------------------------------
#
# MonitoredStrMenu class
@ -821,12 +839,7 @@ class MonitoredTagList(object):
self.track = track
self.db = db
self.set_list = set_list
self.tag_list = []
for handle in get_list():
tag = self.db.get_tag_from_handle(handle)
if tag:
self.tag_list.append((handle, tag.get_name()))
self.get_list = get_list
self.all_tags = []
for tag in self.db.iter_tags():
@ -843,7 +856,7 @@ class MonitoredTagList(object):
button.connect('key-press-event', self.cb_edit)
button.set_sensitive(not readonly)
self._display()
self.update()
## def destroy(self):
## """
@ -878,3 +891,12 @@ class MonitoredTagList(object):
self.set_list([item[0] for item in self.tag_list])
return True
return False
def update(self):
""" force an update so as to correspond with the object monitored"""
self.tag_list = []
for handle in self.get_list():
tag = self.db.get_tag_from_handle(handle)
if tag:
self.tag_list.append((handle, tag.get_name()))
self._display()

View File

@ -0,0 +1,206 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
A class to select source templates
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# GTK classes
#
#-------------------------------------------------------------------------
from gi.repository import Gdk
from gi.repository import Gtk
#-------------------------------------------------------------------------
#
# Gramps classes
#
#-------------------------------------------------------------------------
from gramps.gen.lib import SrcTemplate
#-------------------------------------------------------------------------
#
# SrcTemplateTreeView class
#
#-------------------------------------------------------------------------
class SrcTemplateTreeView(Gtk.TreeView):
'''
TreeView for SrcTemplate templates, to allow fast selection
'''
def __init__(self, default_key, db, sel_callback):
"""
Set up the treeview to select template.
TreeView is initialized to default_key
On setting a selection, sel_callback is called
"""
Gtk.TreeView.__init__(self)
self.db = db
self.sel_callback = sel_callback
self.default_key = default_key
self.build_model()
self.make_columns()
self.selection = self.get_selection()
self.set_model(self.model)
if default_key:
# The default key, normally the GEDCOM template, is available
self.goto(default_key)
# set up selection and fields on click
self.connect('button-release-event', self._on_button_release)
self.connect('key_press_event', self._on_key_press_event)
def build_model(self):
"""
Obtains all templates and stores them in a TreeStore
"""
self.Key2Path = {}
# store (key, src_type)
self.model = Gtk.TreeStore(str, str)
tlist = self.db.get_template_handles()
alltexts = sorted((self.db.get_template_from_handle(handle).get_descr(),
handle)
for handle in tlist )
parentiter = None
parentiterlev1 = None
prevstrval = ['', '']
for alltext, key in alltexts:
vals = alltext.split('-')
if len(vals) > 3:
vals = [vals[0], vals[1], ' - '.join(vals[2:])]
vals = [x.strip() for x in vals]
#lastval is last non '' value
lastval = vals[-1]
if not lastval:
lastval = vals[-2]
if not lastval:
lastval = vals[-3]
truevals = ['','','']
if len(vals) < 3 :
truevals[:len(vals)] = vals[:]
vals = truevals
row = [key, lastval]
iter = None
if prevstrval[0] == vals[0] and prevstrval[1] == vals[1]:
#same parentiter
iter = self.model.append(parentiter, row)
elif prevstrval[0] == vals[0]:
#up one parentiter, make new sublevel2 if needed
parentiter = parentiterlev1
if vals[2]:
parentiter = self.model.append(parentiter, ['', vals[1]])
iter = self.model.append(parentiter, row)
else:
#new value
parentiterlev1 = None
if vals[2] and vals[1]:
#new sublevel1 and 2 needed
parentiterlev1 = self.model.append(None, ['', vals[0]])
#make sublevel2
parentiter= self.model.append(parentiterlev1, ['', vals[1]])
iter = self.model.append(parentiter, row)
elif vals[1]:
#only new sublevel1 needed
parentiterlev1 = self.model.append(None, ['', vals[0]])
parentiter = parentiterlev1
iter = self.model.append(parentiter, row)
else:
#only a top level
iter = self.model.append(None, row)
#store key to path
self.Key2Path[row[0]] = self.model.get_path(iter)
prevstrval = [vals[0], vals[1]]
def make_columns(self):
#make the column in the treeview
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(_("Template"), renderer, text=1)
self.append_column(column)
#no headers needed:
self.set_headers_visible (False)
def goto(self, key):
"""
highlight key in the view
"""
#we determine the path of key
path = self.Key2Path[key]
iter_ = self.model.get_iter(path)
if iter_:
# Expand tree
parent_iter = self.model.iter_parent(iter_)
if parent_iter:
parent_path = self.model.get_path(parent_iter)
parent_path_list = parent_path.get_indices()
for i in range(len(parent_path_list)):
expand_path = Gtk.TreePath(
tuple([x for x in parent_path_list[:i+1]]))
self.expand_row(expand_path, False)
# Select active object
self.selection.unselect_all()
self.selection.select_path(path)
self.scroll_to_cell(path, None, 1, 0.5, 0)
self.sel_callback(key)
def get_selected(self):
"""
Return the (index, key) associated with selected row in the model,
"""
(model, node) = self.selection.get_selected()
if node:
return (model.get_value(node, 0), node)
return None
def _on_button_release(self, obj, event):
"""
Handle button press
"""
if event.type == Gdk.EventType.BUTTON_RELEASE and event.button == 1:
ref = self.get_selected()
if ref and ref[0] != '':
self.sel_callback(ref[0])
return False
def _on_key_press_event(self, widget, event):
if event.type == Gdk.EventType.KEY_PRESS:
if event.keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter):
ref = self.get_selected()
if ref:
if ref[0] != '':
self.sel_callback(ref[0])
else:
path = self.model.get_path(ref[0])
if self.row_expanded(path):
self.collapse_row(path)
else:
self.expand_row(path, False)
return False

View File

@ -102,7 +102,7 @@ def get_primary_source_title(db, obj):
citation = db.get_citation_from_handle(citation_handle)
source = db.get_source_from_handle(citation.get_reference_handle())
if source:
return source.get_title()
return source.get_name()
return ""
#-------------------------------------------------------------------------

View File

@ -908,15 +908,22 @@ class GedcomWriter(UpdateCallback):
for (source_id, handle) in sorted_list:
source = self.dbase.get_source_from_handle(handle)
if source is None: continue
templatehandle = source.get_template()
if templatehandle is None: continue
template = self.dbase.get_template_from-handle(templatehandle)
self._writeln(0, '@%s@' % source_id, 'SOUR')
if source.get_title():
self._writeln(1, 'TITL', source.get_title())
attrlist = source.get_attribute_list()
stitle = template.title_gedcom(attrlist)
if stitle:
self._writeln(1, 'TITL', stitle)
if source.get_author():
self._writeln(1, "AUTH", source.get_author())
sauth = template.author_gedcom(attrlist)
if sauth:
self._writeln(1, "AUTH", sauth)
if source.get_publication_info():
self._writeln(1, "PUBL", source.get_publication_info())
spubi = template.pubinfo_gedcom(attrlist)
if spubi:
self._writeln(1, "PUBL", spubi)
if source.get_abbreviation():
self._writeln(1, 'ABBR', source.get_abbreviation())
@ -1267,11 +1274,17 @@ class GedcomWriter(UpdateCallback):
# Reference to the source
self._writeln(level, "SOUR", "@%s@" % src.get_gramps_id())
if citation.get_page() != "":
templatehandle = src.get_template()
if templatehandle:
template = self.dbase.get_template_from_handle(templatehandle)
gedcom_page = template.page_gedcom(citation.get_attribute_list())
else:
gedcom_page = citation.get_name()
if gedcom_page != "":
# PAGE <WHERE_WITHIN_SOURCE> can not have CONC lines.
# WHERE_WITHIN_SOURCE:= {Size=1:248}
# Maximize line to 248 and set limit to 248, for no line split
self._writeln(level+1, 'PAGE', citation.get_page()[0:248],
self._writeln(level+1, 'PAGE', gedcom_page[0:248],
limit=248)

View File

@ -178,7 +178,7 @@ class GeneWebWriter(object):
)
)
def write_sources(self,reflist):
def write_sources(self, reflist):
# FIXME
#if self.restrict and self.exclnotes:
# return
@ -190,7 +190,7 @@ class GeneWebWriter(object):
source = self.db.get_source_from_handle(src_handle)
if source:
self.writeln( "src %s" %
(self.rem_spaces(source.get_title()))
(self.rem_spaces(source.get_name()))
)
def write_children(self,family, father):
@ -422,7 +422,7 @@ class GeneWebWriter(object):
return ret
def get_primary_source(self,reflist):
def get_primary_source(self, reflist):
ret = ""
if reflist:
for handle in reflist:
@ -432,7 +432,7 @@ class GeneWebWriter(object):
if source:
if ret != "":
ret = ret + ", "
ret = ret + source.get_title()
ret = ret + source.get_name()
return ret
def format_single_date(self, subdate, cal, mode):

View File

@ -208,11 +208,12 @@ class GrampsXmlWriter(UpdateCallback):
repo_len = self.db.get_number_of_repositories()
obj_len = self.db.get_number_of_media_objects()
note_len = self.db.get_number_of_notes()
tag_len = self.db.get_number_of_tags()
tag_len = self.db.get_number_of_tags()
template_len = self.db.get_number_of_templates()
total_steps = (person_len + family_len + event_len + citation_len +
source_len + place_len + repo_len + obj_len + note_len +
tag_len
tag_len + template_len
)
self.set_total(total_steps)
@ -256,6 +257,14 @@ class GrampsXmlWriter(UpdateCallback):
self.update()
self.g.write(" </tags>\n")
if template_len > 0:
self.g.write(" <SourceTemplates>\n")
for key in sorted(self.db.get_template_handles()):
template = self.db.get_template_from_handle(key)
self.write_template(template, 2)
self.update()
self.g.write(" </SourceTemplates>\n")
# Write primary objects
if event_len > 0:
self.g.write(" <events>\n")
@ -350,6 +359,9 @@ class GrampsXmlWriter(UpdateCallback):
mediapath= self.db.get_mediapath()
if mediapath is not None:
self.write_line("mediapath", mediapath, 2)
gedcom_handle = self.db.get_GEDCOM_template_handle()
if gedcom_handle is not None:
self.write_line("gedcom_template", gedcom_handle, 2)
def write_namemaps(self):
group_map = self.db.get_name_group_keys()
@ -435,6 +447,22 @@ class GrampsXmlWriter(UpdateCallback):
self.g.write(' priority="%d"' % tag.get_priority())
self.g.write('/>\n')
def write_template(self, template, index=2):
"""
Write a template definition.
"""
if not template:
return
sp = " "*index
self.write_template_tag('template', template, index)
self.write_force_line("tname", template.get_name(), index+1)
self.write_line("tdescription", template.get_descr(), index+1)
self.write_map_list(template.get_map_dict(), index+1)
self.write_te_list(template.get_template_element_list(), index+1)
self.g.write("%s</template>\n" % sp)
def fix(self,line):
try:
l = cuni(line)
@ -579,7 +607,7 @@ class GrampsXmlWriter(UpdateCallback):
sp = " " * index
self.write_primary_tag("citation", citation, index)
self.write_date(citation.get_date_object(), index+1)
self.write_line("page", citation.get_page(), index+1)
self.write_line("cname", citation.get_name(), index+1)
self.write_line("confidence", citation.get_confidence_level(), index+1)
self.write_note_list(citation.get_note_list(), index+1)
self.write_media_list(citation.get_media_list(), index+1)
@ -594,9 +622,8 @@ class GrampsXmlWriter(UpdateCallback):
def write_source(self, source, index=1):
sp = " "*index
self.write_primary_tag("source", source, index)
self.write_force_line("stitle", source.get_title(), index+1)
self.write_line("sauthor", source.get_author(), index+1)
self.write_line("spubinfo", source.get_publication_info(), index+1)
self.write_force_line("sname", source.get_name(), index+1)
self.write_ref("stemplate", source.get_template(), index+1)
self.write_line("sabbrev", source.get_abbreviation(), index+1)
self.write_note_list(source.get_note_list(), index+1)
self.write_media_list(source.get_media_list(), index+1)
@ -810,6 +837,25 @@ class GrampsXmlWriter(UpdateCallback):
if close:
self.g.write('>\n')
def write_template_tag(self, templatename, obj, index=1, close=True):
"""
Write the template attributes common to all table objects.
"""
if not obj:
return
sp = " " * index
try:
change_text = ' change="%d"' % obj.get_change_time()
except:
change_text = ' change="%d"' % 0
handle_text = ' handle="_%s"' % obj.get_handle()
obj_text = '%s<%s' % (sp, templatename)
self.g.write(obj_text + handle_text + change_text)
if close:
self.g.write('>\n')
def write_family_handle(self,family,index=1):
sp = " "*index
self.write_primary_tag('family',family,index)
@ -1175,6 +1221,27 @@ class GrampsXmlWriter(UpdateCallback):
)
)
def write_map_list(self, map_dict, indent=3):
sp = ' ' * indent
for (key, value) in list(map_dict.items()):
self.g.write('%s<tmap key="%s" value="%s"' %
(sp, escxml(key), self.fix(value))
)
self.g.write('/>\n')
def write_te_list(self, te_list, index=1):
sp = " "*index
for te in te_list:
self.g.write('%s<tefield type="text" citation="%s" short="%s" short_alg="%s" >\n' %
(sp, te.get_citation(), te.get_short(), te.get_short_alg())
)
self.write_line("tename", te.get_name(), index+1)
self.write_line("Display", te.get_display(), index+1)
self.write_line("Hint", te.get_hint(), index+1)
self.write_line("Tooltip", te.get_tooltip(), index+1)
self.g.write('%s</tefield>\n' % sp)
pass
def write_place_obj(self, place, index=1):
self.write_primary_tag("placeobj", place, index)

View File

@ -20,7 +20,7 @@
# $Id$
#
from gramps.gui.editors import EditSource, EditCitation
from gramps.gui.editors import EditSource
from gramps.gui.listmodel import ListModel, NOSORT
from gramps.gen.plug import Gramplet
from gramps.gui.dbguielement import DbGUIElement
@ -28,6 +28,8 @@ from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from gramps.gen.errors import WindowActiveError
from gi.repository import Gtk
from gramps.gen.utils.citeref import (get_gedcom_title, get_gedcom_author,
get_gedcom_pubinfo)
class Citations(Gramplet, DbGUIElement):
@ -142,9 +144,9 @@ class Citations(Gramplet, DbGUIElement):
page = _('<No Citation>')
source_handle = citation.get_reference_handle()
source = self.dbstate.db.get_source_from_handle(source_handle)
title = source.get_title()
author = source.get_author()
publisher = source.get_publication_info()
title = get_gedcom_title(self.dbstate.db, source)
author = get_gedcom_author(self.dbstate.db, source)
publisher = get_gedcom_pubinfo(self.dbstate.db, source)
if source_handle not in self.source_nodes:
node = self.model.add([source_handle, title, author, publisher])
@ -268,7 +270,7 @@ class Citations(Gramplet, DbGUIElement):
citation = self.dbstate.db.get_citation_from_handle(handle)
source_handle = citation.get_reference_handle()
source = self.dbstate.db.get_source_from_handle(source_handle)
EditCitation(self.dbstate, self.uistate, [], citation, source)
EditSource(self.dbstate, self.uistate, [], source, citation)
except WindowActiveError:
pass

View File

@ -50,7 +50,9 @@ LOG = logging.getLogger(".ImportCSV")
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.sgettext
from gramps.gen.lib import ChildRef, Citation, Event, EventRef, EventType, Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place, Source, Surname, Tag
from gramps.gen.lib import (ChildRef, Citation, Event, EventRef, EventType,
Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place,
Source, Surname, SrcAttribute, SrcAttributeType, Tag)
from gramps.gen.db import DbTxn
from gramps.gen.plug.utils import OpenFileOrStdin
from gramps.gen.datehandler import parser as _dp
@ -829,12 +831,16 @@ class CSVParser(object):
LOG.debug("get_or_create_source: looking for: %s", source_text)
for source_handle in source_list:
source = self.db.get_source_from_handle(source_handle)
if source.get_title() == source_text:
if source.get_name() == source_text:
LOG.debug(" returning existing source")
return (0, source)
LOG.debug(" creating source")
source = Source()
source.set_title(source_text)
source.set_name(source_text)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(source_text)
source.add_attribute(sattr)
self.db.add_source(source, self.trans)
return (1, source)

View File

@ -50,7 +50,10 @@ LOG = logging.getLogger(".ImportGeneWeb")
#
#-------------------------------------------------------------------------
from gramps.gen.errors import GedcomError
from gramps.gen.lib import Attribute, AttributeType, ChildRef, Citation, Date, Event, EventRef, EventRoleType, EventType, Family, FamilyRelType, Name, NameType, Note, Person, PersonRef, Place, Source
from gramps.gen.lib import (Attribute, AttributeType, ChildRef, Citation, Date,
Event, EventRef, EventRoleType, EventType, Family, FamilyRelType,
Name, NameType, Note, Person, PersonRef, Place, Source,
SrcAttribute, SrcAttributeType)
from gramps.gen.db import DbTxn
from gramps.gen.constfunc import STRTYPE, cuni, conv_to_unicode
if sys.version_info[0] < 3:
@ -876,9 +879,13 @@ class GeneWebParser(object):
source = self.db.get_source_from_handle(self.skeys[source_name])
else:
source = Source()
source.set_title(source_name)
self.db.add_source(source,self.trans)
self.db.commit_source(source,self.trans)
source.set_name(source_name)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(source_name)
source.add_attribute(sattr)
self.db.add_source(source, self.trans)
self.db.commit_source(source, self.trans)
self.skeys[source_name] = source.get_handle()
citation = Citation()
citation.set_reference_handle(source.get_handle())

View File

@ -55,7 +55,8 @@ from gramps.gui.utils import ProgressMeter
from gramps.gen.lib import (Attribute, AttributeType, ChildRef, Date, Event,
EventRef, EventType, Family, FamilyRelType, Name,
NameType, Note, NoteType, Person, Place, Source,
Surname, Citation, Location, NameOriginType)
Surname, Citation, Location, NameOriginType,
SrcAttribute, SrcAttributeType)
from gramps.gen.db import DbTxn
class ProgenError(Exception):
@ -611,7 +612,11 @@ class ProgenParser(object):
else:
# Create a new Source
source = Source()
source.set_title(source_name)
source.set_name(source_name)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(source_name)
source.add_attribute(sattr)
self.db.add_source(source, self.trans)
self.db.commit_source(source, self.trans)
self.skeys[source_name] = source.get_handle()

View File

@ -55,7 +55,7 @@ from gramps.gen.lib import (Address, Attribute, AttributeType, ChildRef,
Place, RepoRef, Repository, Researcher, Source,
SrcAttribute, SrcAttributeType,
StyledText, StyledTextTag, StyledTextTagType,
Surname, Tag, Url)
Surname, Tag, Url, SrcTemplate, TemplateElement)
from gramps.gen.db import DbTxn
from gramps.gen.db.write import CLASS_TO_KEY_MAP
from gramps.gen.errors import GrampsImportError
@ -67,7 +67,7 @@ from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY,
EVENT_KEY, MEDIA_KEY, PLACE_KEY,
REPOSITORY_KEY, NOTE_KEY, TAG_KEY,
CITATION_KEY)
CITATION_KEY, TEMPLATE_KEY)
from gramps.gen.updatecallback import UpdateCallback
from gramps.version import VERSION
from gramps.gen.config import config
@ -215,7 +215,8 @@ class ImportInfo(object):
Class object that can hold information about the import
"""
keyorder = [PERSON_KEY, FAMILY_KEY, SOURCE_KEY, EVENT_KEY, MEDIA_KEY,
PLACE_KEY, REPOSITORY_KEY, NOTE_KEY, TAG_KEY, CITATION_KEY]
PLACE_KEY, REPOSITORY_KEY, NOTE_KEY, TAG_KEY, CITATION_KEY,
TEMPLATE_KEY]
key2data = {
PERSON_KEY : 0,
FAMILY_KEY : 1,
@ -226,7 +227,8 @@ class ImportInfo(object):
REPOSITORY_KEY: 6,
NOTE_KEY: 7,
TAG_KEY: 8,
CITATION_KEY: 9
CITATION_KEY: 9,
TEMPLATE_KEY: 10
}
def __init__(self):
@ -235,9 +237,9 @@ class ImportInfo(object):
This creates the datastructures to hold info
"""
self.data_mergecandidate = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}]
self.data_newobject = [0] * 10
self.data_unknownobject = [0] * 10
self.data_mergecandidate = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]
self.data_newobject = [0] * 11
self.data_unknownobject = [0] * 11
self.data_families = ''
self.expl_note = ''
self.data_relpath = False
@ -315,6 +317,7 @@ class ImportInfo(object):
NOTE_KEY : _(' Notes: %d\n'),
TAG_KEY : _(' Tags: %d\n'),
CITATION_KEY : _(' Citations: %d\n'),
TEMPLATE_KEY : _(' Source Templates; %d\n'),
}
txt = _("Number of new objects imported:\n")
for key in self.keyorder:
@ -537,6 +540,7 @@ class GrampsParser(UpdateCallback):
self.attribute = None
self.srcattribute = None
self.placeobj = None
self.template = None
self.locations = 0
self.place_map = {}
@ -625,7 +629,7 @@ class GrampsParser(UpdateCallback):
"attribute": (self.start_attribute, self.stop_attribute),
"attr_type": (None, self.stop_attr_type),
"attr_value": (None, self.stop_attr_value),
"srcattribute": (self.start_srcattribute, self.stop_srcattribute),
"srcattribute": (self.start_srcattribute, self.stop_srcattribute), #new in 1.6.0
"bookmark": (self.start_bmark, None),
"bookmarks": (None, None),
"format": (self.start_format, None),
@ -673,7 +677,8 @@ class GrampsParser(UpdateCallback):
"objref": (self.start_objref, self.stop_objref),
"object": (self.start_object, self.stop_object),
"file": (self.start_file, None),
"page": (None, self.stop_page),
"page": (None, self.stop_page), #deprecated in 1.6.0
"cname": (None, self.stop_cname),
"place": (self.start_place, self.stop_place),
"dateval": (self.start_dateval, None),
"daterange": (self.start_daterange, None),
@ -701,22 +706,34 @@ class GrampsParser(UpdateCallback):
"respostal": (None, self.stop_respostal),
"resphone": (None, self.stop_resphone),
"resemail": (None, self.stop_resemail),
"sauthor": (None, self.stop_sauthor),
"sauthor": (None, self.stop_sauthor), #deprecated in 1.6.0
"sabbrev": (None, self.stop_sabbrev),
"scomments": (None, self.stop_scomments),
"source": (self.start_source, self.stop_source),
"sourceref": (self.start_sourceref, self.stop_sourceref),
"sources": (None, None),
"spage": (None, self.stop_spage),
"spubinfo": (None, self.stop_spubinfo),
"SourceTemplates": (None, None),
"spage": (None, self.stop_spage), #deprecated
"spubinfo": (None, self.stop_spubinfo), #deprecated in 1.6.0
"state": (None, self.stop_state),
"stext": (None, self.stop_stext),
"stitle": (None, self.stop_stitle),
"stitle": (None, self.stop_stitle), #deprecated in 1.6.0
"sname": (None, self.stop_sname), #new in 1.6.0
"stemplate": (self.start_stemplate, None), #new in 1.6.0
"street": (None, self.stop_street),
"style": (self.start_style, None),
"tag": (self.start_tag, self.stop_tag),
"tagref": (self.start_tagref, None),
"tags": (None, None),
"tdescription": (None, self.stop_tdescription),
"tefield": (self.start_tefield, self.stop_tefield),
"tename": (None, self.stop_tename),
"tedisplay": (None, self.stop_tedisplay),
"tehint": (None, self.stop_tehint),
"tetooltip": (None, self.stop_tetooltip),
"template": (self.start_template, self.stop_template),
"tmap": (self.start_tmap, None),
"tname": (None, self.stop_tname), # Template name
"text": (None, self.stop_text),
"url": (self.start_url, None),
"repository": (self.start_repo, self.stop_repo),
@ -764,7 +781,8 @@ class GrampsParser(UpdateCallback):
"repository": self.db.get_raw_repository_data,
"media": self.db.get_raw_object_data,
"note": self.db.get_raw_note_data,
"tag": self.db.get_raw_tag_data}[target]
"tag": self.db.get_raw_tag_data,
"template": self.db.get_raw_template_data}[target]
raw = get_raw_obj_data(handle)
prim_obj.unserialize(raw)
self.import_handles[orig_handle][target][INSTANTIATED] = True
@ -792,7 +810,8 @@ class GrampsParser(UpdateCallback):
"repository": self.db.has_repository_handle,
"media": self.db.has_object_handle,
"note": self.db.has_note_handle,
"tag": self.db.has_tag_handle}[target]
"tag": self.db.has_tag_handle,
"template": self.db.has_template_handle}[target]
while has_handle_func(handle):
handle = create_id()
self.import_handles[orig_handle] = {target: [handle, False]}
@ -803,6 +822,8 @@ class GrampsParser(UpdateCallback):
prim_obj.set_handle(handle)
if target == "tag":
self.db.add_tag(prim_obj, self.trans)
elif target == "template":
self.db.add_template(prim_obj, self.trans)
else:
add_func = {"person": self.db.add_person,
"family": self.db.add_family,
@ -1804,6 +1825,68 @@ class GrampsParser(UpdateCallback):
self.note_tags[-1].ranges.append((int(attrs['start']),
int(attrs['end'])))
def start_template(self, attrs):
"""
Template definition.
"""
# Tag defintion
self.template = SrcTemplate()
self.inaugurate(attrs['handle'], "template", self.template)
self.template.change = int(attrs.get('change', self.change))
self.info.add('new-object', TEMPLATE_KEY, self.template)
self.template.set_name(attrs.get('tname', _('Unknown when imported')))
self.template.set_descr(attrs.get('tdescription', _('Unknown when imported')))
return self.template
def stop_template(self, *tag):
self.db.commit_template(self.template, self.trans, self.template.get_change_time())
self.template = None
def stop_tname(self, tag):
self.template.set_name(tag)
def stop_tdescription(self, tag):
self.template.set_descr(tag)
def start_tmap(self, attrs):
self.template.set_map_element(attrs["key"], attrs["value"])
@staticmethod
def _conv_bool(val, default):
"""
Converts a string attribute to True or False. If the attribute is absent
(val is None) the default value is returned. If the value is "True" then
True is returned and vice-versa for False
"""
if val is None:
return default
if val == "True":
return True
else:
return False
def start_tefield(self, attrs):
self.template_element = TemplateElement()
self.template_element.set_citation(self._conv_bool(attrs.get("citation"), False))
self.template_element.set_short(self._conv_bool(attrs.get("short"), False))
self.template_element.set_short_alg(attrs.get("short_alg", None))
def stop_tename(self, tag):
self.template_element.set_name(tag)
def stop_tedisplay(self, tag):
self.template_element.set_display(tag)
def stop_tehint(self, tag):
self.template_element.set_hint(tag)
def stop_tetooltip(self, tag):
self.template_element.set_tooltip(tag)
def stop_tefield(self, tag):
self.template.add_template_element(self.template_element)
self.template_element = None
def start_note(self, attrs):
"""
Add a note to db if it doesn't exist yet and assign
@ -2080,6 +2163,7 @@ class GrampsParser(UpdateCallback):
self.inaugurate_id(attrs.get('id'), SOURCE_KEY, self.source)
self.source.private = bool(attrs.get("priv"))
self.source.change = int(attrs.get('change', self.change))
self.source.template = None
self.info.add('new-object', SOURCE_KEY, self.source)
return self.source
@ -2725,8 +2809,25 @@ class GrampsParser(UpdateCallback):
else:
self.person.set_gender (Person.UNKNOWN)
def stop_sname(self, tag):
#store descriptive name of the source
self.source.name = tag
def start_stemplate(self, attrs):
"""
Add a template reference to the source object currently being processed
"""
handle = self.inaugurate(attrs['hlink'], "template", SrcTemplate)
self.source.set_template(handle)
def stop_stitle(self, tag):
self.source.title = tag
#title was deprecated and converted to name and attribute TITLE in 1.6.0
if not self.source.name:
self.source.name = tag
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(tag)
self.source.add_attribute(sattr)
def stop_sourceref(self, *tag):
# if we are in an old style sourceref we need to commit the citation
@ -2737,6 +2838,18 @@ class GrampsParser(UpdateCallback):
self.in_old_sourceref = False
def stop_source(self, *tag):
# Template are new at 1.6.0. Prior to 1.6.0, sources (and citations) wll
# be GEDCOM style, so the template needs to be set to GEDCOM - if the
# GEDCOM template has not alraedy been defined, it needs to be built.
if self.__xml_version < '1.6.0':
gedcom_handle = self.db.get_GEDCOM_template_handle()
if gedcom_handle is None:
from gramps.plugins.srctemplates.gedcomtemplate import load_template
load_template(self.db)
gedcom_handle = self.db.get_GEDCOM_template_handle()
self.source.set_template(gedcom_handle)
# From xml version 1.6.0, if the template is None, this is intentional,
# and there is no template defined.
self.db.commit_source(self.source, self.trans,
self.source.get_change_time())
self.source = None
@ -2747,7 +2860,11 @@ class GrampsParser(UpdateCallback):
self.citation = None
def stop_sauthor(self, tag):
self.source.author = tag
#author was deprecated and converted to attribute AUTHOR in 1.6.0
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.AUTHOR)
sattr.set_value(tag)
self.source.add_attribute(sattr)
def stop_phone(self, tag):
self.address.phone = tag
@ -2775,11 +2892,25 @@ class GrampsParser(UpdateCallback):
def stop_spage(self, tag):
# Valid for version <= 1.4.0
self.citation.set_page(tag)
if not self.citation.name:
self.citation.set_name(tag)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.PAGE)
sattr.set_value(tag)
self.citation.add_attribute(sattr)
def stop_cname(self, tag):
self.citation.set_name(tag)
def stop_page(self, tag):
# Valid for version >= 1.5.0
self.citation.set_page(tag)
# page was deprecated and converted to name and attribute PAGE in 1.6.0
if not self.citation.name:
self.citation.set_name(tag)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.PAGE)
sattr.set_value(tag)
self.citation.add_attribute(sattr)
def stop_confidence(self, tag):
# Valid for version >= 1.5.0
@ -2789,7 +2920,11 @@ class GrampsParser(UpdateCallback):
self.ord = None
def stop_spubinfo(self, tag):
self.source.set_publication_info(tag)
#pubinfo was deprecated and converted to attribute PUB_INFO in 1.6.0
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.PUB_INFO)
sattr.set_value(tag)
self.source.add_attribute(sattr)
def stop_sabbrev(self, tag):
self.source.set_abbreviation(tag)

View File

@ -1852,7 +1852,12 @@ class GedcomParser(UpdateCallback):
if self.use_def_src:
self.def_src = Source()
fname = os.path.basename(filename).split('\\')[-1]
self.def_src.set_title(_("Import from GEDCOM (%s)") % fname)
stitle = _("Import from GEDCOM (%s)") % fname
self.def_src.set_name(stitle)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(stitle)
self.def_src.add_attribute(sattr)
if default_tag_format:
name = time.strftime(default_tag_format)
tag = self.dbase.get_tag_from_name(name)
@ -2664,7 +2669,11 @@ class GedcomParser(UpdateCallback):
for title, handle in self.inline_srcs.items():
src = Source()
src.set_handle(handle)
src.set_title(title)
src.set_name(title)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(title)
src.add_attribute(sattr)
self.dbase.add_source(src, self.trans)
self.__clean_up()
@ -3380,7 +3389,11 @@ class GedcomParser(UpdateCallback):
# A source formatted in a single line, for example:
# 0 @S62@ SOUR This is the title of the source
source = self.__find_or_create_source(self.sid_map[line.data])
source.set_title(line.data[5:])
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(line.data[5:])
source.add_attribute(sattr)
source.set_name(line.data[5:])
self.dbase.commit_source(source, self.trans)
elif key[0:4] == "NOTE":
try:
@ -5865,7 +5878,12 @@ class GedcomParser(UpdateCallback):
@param state: The current state
@type state: CurrentState
"""
state.citation.set_page(line.data)
page = line.data
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.PAGE)
sattr.set_value(page)
state.citation.add_attribute(sattr)
state.citation.set_name(page)
def __citation_date(self, line, state):
"""
@ -6052,7 +6070,7 @@ class GedcomParser(UpdateCallback):
state = CurrentState()
state.source = self.__find_or_create_source(self.sid_map[name])
# SOURce with the given gramps_id had no title
state.source.set_title(_("No title - ID %s") %
state.source.set_name(_("No title - ID %s") %
state.source.get_gramps_id())
state.level = level
@ -6247,7 +6265,10 @@ class GedcomParser(UpdateCallback):
@param state: The current state
@type state: CurrentState
"""
state.source.set_author(line.data)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.AUTHOR)
sattr.set_value(line.data)
state.source.add_attribute(sattr)
def __source_publ(self, line, state):
"""
@ -6256,7 +6277,10 @@ class GedcomParser(UpdateCallback):
@param state: The current state
@type state: CurrentState
"""
state.source.set_publication_info(line.data)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.PUB_INFO)
sattr.set_value(line.data)
state.source.add_attribute(sattr)
self.__skip_subordinate_levels(state.level+1, state)
def __source_title(self, line, state):
@ -6266,7 +6290,12 @@ class GedcomParser(UpdateCallback):
@param state: The current state
@type state: CurrentState
"""
state.source.set_title(line.data.replace('\n', ' '))
title = line.data.replace('\n', ' ')
state.source.set_name(title)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(title)
state.source.add_attribute(sattr)
def __source_taxt_peri(self, line, state):
"""
@ -6275,8 +6304,17 @@ class GedcomParser(UpdateCallback):
@param state: The current state
@type state: CurrentState
"""
if state.source.get_title() == "":
state.source.set_title(line.data.replace('\n', ' '))
templatehandle = state.source.get_template()
if templatehandle:
template = self.dbase.get_template_from_handle(templatehandle)
title = template.title_gedcom(state.source.get_attribute_list())
if title == "":
title = line.data.replace('\n', ' ')
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(title)
state.source.add_attribute(sattr)
state.source.set_name(title)
#----------------------------------------------------------------------
#
@ -6873,7 +6911,12 @@ class GedcomParser(UpdateCallback):
if self.use_def_src:
filename = os.path.basename(line.data).split('\\')[-1]
# feature request 2356: avoid genitive form
self.def_src.set_title(_("Import from %s") % filename)
title = _("Import from %s") % filename
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.TITLE)
sattr.set_value(title)
src.add_attribute(sattr)
self.def_src.set_name(title)
def __header_copr(self, line, state):
"""
@ -6883,7 +6926,10 @@ class GedcomParser(UpdateCallback):
@type state: CurrentState
"""
if self.use_def_src:
self.def_src.set_publication_info(line.data)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.PUB_INFO)
sattr.set_value(line.data)
self.def_src.add_attribute(sattr)
def __header_subm(self, line, state):
"""
@ -7088,7 +7134,10 @@ class GedcomParser(UpdateCallback):
@type state: CurrentState
"""
if self.use_def_src:
self.def_src.set_author(line.data)
sattr = SrcAttribute()
sattr.set_type(SrcAttributeType.AUTHOR)
sattr.set_value(line.data)
self.def_src.add_attribute(sattr)
def __parse_note(self, line, obj, level, state):
if line.token == TOKEN_RNOTE:
@ -7245,13 +7294,13 @@ class GedcomParser(UpdateCallback):
self.inline_srcs[title] = handle
else:
src = self.__find_or_create_source(self.sid_map[line.data])
# We need to set the title to the cross reference identifier of the
# We need to set the name to the cross reference identifier of the
# SOURce record, just in case we never find the source record. If we
# din't find the source record, then the source object would have
# got deleted by Chack and repair because the record is empty. If we
# got deleted by Check and repair because the record is empty. If we
# find the source record, the title is overwritten in
# __source_title.
src.set_title(line.data)
src.set_name(line.data)
self.dbase.commit_source(src, self.trans)
self.__parse_source_reference(citation, level, src.handle, state)
citation.set_reference_handle(src.handle)

View File

View File

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Registering srctemplates for GRAMPS.
"""
#
# SrcTemplates distributed with Gramps
#
# EE
plg = newplugin()
plg.id = 'evidence explained styles'
plg.name = _("Evidence Explained Source Templates")
plg.description = _("Defines source templates corresponding with those from the"
" book Evidence Explained.")
plg.version = '1.0'
plg.gramps_target_version = '4.1'
plg.status = STABLE
plg.fname = 'evidenceexplained.py'
plg.ptype = SRCTEMPLATE

View File

@ -0,0 +1,263 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Registering srctemplates for GRAMPS.
"""
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
import os
from functools import partial
from gramps.gen.const import DATA_DIR
#
# SrcTemplates distributed with Gramps
#
# Add EE styles to the src templates defined
#the csv file with the template definitions
path_csv = partial(os.path.join, DATA_DIR, "evidencestyle")
csvfile = path_csv('evidence_style.csv')
#name of this style
style = 'EE'
input_type = 'csv'
#strings to translate
#following translations are generated with extract_trans_csv.py
if False:
#these translations will only occur when needed first time!
_("1790-1840")
_("1850-1860: slaves")
_("1850-1870")
_("1880-1930")
_("Abstracts")
_("Administrative material")
_("Appeals court record books")
_("Application file")
_("Archival preservation copy")
_("Archived Material")
_("Archived in-house")
_("Archived off-site")
_("Archives & Artifacts")
_("Artifact")
_("Audio book")
_("Audio recordings")
_("Basic Format")
_("Blogs")
_("Book")
_("Book:")
_("Bound volume")
_("Broadcasts & Web Miscellanea")
_("Business & institutional Records")
_("CD-ROM publication")
_("CD/DVD")
_("CD/DVD book (text)")
_("CD/DVD publication")
_("Case Reporters")
_("Case files")
_("Cemetery Office Records")
_("Cemetery Records")
_("Cemetery abstracts")
_("Census Records")
_("Church Books")
_("Church Records")
_("Church record book, recopied")
_("Church-issued certificate")
_("Church-records database")
_("Citing volume from title page")
_("Codes & statutes, online")
_("Collection, emphasis on")
_("Congressional Records")
_("Corporate Records")
_("Database")
_("Database online")
_("Databases")
_("Derivatives")
_("Descriptive pamphlet, online")
_("Diary or journal, etc.")
_("Digital Archives")
_("Digital Images")
_("Digitized online")
_("Discussion forums & lists")
_("Document (loose record)")
_("Document, emphasis on")
_("Electronic Publications")
_("Extract supplied by staff")
_("FHL-GSU film")
_("FHL-GSU preservation")
_("FHL-GSU preservation copy")
_("FHL-GSU preservation film")
_("Family Bible Records")
_("Family Chart or Group Sheet")
_("File items")
_("Files moved to state archives")
_("France")
_("Genetic testing")
_("Grave markers")
_("Historic letter")
_("Historical research: corporate")
_("Historical research: online")
_("Image Copies")
_("Images online")
_("In-house film")
_("Interview tape & transcript")
_("Journal articles")
_("LDS records at FHL")
_("Land warrants: loose")
_("Land-grant register")
_("Leaflet")
_("Legal Reference Works")
_("Legal document, unrecorded")
_("Legislative petitions & files")
_("Library of Congress")
_("Lineage-society Records")
_("Local")
_("Local & State Records: Courts & Governance")
_("Local & State Records: Licenses, Registrations, Rolls & Vital Records")
_("Local & State Records: Property & Probates")
_("Local Records")
_("Local copy")
_("Magazine articles")
_("Manuscript Records")
_("Manuscripts")
_("Map")
_("Maps")
_("Markers & Memorials (Originals)")
_("Memorial plaques")
_("Microfilm")
_("Microfilm (U.S.)")
_("Microfilm publication")
_("Miscellaneous file")
_("NARA Style citation")
_("NARA film")
_("Named volume")
_("National Archives")
_("National Archives (Australia)")
_("National Archives (Canada)")
_("National Archives (U.K.)")
_("National Archives (U.S.)")
_("National Archives (U.S.) guides")
_("National Archives copy")
_("National Archives microfilm")
_("National Archives-Regional")
_("National Government Records")
_("Native-American tribal census")
_("Newsletter articles")
_("Newspaper articles")
_("Nonpopulation schedules")
_("Numbered volume")
_("Office records")
_("Online")
_("Online archives")
_("Online archives of print journals")
_("Online commercial site")
_("Online database")
_("Online image")
_("Online images")
_("Online journals")
_("Online publication")
_("Online reprints, random items")
_("Online:")
_("Organizational Records")
_("Original Materials (U.S.)")
_("Original Records")
_("Original manuscripts (U.S.)")
_("Patent & Trademark Office (U.S.)")
_("Periodicals")
_("Personal Bible")
_("Personal correspondence")
_("Personal e-mail")
_("Photographs")
_("Podcasts")
_("Population schedules")
_("Portrait")
_("Preliminary inventory, microfilmed")
_("Preservation Film")
_("Preservation film, FHL-GSU")
_("Print Publications")
_("Print editions")
_("Printed Government Documents")
_("Private Holdings")
_("Professional Reports")
_("Publications Style citation")
_("Publications: Books, CDs, Maps, Leaflets & Videos")
_("Publications: Legal Works & Government Documents")
_("Publications: Periodicals, Broadcasts & Web Miscellanea")
_("Radio & television clips")
_("Railroad Retirement Board")
_("Record Books")
_("Record Books, archived off-site")
_("Registers")
_("Research Report")
_("School Records")
_("Series named for editor")
_("Series, emphasis on")
_("Slip laws:")
_("Social Security Administration")
_("Soundex & Miracode, microfilm")
_("Standardized series")
_("State database")
_("State level")
_("State-level")
_("State-level Records")
_("State-level copies")
_("State-sponsored censuses")
_("Statistical database")
_("Statutes:")
_("Student transcript")
_("Tract book")
_("Tradition, recorded")
_("Traditional academic style")
_("U.K. Wales")
_("U.S. Code")
_("UNC microfilm publication")
_("Unpublished narrative")
_("Vertical file")
_("Video")
_("Vital records, amended")
_("Vital records, delayed")
_("Vital-records certificate")
_("Vital-records register")
_("Website as book")
_("archived off-site")
_("basic format")
_("card file")
_("chapter")
_("edited")
_("federal")
_("federal census")
_("held by church")
_("multivolume set")
_("online")
_("personally used")
_("reprint")
_("revised edition")
_("rural")
_("state")
_("supplied by staff")
_("urban")
_("vertical file")

View File

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Registering srctemplates for GRAMPS.
"""
#
# SrcTemplates distributed with Gramps
#
# GEDCOM
plg = newplugin()
plg.id = 'GEDCOM styles'
plg.name = _("GEDCOM Source Templates")
plg.description = _("Defines source templates corresponding with GEDCOM.")
plg.version = '1.0'
plg.gramps_target_version = '4.1'
plg.status = STABLE
plg.fname = 'gedcomtemplate.py'
plg.ptype = SRCTEMPLATE

View File

@ -0,0 +1,194 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Registering GEDCOM srctemplates for GRAMPS.
N.B. This is used both from creating a new database (when the database is in its
normal state), and
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from __future__ import print_function
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from gramps.gen.db import DbTxn
from gramps.gen.utils.id import create_id
from gramps.gen.lib.srctemplate import SrcTemplate
from gramps.gen.lib.templateelement import TemplateElement
from gramps.gen.utils.citeref import (REF_TYPE_L, REF_TYPE_S, REF_TYPE_F,
GED_TITLE, GED_AUTHOR, GED_PUBINF,
GED_DATE, GED_PAGE)
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
LOG = logging.getLogger('.template')
#
# GEDCOM SrcTemplates distributed with Gramps
#
#name of this style
style = 'GEDCOM'
input_type = 'code'
def load_template(db):
# Don't load the GEDCOM template twice
if db.get_GEDCOM_template_handle() is None:
template = build_GEDCOM_template()
msg = _("Add template (%s)") % template.get_name()
with DbTxn(msg, db) as trans:
db.commit_template(template, trans)
db.set_GEDCOM_template_handle(template.get_handle())
def build_GEDCOM_template():
"""
Builds the GEDCOM template. This does not commit the template to the
database. For Upgrade commit is done in the upgrade code. For new databases,
commit is done by load_template function.
"""
EMPTY = 0
DESCR = -10
# template to GEDCOM field mapping for L reference fields
# template to a style mapping
STYLE_QUOTE = 1 # add quotes around the field
DEFAULTS = {
"Author" : ("Doe, D.P. & Cameron, E." , "Give names in following form:'FirstAuthorSurname, Given Names & SecondAuthorSurname, Given Names'. Like this Gramps can parse the name and shorten as needed."),
"Date" : ("17 Sep 1745" , "The date that this event data was entered into the original source document. ."),
"Page" : ("5; or 4,6-8, ..." , "Specific location with in the information referenced. For a published work, this could include the volume of a multi-volume work and the page number(s). For a periodical, it could include volume, issue, and page numbers. For a newspaper, it could include a column number and page number. For an unpublished source, this could be a sheet number, page number, frame number, etc. A census record might have a line number or dwelling and family numbers in addition to the page number. "),
"Pub_info" : ("Springer, Berlin, 2014" , "When and where the record was created. For published works, this includes information such as the city of publication, name of the publisher, and year of publication."),
"Title" : ("Diary Title, Message Title, Bible Name, Article Title, ..." , "The title of the work, record, or item and, when appropriate, the title of the larger work or series of which it is a part."),
}
TEMPLATES = {
'GEDCOM': {
REF_TYPE_L: [
('', "Author", '', '.', EMPTY, False, False, EMPTY, GED_AUTHOR,
None, None),
('', "Title", '', '.', STYLE_QUOTE, False, False, EMPTY, GED_TITLE,
None, None),
('', "Pub_info", '', '', EMPTY, False, False, EMPTY, GED_PUBINF,
None, None),
],
REF_TYPE_F: [
('', "Author", '', ',', EMPTY, False, False, EMPTY, EMPTY,
None, None),
('', "Title", '', ',', STYLE_QUOTE, False, False, EMPTY, EMPTY,
None, None),
('', "Pub_info", '', '.', EMPTY, False, False, EMPTY, EMPTY,
None, None),
('', "Date", '', ' -', EMPTY, False, False, EMPTY, EMPTY,
None, None),
('', "Page", 'Page(s)', '.', EMPTY, False, False, EMPTY, EMPTY,
None, None),
],
REF_TYPE_S: [
('', "Author", '', ',', EMPTY, False, False, EMPTY, EMPTY,
None, None),
('', "Date", '', ' -', EMPTY, False, False, EMPTY, EMPTY,
None, None),
('', "Page", 'Page(s)', '.', EMPTY, False, False, EMPTY, EMPTY,
None, None),
],
DESCR: '%(first)s - %(sec)s - %(third)s' % { 'first': _('Basic'), 'sec': _('GEDCOM Style'), 'third': _('')},
},
}
template = SrcTemplate()
template.set_name('GEDCOM')
template.set_descr('%(first)s - %(sec)s - %(third)s' % { 'first': _('Basic'), 'sec': _('GEDCOM Style'), 'third': _('')})
handle = create_id()
template.set_handle(handle)
for (cite_type, slist) in list(TEMPLATES['GEDCOM'].items()):
if cite_type != DESCR:
for struct in slist:
if cite_type == REF_TYPE_L or cite_type == REF_TYPE_F:
elem = [x for x in template.get_template_element_list()
if x.get_name()==struct[1] and x.get_short()==False]
if elem:
te = elem[0]
else:
te = TemplateElement()
template.add_template_element(te)
elif cite_type == REF_TYPE_S:
te = TemplateElement()
template.add_template_element(te)
ldel = struct[0]
field_type = struct[1]
field_label = struct[2]
rdel = struct[3]
style = struct[4]
private = struct[5]
optional = struct[6]
shorteralg = struct[7]
gedcommap = struct[8]
hint = struct[9]
tooltip = struct[10]
te.set_name(field_type)
te.set_display(field_label)
if DEFAULTS.get(field_type):
te.set_hint(hint or (DEFAULTS[field_type][0] or ""))
te.set_tooltip(tooltip or (DEFAULTS[field_type][1] or ""))
else:
te.set_hint("")
te.set_tooltip("")
if cite_type == REF_TYPE_S:
te.set_short(True)
if field_type.lower().endswith(' (short)'):
te.set_name(field_type)
else:
te.set_name(field_type + ' (Short)')
if field_type == "Page" or \
field_type == "Date":
te.set_citation(True)
template.set_map_element(GED_AUTHOR, "%(AUTHOR)s")
template.set_map_element(GED_TITLE, "%(TITLE)s")
template.set_map_element(GED_PUBINF, "%(PUB_INFO)s")
template.set_map_element(GED_DATE, "%(DATE)s")
template.set_map_element(GED_PAGE, "%(PAGE)s")
template.set_map_element(REF_TYPE_L, "%(AUTHOR)s. %(TITLE)s. %(PUB_INFO)s")
template.set_map_element(REF_TYPE_F, "%(AUTHOR)s, %(TITLE)s, %(PUB_INFO)s. %(DATE)s - %(PAGE)s")
template.set_map_element(REF_TYPE_S, "%(AUTHOR_(SHORT))s, %(DATE_(SHORT))s - %(PAGE_(SHORT))s.")
return template

View File

@ -0,0 +1,503 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
# Copyright (C) 2013 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Import SrcTemplates for GRAMPS.
"""
from __future__ import print_function
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
import csv
import collections
import sys
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gramps.gen.db import DbTxn
from gramps.gen.utils.id import create_id
from gramps.gen.lib.srcattrtype import *
from gramps.gen.lib.date import Date
from gramps.gen.lib.srctemplate import SrcTemplate
from gramps.gen.lib.templateelement import TemplateElement
from gramps.gen.utils.citeref import (REF_TYPE_L, REF_TYPE_S, REF_TYPE_F,
GED_TITLE, GED_AUTHOR, GED_PUBINF,
GED_DATE, GED_PAGE)
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
LOG = logging.getLogger('.template')
#columns in a csv file defining templates
NRCOL = 0
CATCOL = 1
CATTYPECOL = 2
TYPECOL = 3
DESCRCOL= 4
CITETYPECOL = 5
IDENTCOL = 6
LDELCOL = 7 # left delimiter
FIELDCOL = 8
LABELCOL = 9
RDELCOL = 10 # right delimiter
GEDCOMCOL = 11
SHORTERCOL = 12
STYLECOL = 13
PRIVACYCOL = 14
OPTCOL = 15
HINTCOL = 16
TOOLTIPCOL = 17
UNKNOWN = 'UNKNOWN'
DESCR = -10
# This contains the default hints and tooltips
DEFAULTS = {
"Act" : ("Public Law 12-98" , "A statute or law name passed by a legislature"),
"Address" : ("Broadway Avenue, New York" , "Store address information. Set Private if needed! Give information from lowest to highest level separated by comma's"),
"Affiliation" : ("Agent of Gramps Software" , "A relevant affiliation that might influence data in the source"),
"Author" : ("Doe, D.P. & Cameron, E." , "Give names in following form:'FirstAuthorSurname, Given Names & SecondAuthorSurname, Given Names'. Like this Gramps can parse the name and shorten as needed."),
"Author location" : ("Chicago" , "City where author resides or wrote."),
"Book" : ("The big example Gramps manual" , "Title of the Book"),
"Case" : ("B. Malengier versus N. Hall" , "Dispute between opposing parties in a court of law."),
"Cemetery" : ("Greenwich Cemetery Office" , "Name of cemetery or cemetery office with sources."),
"Chapter" : ("The first office of T. Rooseveld" , None),
"Chapter pages" : ("24-55" , "The pages in the chapter."),
"Collection" : ("Bruges Lace Collection" , "The name of the person who compiled the source."),
"Column" : ("col. 3" , "The name of the creator of the artifact."),
"Compiler" : ("T. Da Silva" , None),
"Creation date" : ("13 Aug 1965" , None),
"Creator" : ("P. Picasso" , None),
"Credit line" : ("Based on unnamed document lost in fire" , "Acknowledgement of writers and contributors"),
"Date" : ("17 Sep 1745" , "The range of years which are present in the source."),
"Date accessed" : ("18 Jun 2013" , "Some important detail of the source."),
"Date range" : ("2003-6" , None),
"Description" : ("The lace has inscriptions with names of nobility" , None),
"District" : ("Enumeration district (ED) 14" , "District as handled by Census"),
"Division" : ("Peterburg Post Office, or Portland, ward 4" , "The subdivision of a larger group that is handled in the source."),
"Edition" : ("Second Edition" , None),
"Editor" : ("Hoover, J.E." , "The Editor of a multi-author book."),
"File" : ("Membership application J. Rapinat" , "The title of a specific file in a source."),
"File date" : ("15 Jan 1870" , "Date of submitting the document to a clerk or court."),
"File location" : ("Accession 7, Box 3" , "Accession method to the file"),
"File no." : ("1243-EB-98" , "Number to indicate a file"),
"File unit" : ("Letters to George Washington" , "A grouping unit for a number of files in a source."),
"Film id" : ("T345" , "ID of a Microfilm."),
"Film publication place" : ("Kansas City" , None),
"Film publisher" : ("NY Genealogy Association" , None),
"Film type" : ("FHL microfilm" , "The type of the microfilm."),
"Format" : ("Digital Images, or Database, or Cards, ..." , "The format of the source."),
"Frame" : ("frames 387-432" , "What frames in the source are relevant."),
"Group" : ("Miami Patent Office" , "A larger grouping to which the source belongs."),
"Household" : ("dwelling 345, family 654" , "Household of interest on a census."),
"Id" : ("I50-68, or 1910 U.S. census, or ..." , "ID to identify the source or citation part"),
"Institution" : ("Sorbonne University" , "Institution that issued the source."),
"Interviewer" : ("Materley, B." , None),
"Issue date" : ("Jun 2004" , "Date the source was issued."),
"Issue range" : ("145-394, scattered issues" , "A range of magazine, journal, ... issues covered in the source"),
"Item of interest" : ("entry for G. Galileo, or Doe Household, or A. Einstein Grave ..." , "Specific part, item, or person of interest in the source"),
"Jurisdiction" : ("Jackson County, Alabama" , "Area with a set of laws under the control of a system of courts or government entity. Enter this from lowest to highest relevant jurisdiction, separated by comma's."),
"Location" : ("Istanbul" , "City that is relevant."),
"Number" : ("2, or Record Group 34, or ..." , "A number."),
"Number (total)" : ("5" , "The maximum of entities available."),
"Original repository" : ("National Archives" , "Name of the repository where the original is stored."),
"Original repository location" : ("Washington, D.C." , "Address or only city of the repository where the original is stored."),
"Original year" : ("1966" , "Year the original source was published/created"),
"Page" : ("5; or 4,6-8, ..." , "The page or page(s) relevant for the citation"),
"Page range" : ("1-13" , "The range of the pages in the source. The page given for a citation must be in this range."),
"Part" : ("Part 3" , None),
"Place created" : ("London" , None),
"Position" : ("written in the left margin, or second row, 3th line" , "Where in or on the source the citation piece can be found."),
"Posting date" : ("5 Jul 1799" , None),
"Professional credentials" : ("Prof.; or Dr. ..." , None),
"Provenance" : ("add provenance of the material" , "Where the material originated from."),
"Publication format" : ("CD-ROM or eprint or ..." , None),
"Publication place" : ("Berlin" , None),
"Publication title" : ("Title of Blog, Newsletter, DVD, ..." , None),
"Publication year" : ("2014" , None),
"Publisher" : ("Springer" , None),
"Pub_info" : ("Springer, Berlin, 2014" , "Publication Information, such as city and year of publication, name of publisher, ..."),
"Recipient" : ("J. Ralls" , "The person to who the letter is addressed."),
"Relationship" : ("Paul's uncle and brother of Erik" , "The relationship of the author to the person of interest that is the subject."),
"Report date" : ("3 May 1999" , "Date the report was written/submitted."),
"Research comment" : ("Descriptive detail or provenance or research analysis conclusion, ..." , "Descriptive detail or provenance or research analysis conclusion, ..."),
"Research project" : ("Tahiti Natives" , "The genealogical or scientific research project."),
"Roll" : ("176, or rolls 145-160" , "The Microfilm role."),
"Schedule" : ("population schedule or slave schedule or ..." , "The census schedule (the type of census table) used, eg population schedule or slave schedule. or ..."),
"Section" : ("1890 section or ER patients or ..." , "The section or subgroup under which filed, eg 'Diplomatic correspondance, 1798-1810'"),
"Series" : ("Carnival County Records" , None),
"Series no." : ("series 34-38" , None),
"Session" : ("2nd session" , "The number of the meeting or series of connected meetings devoted by a legislature to a single order of business, program, agenda, or announced purpose."),
"Sheet no." : ("sheet 13-C" , "Number of a census sheet."),
"Subject" : ("D. Copernicus and close family" , None),
"Subseries" : (None , None),
"Subtitle" : ("Subtitle of article or magazine ..." , None),
"Term" : ("June Term 1934 or 13th Congress or Reagan Office or ..." , "Reference to the time a person/group/parliament is in office or session."),
"Timestamp" : ("min. 34-36" , "Indication of the time in audio or video where the relevant fragment can be found."),
"Title" : ("Diary Title, Message Title, Bible Name, Article Title, ..." , None),
"Translation" : ("A translated version, typically of the title" , "A translated version, typically of the title"),
"Type" : ("Letter" , None),
"Url (digital location)" : ("http//gramps-project.org/blog" , "Detailed internet address of the content"),
"Volume" : ("4" , None),
"Volume info" : ("5 volumes" , "Information about the volumes, eg the amount of volumes."),
"Website" : ("gramps-project.org" , "The main internet address."),
"Website creator/owner" : ("Family Historians Inc" , "Organization or person behind a website."),
"Year" : ("1888" , None),
"Year accessed" : ("2013" , None),
}
def load_srctemplates_data(db):
"""
Loads the srctemplates defined, and returns a dict with template data
"""
LOG.debug("**** load_srctemplate_data. Starting")
from gramps.gen.plug import BasePluginManager
bpmgr = BasePluginManager.get_instance()
pdatas = bpmgr.get_reg_srctemplates()
for plugin in pdatas:
mod = bpmgr.load_plugin(plugin)
if mod:
if mod.input_type == 'csv':
csvfilename = mod.csvfile
LOG.debug("**** load_srctemplate_data. Loading csv from %s" % csvfilename)
if sys.version_info[0] <3:
with open(csvfilename, 'rb') as csvfile:
load_srctemplate_csv(csvfile, db)
else:
with open(csvfilename, 'r') as csvfile:
load_srctemplate_csv(csvfile, db)
LOG.debug("**** load_srctemplate_data. csv data loaded")
elif mod.input_type == 'code':
mod.load_template(db)
LOG.debug("**** load_srctemplate_data. GEDCOM loaded")
for handle in db.get_template_handles():
LOG.debug("handle %s" % handle)
template = db.get_template_from_handle(handle)
LOG.debug("source_type: %s; handle %s" % (template.get_name(), template.get_handle()))
for te in template.get_template_element_list():
LOG.debug(" name: %s; display: %s; hint: %s; tooltip: %s; citation %s; "
"short %s; short_alg %s" %
(te.get_name(),
te.get_display(), te.get_hint(),
te.get_tooltip(), te.get_citation(),
te.get_short(), te.get_short_alg()
))
for target in template.get_map_dict():
LOG.debug("Type %s; target %s; map %s" %
(template.get_name(), target, template.get_map_element(target)))
LOG.debug("**** load_srctemplate_data. finished")
def load_srctemplate_csv(csvfile, db):
"""
Loads a template csvfile, and returns a dict with template data
Note: csvfile could be a list containing strings!
"""
first = True
TYPE2CITEMAP = {}
TYPE2TEMPLATEMAP = {}
TYPE2FIELDS = collections.defaultdict(lambda: collections.defaultdict(list))
CITE_TYPES = {'F': REF_TYPE_F, 'L': REF_TYPE_L, 'S': REF_TYPE_S}
GEDCOMFIELDS = {'A': GED_AUTHOR, 'T': GED_TITLE,
'P': GED_PUBINF, 'D': GED_DATE}
EMPTY = 0
# template to a shortening algorithm mapping for predefined algorithms
SHORTERALG_LOC = 1 # reduce a location to a shorter format (typically city level)
SHORTERALG_YEAR = 2 # reduce a date to only the year part
SHORTERALG_ETAL = 3 # reduce an author list to "first author et al."
SHORTERALG_REVERT_TO_DOT = 4 # change a list of first, second, third to
# a list third. second. first.
# template to a style mapping
STYLE_QUOTE = 1 # add quotes around the field
STYLE_QUOTECONT = 2 # add quotes around this field combined with other
# QUOTECONT fields around it
STYLE_EMPH = 3 # emphasize field
STYLE_BOLD = 4 # make field bold
SHORTERALG = {'LOC': SHORTERALG_LOC, 'YEAR': SHORTERALG_YEAR,
'ETAL': SHORTERALG_ETAL, 'REV.': SHORTERALG_REVERT_TO_DOT}
STYLES = {'Quoted': STYLE_QUOTE, 'Italics': STYLE_EMPH,
'QuotedCont': STYLE_QUOTECONT, 'Bold': STYLE_BOLD}
reader = csv.reader(csvfile, delimiter=';')
prevtempl = ''
newtempl = True
for row in reader:
if first:
#skip first row with headers
first=False
continue
if row[CATCOL]:
cat = row[CATCOL].strip()
cattype = row[CATTYPECOL].strip()
types = row[TYPECOL].strip()
descr = row[DESCRCOL].strip()
source_type = row[IDENTCOL].strip()
if prevtempl != source_type:
newtempl = True
prevtempl = source_type
else:
newtempl = False
if descr:
source_descr = '%s - %s - %s (%s)' % (_(cat), _(cattype),
_(types), _(descr))
else:
source_descr = '%s - %s - %s' % (_(cat), _(cattype), _(types))
if source_type in TYPE2TEMPLATEMAP:
if not TYPE2TEMPLATEMAP[source_type].get_descr() == source_descr:
raise NotImplementedError(source_type + ' ' + TYPE2TEMPLATEMAP[source_type].get_descr() + ' NOT equal to known description' + source_descr)
if newtempl:
#the template is new in this csv, but already defined, probably user error
raise NotImplementedError('Source template ' + prevtempl + ' is twice defined in the csv.')
else:
template = SrcTemplate()
template.set_name(source_type)
template.set_descr(source_descr)
handle = create_id()
template.set_handle(handle)
TYPE2TEMPLATEMAP[source_type] = template
# TYPE2CITEMAP[source_type] = {REF_TYPE_L: [], REF_TYPE_F: [],
# REF_TYPE_S: [], DESCR: source_descr}
if row[CITETYPECOL]:
#new citation type,
cite_type_text = row[CITETYPECOL].strip()
assert cite_type_text in ['F', 'L', 'S'], str(cite_type_text)
if cite_type_text == 'S':
shortcite = True
else:
shortcite = False
cite_type = CITE_TYPES[cite_type_text]
#add field for template to evidence style
field = row[FIELDCOL].strip()
field_type = field.replace('[', '').replace(']','').lower().capitalize()
#field_type = field.replace(' ', '_').replace("'","")\
# .replace('&','AND').replace('(', '6').replace(')','9')\
# .replace('[', '').replace(']','').replace('/', '_OR_')\
# .replace(',', '').replace('.', '').replace(':', '')\
# .replace('-', '_')
# #we need to force English SrcAttributeType
# ifield_type = SrcAttributeType()
# ifield_type.set_from_xml_str(field_type)
# ifield_type = int(SrcAttributeType(ifield_type))
# if ifield_type == SrcAttributeType.CUSTOM:
# raise NotImplementedError("field must be a known SrcAttributeType, is " + str(SrcAttributeType(field_type)))
# field_type = ifield_type
#field_descr = field.replace('[', '').replace(']','').lower().capitalize()
field_label = row[LABELCOL].strip()
#field_label = field_label.replace("'", "\\'")
private = False
if row[PRIVACYCOL].strip():
private = True
optional = False
if row[OPTCOL].strip():
optional = True
shorteralg = SHORTERALG.get(row[SHORTERCOL].strip()) or EMPTY
gedcom_type_text = row[GEDCOMCOL].strip()
gedcommap = GEDCOMFIELDS.get(row[GEDCOMCOL].strip())
style = STYLES.get(row[STYLECOL].strip()) or EMPTY
if source_type in TYPE2TEMPLATEMAP:
template = TYPE2TEMPLATEMAP[source_type]
else:
template = SrcTemplate()
handle = create_id()
template.set_handle(handle)
TYPE2TEMPLATEMAP[source_type] = template
tlist.add_template(handle, template)
if cite_type == REF_TYPE_L or REF_TYPE_F:
elem = [x for x in template.get_template_element_list()
if x.get_name()==field_type and x.get_short()==False]
if elem:
te = elem[0]
else:
te = TemplateElement()
template.add_template_element(te)
hint = row[HINTCOL]
tooltip = row[TOOLTIPCOL]
te.set_name(field_type)
te.set_display(field_label)
te.set_hint(hint or te.get_hint())
te.set_tooltip(tooltip or te.get_tooltip())
te.set_short_alg(shorteralg)
if cite_type == REF_TYPE_S:
te = TemplateElement()
te.set_name(field_type)
te.set_short_alg(shorteralg)
te.set_short(True)
lblval = field_label
if lblval:
te.set_display(_('%(normal_version_label)s (Short)') % {
'normal_version_label': lblval})
template.add_template_element(te)
TYPE2FIELDS[source_type][cite_type].append(field_type)
# Setup the mapping. A typical mapping would look like:
# ('EE_Full' : '%(COMPILER)s, "%(TITLE)s", %(TYPE)s, %(WEBSITE CREATOR/OWNER)s, <i>%(WEBSITE)s</i>, (%(URL (DIGITAL LOCATION))s: accessed %(DATE ACCESSED)s), %(ITEM OF INTEREST)s; %(CREDIT LINE)s.')
if te.get_short():
if field_type.lower().endswith(' (short)'):
txt = field_type
else:
txt = field_type + ' (Short)'
else:
txt = field_type
txt = row[LDELCOL] + "%(" + \
txt.upper().replace(' ', '_') + \
")s" + row[RDELCOL]
if len(row[RDELCOL]) and row[RDELCOL][-1] in ['.', ',', ':', ';', '-']:
txt += ' '
if style == STYLE_QUOTE:
txt = '"' + txt + '"'
elif style == STYLE_QUOTECONT:
if template.get_map_element(cite_type)[-1] == '"':
template.set_map_element(cite_type, template.get_map_element(cite_type)[:-1])
txt = txt + '"'
else:
txt = '"' + txt + '"'
elif style == STYLE_EMPH:
txt = "<i>" + txt + "</i>"
elif style == STYLE_BOLD:
txt = "<b>" + txt + "</b>"
template.set_map_element(cite_type, template.get_map_element(cite_type) + txt)
# Setup the GEDCOM fields. These are only stored in the L template
if cite_type == REF_TYPE_L and gedcom_type_text:
if style == STYLE_QUOTECONT:
if template.get_map_element(gedcommap) and template.get_map_element(gedcommap)[-1] == '"':
template.set_map_element(gedcommap, template.get_map_element(gedcommap)[:-1])
template.set_map_element(gedcommap, template.get_map_element(gedcommap) + txt)
msg = _("Add template (%s)") % template.get_name()
with DbTxn(msg, db) as trans:
db.commit_template(template, trans)
# Now we adjust some fields that could not be changed till all the data had
# been read in
for source_type in TYPE2FIELDS:
template = TYPE2TEMPLATEMAP[source_type]
# First we determine which are citation fields
cite_fields = [field for field in
TYPE2FIELDS[source_type][REF_TYPE_F] +
TYPE2FIELDS[source_type][REF_TYPE_S]
if field not in TYPE2FIELDS[source_type][REF_TYPE_L]]
for te in template.get_template_element_list():
# Set the boolean if this is a citation field
if te.get_name() in cite_fields:
te.set_citation(True)
# Set the hint and tooltip to default if not already set
if DEFAULTS.get(te.get_name()):
te.set_hint(hint or (DEFAULTS[te.get_name()][0] or ""))
te.set_tooltip(tooltip or (DEFAULTS[te.get_name()][1] or ""))
else:
te.set_hint("")
te.set_tooltip("")
# If this is a short version, set the name accordingly. This could
# not be done earlier because we needed to keep the old 'non-short'
# name to find which fields belonged to citations as opposed to
# sources
if te.get_short() == True:
if te.get_name().lower().endswith(' (short)'):
te.set_name(te.get_name())
else:
te.set_name(te.get_name() + ' (Short)')
msg = _("Add template (%s)") % template.get_name()
with DbTxn(msg, db) as trans:
db.commit_template(template, trans)
# Finally we setup the GEDCOM page fields
for source_type in TYPE2FIELDS:
template = TYPE2TEMPLATEMAP[source_type]
for te in [x for x in template.get_template_element_list()
if x.get_citation() and not x.get_short()]:
template.set_map_element(GED_PAGE,
", ".join((template.get_map_element(GED_PAGE), txt)))
msg = _("Add template (%s)") % template.get_name()
with DbTxn(msg, db) as trans:
db.commit_template(template, trans)
# Proof of concept for CSL mapping
template = TYPE2TEMPLATEMAP.get('ESM254')
if template:
amap = {
'type' : 'chapter',
'author' : '%(COMPILER)s',
'title' : '%(TITLE)s',
'edition' : '%(TYPE)s',
'container_author' : '%(WEBSITE_CREATOR/OWNER)s',
'container_title' : '%(WEBSITE)s',
'url' : '%(URL_(DIGITAL_LOCATION))s',
'locator' : '%(ITEM_OF_INTEREST)s; %(CREDIT_LINE)s',
'accessed' : '%(DATE_ACCESSED)s',
'page' : '1-7'
}
for key, val in list(amap.items()):
template.set_map_element(key, val)
msg = _("Add template (%s)") % template.get_name()
with DbTxn(msg, db) as trans:
db.commit_template(template, trans)
# for source_type in TYPE2FIELDS:
# LOG.debug("source_type: %s; handle %s" % (template.get_name(), template.get_handle()))
# template = TYPE2TEMPLATEMAP[source_type]
# for te in template.get_template_element_list():
# LOG.debug(" name: %s; display: %s; hint: %s; tooltip: %s; "
# "citation %s; short %s; short_alg %s" %
# (te.get_name(),
# te.get_display(), te.get_hint(),
# te.get_tooltip(), te.get_citation(),
# te.get_short(), te.get_short_alg()
# ))
# for target in template.get_map_dict():
# LOG.debug("Type %s; target %s; map %s" %
# (source_type, target, template.get_map_element(target)))
# LOG.debug(tlist.get_template_list())
# for handle in tlist.get_template_list():
# LOG.debug(tlist.get_template_from_handle(handle).to_struct())

View File

@ -75,7 +75,7 @@ IGNORE_CONFIDENCE = 2
IGNORE_BOTH = 3
_val2label = {
ALL_FIELDS : _("Match on Page/Volume, Date and Confidence"),
ALL_FIELDS : _("Match on Citation Name, Date and Confidence"),
IGNORE_DATE : _("Ignore Date"),
IGNORE_CONFIDENCE : _("Ignore Confidence"),
IGNORE_BOTH : _("Ignore Date and Confidence")
@ -198,7 +198,7 @@ class MergeCitations(tool.BatchTool,ManagedWindow):
"that has a citation reference." % class_name)
citation = db.get_citation_from_handle(citation_handle)
key = citation.get_page()
key = citation.get_name()
if fields != IGNORE_DATE and fields != IGNORE_BOTH:
key += "\n" + get_date(citation)
if fields != IGNORE_CONFIDENCE and fields != IGNORE_BOTH:
@ -297,10 +297,10 @@ class MergeCitationsOptions(tool.ToolOptions):
}
self.options_help = {
'dont_merge_notes' :
("=0/1","Whether to merge citations if they have notes",
("=0/1", "Whether to merge citations if they have notes",
["Merge citations with notes",
"Do not merge citations with notes"],
False),
'fields' : ("=num","Threshold for matching",
"Integer number")
'fields' : ("=num", "Threshold for matching",
"Integer number")
}

View File

@ -354,11 +354,11 @@ class TestcaseGenerator(tool.BatchTool):
handle = o.get_handle()
o = Source()
o.set_title("dup 2" + self.rand_text(self.SHORT))
if randint(0,1) == 1:
o.set_author( self.rand_text(self.SHORT))
if randint(0,1) == 1:
o.set_publication_info( self.rand_text(self.LONG))
o.set_name("dup 2" + self.rand_text(self.SHORT))
## if randint(0,1) == 1:
## o.set_author( self.rand_text(self.SHORT))
## if randint(0,1) == 1:
## o.set_publication_info( self.rand_text(self.LONG))
if randint(0,1) == 1:
o.set_abbreviation( self.rand_text(self.SHORT))
while randint(0,1) == 1:
@ -402,7 +402,7 @@ class TestcaseGenerator(tool.BatchTool):
self.db.add_object(m, self.trans)
s = Source()
s.set_title('media should be removed from this source')
s.set_name('media should be removed from this source')
r = MediaRef()
r.set_reference_handle(m.handle)
s.add_media_reference(r)
@ -411,7 +411,7 @@ class TestcaseGenerator(tool.BatchTool):
c = Citation()
self.fill_object(c)
c.set_reference_handle(s.handle)
c.set_page('media should be removed from this citation')
c.set_name('media should be removed from this citation')
r = MediaRef()
r.set_reference_handle(m.handle)
c.add_media_reference(r)
@ -843,25 +843,25 @@ class TestcaseGenerator(tool.BatchTool):
c = Citation()
self.fill_object(c)
c.set_reference_handle("unknownsourcehandle")
c.set_page('unreferenced citation with invalid source ref')
c.set_name('unreferenced citation with invalid source ref')
self.db.add_citation(c, self.trans)
c = Citation()
self.fill_object(c)
c.set_reference_handle(None)
c.set_page('unreferenced citation with invalid source ref')
c.set_name('unreferenced citation with invalid source ref')
self.db.add_citation(c, self.trans)
c = Citation()
self.fill_object(c)
c.set_reference_handle("unknownsourcehandle")
c.set_page('citation and references to it should be removed')
c.set_name('citation and references to it should be removed')
c_h1 = self.db.add_citation(c, self.trans)
c = Citation()
self.fill_object(c)
c.set_reference_handle(None)
c.set_page('citation and references to it should be removed')
c.set_name('citation and references to it should be removed')
c_h2 = self.db.add_citation(c, self.trans)
self.create_all_possible_citations([c_h1, c_h2], "Broken21",
@ -1693,11 +1693,11 @@ class TestcaseGenerator(tool.BatchTool):
o.set_name( self.rand_text(self.SHORT))
if isinstance(o,Source):
o.set_title( self.rand_text(self.SHORT))
if randint(0,1) == 1:
o.set_author( self.rand_text(self.SHORT))
if randint(0,1) == 1:
o.set_publication_info( self.rand_text(self.LONG))
o.set_name( self.rand_text(self.SHORT))
## if randint(0,1) == 1:
## o.set_author( self.rand_text(self.SHORT))
## if randint(0,1) == 1:
## o.set_publication_info( self.rand_text(self.LONG))
if randint(0,1) == 1:
o.set_abbreviation( self.rand_text(self.SHORT))
while randint(0,1) == 1:
@ -1728,7 +1728,7 @@ class TestcaseGenerator(tool.BatchTool):
self.generated_sources.append( s.get_handle())
o.set_reference_handle( choice( self.generated_sources))
if randint(0,1) == 1:
o.set_page( self.rand_text(self.NUMERIC))
o.set_name( self.rand_text(self.NUMERIC))
#if randint(0,1) == 1:
# o.set_text( self.rand_text(self.SHORT))
#if randint(0,1) == 1:

View File

@ -54,7 +54,7 @@ from gramps.gui.views.bookmarks import CitationBookmarks
from gramps.gen.errors import WindowActiveError
from gramps.gui.ddtargets import DdTargets
from gramps.gui.dialog import ErrorDialog
from gramps.gui.editors import EditCitation, DeleteCitationQuery
from gramps.gui.editors import EditSource, DeleteCitationQuery
from gramps.gui.filters.sidebar import CitationSidebarFilter
from gramps.gui.merge import MergeCitation
@ -81,7 +81,7 @@ class CitationListView(ListView):
"""
# The data items here have to correspond, in order, to the items in
# src/giu/views/treemodels/citationlismodel.py
COL_TITLE_PAGE = 0
COL_TITLE_NAME = 0
COL_ID = 1
COL_DATE = 2
COL_CONFIDENCE = 3
@ -90,14 +90,12 @@ class CitationListView(ListView):
COL_CHAN = 6
COL_SRC_TITLE = 7
COL_SRC_ID = 8
COL_SRC_AUTH = 9
COL_SRC_ABBR = 10
COL_SRC_PINFO = 11
COL_SRC_PRIV = 12
COL_SRC_CHAN = 13
COL_SRC_ABBR = 9
COL_SRC_PRIV = 10
COL_SRC_CHAN = 11
# column definitions
COLUMNS = [
(_('Volume/Page'), TEXT, None),
(_('Name'), TEXT, None),
(_('ID'), TEXT, None),
(_('Date'), MARKUP, None),
(_('Confidence'), TEXT, None),
@ -106,22 +104,22 @@ class CitationListView(ListView):
(_('Last Changed'), TEXT, None),
(_('Source: Title'), TEXT, None),
(_('Source: ID'), TEXT, None),
(_('Source: Author'), TEXT, None),
#(_('Source: Author'), TEXT, None),
(_('Source: Abbreviation'), TEXT, None),
(_('Source: Publication Information'), TEXT, None),
#(_('Source: Publication Information'), TEXT, None),
(_('Source: Private'), ICON, 'gramps-lock'),
(_('Source: Last Changed'), TEXT, None),
]
# default setting with visible columns, order of the col, and their size
CONFIGSETTINGS = (
('columns.visible', [COL_TITLE_PAGE, COL_ID, COL_DATE,
('columns.visible', [COL_TITLE_NAME, COL_ID, COL_DATE,
COL_CONFIDENCE]),
('columns.rank', [COL_TITLE_PAGE, COL_ID, COL_DATE, COL_CONFIDENCE,
('columns.rank', [COL_TITLE_NAME, COL_ID, COL_DATE, COL_CONFIDENCE,
COL_PRIV, COL_TAGS, COL_CHAN, COL_SRC_TITLE,
COL_SRC_ID, COL_SRC_AUTH, COL_SRC_ABBR, COL_SRC_PINFO,
COL_SRC_ID, COL_SRC_ABBR,
COL_SRC_PRIV, COL_SRC_CHAN]),
('columns.size', [200, 75, 100, 100, 40, 100, 100, 200, 75, 75, 100,
150, 40, 100])
('columns.size', [200, 75, 100, 100, 40, 100, 100, 200, 75, 100,
40, 100])
)
ADD_MSG = _("Add a new citation and a new source")
ADD_SOURCE_MSG = _("Add a new source")
@ -255,7 +253,7 @@ class CitationListView(ListView):
citation to an existing source)
Create a new Source instance and Citation instance and call the
EditCitation editor with the new source and new citation.
EditSource editor with the new source and new citation.
Called when the Add button is clicked.
If the window already exists (WindowActiveError), we ignore it.
@ -266,8 +264,7 @@ class CitationListView(ListView):
window to already exist, so this is just an extra safety measure.
"""
try:
EditCitation(self.dbstate, self.uistate, [], Citation(),
Source())
EditSource(self.dbstate, self.uistate, [], Source(), Citation())
except WindowActiveError:
pass
@ -289,7 +286,9 @@ class CitationListView(ListView):
for handle in self.selected_handles():
citation = self.dbstate.db.get_citation_from_handle(handle)
try:
EditCitation(self.dbstate, self.uistate, [], citation)
EditSource(self.dbstate, self.uistate, [],
self.dbstate.db.get_source_from_handle(
citation.get_reference_handle()), citation)
except WindowActiveError:
pass

View File

@ -56,10 +56,12 @@ from gramps.gui.views.bookmarks import CitationBookmarks
from gramps.gen.errors import WindowActiveError
from gramps.gui.ddtargets import DdTargets
from gramps.gui.dialog import ErrorDialog
from gramps.gui.editors import EditCitation, DeleteCitationQuery, EditSource, \
DeleteSrcQuery
from gramps.gui.editors import (DeleteCitationQuery, EditSource,
DeleteSrcQuery)
from gramps.gui.filters.sidebar import SourceSidebarFilter
from gramps.gui.merge import MergeCitation, MergeSource
from gramps.gen.utils.citeref import (get_gedcom_title, get_gedcom_author,
get_gedcom_pubinfo, get_gedcom_page)
#-------------------------------------------------------------------------
#
@ -80,45 +82,48 @@ class CitationTreeView(ListView):
"""
# The data items here have to correspond, in order, to the items in
# src/giu/views/treemodels/citationtreemodel.py
COL_TITLE_PAGE = 0
COL_TITLE_NAME = 0
COL_ID = 1
COL_DATE = 2
COL_CONFIDENCE = 3
COL_PRIV = 4
COL_TAGS = 5
COL_CHAN = 6
COL_SRC_AUTH = 7
COL_SRC_ABBR = 8
COL_SRC_PINFO = 9
COL_CHAN = 6
COL_SRC_TEMPLATE = 7
COL_SRC_AUTH = 8
COL_SRC_ABBR = 9
COL_SRC_PINFO = 10
# column definitions
COLUMNS = [
(_('Title or Page'), TEXT, None),
(_('Name'), TEXT, None),
(_('ID'), TEXT, None),
(_('Date'), MARKUP, None),
(_('Confidence'), TEXT, None),
(_('Private'), ICON, 'gramps-lock'),
(_('Tags'), TEXT, None),
(_('Last Changed'), TEXT, None),
(_('Source: Template'), TEXT, None),
(_('Source: Author'), TEXT, None),
(_('Source: Abbreviation'), TEXT, None),
(_('Source: Publication Information'), TEXT, None),
]
COLUMN_FILTERABLE = [
COL_TITLE_PAGE,
COL_TITLE_NAME,
COL_ID,
COL_CHAN,
COL_SRC_TEMPLATE,
COL_SRC_AUTH,
COL_SRC_ABBR,
COL_SRC_PINFO
]
# default setting with visible columns, order of the col, and their size
CONFIGSETTINGS = (
('columns.visible', [COL_TITLE_PAGE, COL_ID, COL_SRC_AUTH,
('columns.visible', [COL_TITLE_NAME, COL_ID, COL_SRC_AUTH,
COL_SRC_PINFO]),
('columns.rank', [COL_TITLE_PAGE, COL_ID, COL_DATE, COL_CONFIDENCE,
('columns.rank', [COL_TITLE_NAME, COL_ID, COL_DATE, COL_CONFIDENCE,
COL_PRIV, COL_TAGS, COL_CHAN, COL_SRC_AUTH,
COL_SRC_ABBR, COL_SRC_PINFO]),
('columns.size', [200, 75, 100, 75, 40, 100, 100, 150, 100, 150])
COL_SRC_ABBR, COL_SRC_PINFO, COL_SRC_TEMPLATE]),
('columns.size', [200, 75, 100, 75, 40, 100, 100, 150, 100, 150, 50])
)
ADD_MSG = _("Add a new citation and a new source")
ADD_SOURCE_MSG = _("Add a new source")
@ -170,17 +175,10 @@ class CitationTreeView(ListView):
def setup_filter(self):
"""
Override the setup of the default Search Bar in listview, so that only
the searchable source fields are shown. This includes renaming the
'Title or Page' search to 'Title'
the searchable source fields are shown.
"""
def name(i):
if i == 0:
return _('Title')
else:
return self.COLUMNS[i][0]
self.search_bar.setup_filter(
[(name(pair[1]), pair[1], pair[1] in self.exact_search())
[(self.COLUMNS[(pair[1])][0], pair[1], pair[1] in self.exact_search())
for pair in self.column_order() if pair[0] and
pair[1] in self.COLUMN_FILTERABLE])
@ -191,10 +189,10 @@ class CitationTreeView(ListView):
_LOG.debug("\n\n\n")
if source:
_LOG.debug("---- %s -- source %s" %
(text, source.get_title()))
(text, get_gedcom_title(self.dbstate.db, source)))
elif citation:
_LOG.debug("---- %s -- citation %s" %
(text, citation.get_page()))
(text, get_gedcom_page(self.dbstate.db, citation)))
else:
_LOG.debug("---- %s -- handle %s" % (text, handle))
@ -411,8 +409,7 @@ class CitationTreeView(ListView):
window to already exist, so this is just an extra safety measure.
"""
try:
EditCitation(self.dbstate, self.uistate, [], Citation(),
Source())
EditSource(self.dbstate, self.uistate, [], Source(), Citation())
except WindowActiveError:
pass
@ -429,8 +426,8 @@ class CitationTreeView(ListView):
raise ValueError("selection must be either source or citation")
if source:
try:
EditCitation(self.dbstate, self.uistate, [],
Citation(), source)
EditSource(self.dbstate, self.uistate, [], source,
Citation())
except WindowActiveError:
from gramps.gui.dialog import WarningDialog
WarningDialog(_("Cannot share this reference"),
@ -480,7 +477,9 @@ class CitationTreeView(ListView):
raise ValueError("selection must be either source or citation")
if citation:
try:
EditCitation(self.dbstate, self.uistate, [], citation)
EditSource(self.dbstate, self.uistate, [],
self.dbstate.db.get_source_from_handle(
citation.get_reference_handle()), citation)
except WindowActiveError:
pass
else: # FIXME need try block here
@ -587,7 +586,7 @@ class CitationTreeView(ListView):
"""
Define the default gramplets for the sidebar and bottombar.
"""
return (("Source Filter",),
return (("Citation Filter",),
("Citation Gallery",
"Citation Notes",
"Citation Backlinks"))

View File

@ -70,32 +70,34 @@ _ = glocale.translation.gettext
class SourceView(ListView):
""" sources listview class
"""
COL_TITLE = 0
COL_NAME = 0
COL_ID = 1
COL_AUTH = 2
COL_ABBR = 3
COL_PINFO = 4
COL_PRIV = 5
COL_TAGS = 6
COL_CHAN = 7
COL_TEMPLATE = 5
COL_PRIV = 6
COL_TAGS = 7
COL_CHAN = 8
# column definitions
COLUMNS = [
(_('Title'), TEXT, None),
(_('Name'), TEXT, None),
(_('ID'), TEXT, None),
(_('Author'), TEXT, None),
(_('Abbreviation'), TEXT, None),
(_('Publication Information'), TEXT, None),
(_('Template'), TEXT, None),
(_('Private'), ICON, 'gramps-lock'),
(_('Tags'), TEXT, None),
(_('Last Changed'), TEXT, None),
]
# default setting with visible columns, order of the col, and their size
CONFIGSETTINGS = (
('columns.visible', [COL_TITLE, COL_ID, COL_AUTH, COL_PINFO]),
('columns.rank', [COL_TITLE, COL_ID, COL_AUTH, COL_ABBR, COL_PINFO,
COL_PRIV, COL_TAGS, COL_CHAN]),
('columns.size', [200, 75, 150, 100, 150, 40, 100, 100])
('columns.visible', [COL_NAME, COL_ID, COL_AUTH, COL_PINFO]),
('columns.rank', [COL_NAME, COL_ID, COL_AUTH, COL_ABBR, COL_PINFO,
COL_TEMPLATE, COL_PRIV, COL_TAGS, COL_CHAN]),
('columns.size', [200, 75, 150, 100, 150, 50, 40, 100, 100])
)
ADD_MSG = _("Add a new source")
EDIT_MSG = _("Edit the selected source")

View File

@ -148,6 +148,8 @@ from gramps.gen.utils.place import conv_lat_lon
from gramps.gui.pluginmanager import GuiPluginManager
from gramps.gen.relationship import get_relationship_calculator
from gramps.gen.utils.citeref import (get_gedcom_title, get_gedcom_author,
get_gedcom_pubinfo, get_gedcom_page)
COLLATE_LANG = glocale.collation
SORT_KEY = glocale.sort_key
@ -2346,7 +2348,7 @@ class BasePage(object):
# Add this source and its references to the page
source = self.dbase_.get_source_from_handle(citation.get_source_handle())
if source is not None:
list = Html("li", self.source_link(source.get_handle(), source.get_title(),
list = Html("li", self.source_link(source.get_handle(), get_gedcom_title(self.dbase_, source),
source.get_gramps_id(), cindex, uplink = self.up))
else:
list = Html("li", "None")
@ -2361,7 +2363,7 @@ class BasePage(object):
conf = None
for (label, data) in [
[_("Date"), _dd.display(sref.date)],
[_("Page"), sref.page],
[_("Page"), get_gedcom_page(self.dbase_, sref)],
[_("Confidence"), conf] ]:
if data:
tmp += Html("li", "%s: %s" % (label, data))
@ -4180,7 +4182,7 @@ class SourcePages(BasePage):
for handle in source_handles:
source = self.db.get_source_from_handle(handle)
if source is not None:
key = source.get_title() + str(source.get_gramps_id())
key = get_gedcom_title(report.database, source) + str(source.get_gramps_id())
source_dict[key] = (source, handle)
keys = sorted(source_dict, key=SORT_KEY)
@ -4219,8 +4221,9 @@ class SourcePages(BasePage):
)
tbody += trow
trow.extend(
Html("td", self.source_link(source_handle, source.get_title(),
source.get_gramps_id()), class_ ="ColumnName")
Html("td", self.source_link(source_handle,
get_gedcom_title(report.database, source),
source.get_gramps_id()), class_ ="ColumnName")
)
# add clearline for proper styling
@ -4245,7 +4248,7 @@ class SourcePages(BasePage):
return
BasePage.__init__(self, report, title, source.get_gramps_id())
self.page_title = source.get_title()
self.page_title = get_gedcom_title(report.database, source)
inc_repositories = self.report.options["inc_repository"]
self.navigation = self.report.options['navigation']
@ -4267,7 +4270,7 @@ class SourcePages(BasePage):
sourcedetail += thumbnail
# add section title
sourcedetail += Html("h3", html_escape(source.get_title()), inline = True)
sourcedetail += Html("h3", html_escape(get_gedcom_title(report.database, source)), inline = True)
# begin sources table
with Html("table", class_ = "infolist source") as table:
@ -4282,9 +4285,9 @@ class SourcePages(BasePage):
for (label, value) in [
(_("Gramps ID"), source_gid),
(_("Author"), source.get_author()),
(_("Author"), get_gedcom_author(report.database, source)),
(_("Abbreviation"), source.get_abbreviation()),
(_("Publication information"), source.get_publication_info()) ]:
(_("Publication information"), get_gedcom_pubinfo(report.database, source)) ]:
if value:
trow = Html("tr") + (
Html("td", label, class_ = "ColumnAttribute", inline = True),
@ -7423,7 +7426,7 @@ class NavWebReport(Report):
def _add_source(self, source_handle, bkref_class, bkref_handle):
source = self.database.get_source_from_handle(source_handle)
source_name = source.get_title()
source_name = get_gedcom_title(self.database, source)
source_fname = self.build_url_fname(source_handle, "src",
False) + self.ext
self.obj_dict[Source][source_handle] = (source_fname, source_name,
@ -7446,7 +7449,7 @@ class NavWebReport(Report):
citation = self.database.get_citation_from_handle(citation_handle)
# If Page is none, we want to make sure that a tuple is generated for
# the source backreference
citation_name = citation.get_page() or ""
citation_name = citation.get_name() or ""
source_handle = citation.get_reference_handle()
self.obj_dict[Citation][citation_handle] = ("", citation_name,
citation.gramps_id)