Simple Marriage Certificate.fh_lua--[[
@Title: Simple Marriage Certificate
@Type: Standard
@Author: [Norman Martin]
@Version: 1.1
@Keywords:
@LastUpdated: 14 April 2024
@Licence: This plugin is copyright (c) Norman Martin 2024 and contributors, and is licensed under the MIT License
which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence)
@Description: Designed to work with 'Civil Registration Certificate' Source Template from the Essentials collection,
it will record the details of a marriage certificate, for the current individual, based on the format of the
England and Wales Marriage Certificate/Parish Register since 1837.
Where the information is provided, it will also the residence and occupation of the husband,
and the occupations of their respective fathers at the time of the marriage.
For further support please post in the appropriate Family Historian User Group forums (FHUG) topic or a reply at the end of this download page,
where the plugin author will answer your questions which can be supplemented with screenshots if necessary.
@changes:
1.2 Added Vertical Scroll bar for certificate deatils to cater for different screen resolutions.
1.1 Amended Help and Support Options
]]
local help=[[
This plugin records a Marriage Certificate based on the format of the England and Wales Marriage Certificate/Parish Register since 1837.
It also creates of marriage, occupation and residence facts. To ensure consistency, it uses the Civil Registration Certificate Template
for the source.
Prerequisites
Before it can be used, the "Civil Registration Certificate" template from the Essentials collection
must have already been added to the project. This can be done by selecting Tools>Source Template Definitions
and then highlight the template(s) and add to project.
This plugin does NOT create any individuals. Before it is called, It requires that a person is first selected
and that that person is married.
Any fathers should be created before the plugin is called, as any name changed on the form will be considered as information
printed on the certificate (text from source).
To avoid replication of input, the following fields are saved to be displayed next time the plugin is used:
Region, Repository, Assessment, Image Directory and Media Directory.
The Region is a dropdown list of Regions declared in the source template; Repository is a dropdown list of Repositories you have set up;
and Assessment is a dropdown list of valid assessments for the source.
Image Directory is the windows directory where the marriage certificate image can be found. It can be populated by typing the directory
name in manually, or found by pressing the 'Image Directory' button to the left of the field and showing a Windows Folder Dialog screen.
Media Directory is where the image of the Marriage Certificate will be saved. It can be populated in the same method for the
Image Directory. Note you can create the appropriate media directory in the Windows Folder Dialog screen.
Form Fields
Region (Required):- this is a list of Regions declared in the source template
Repository : - this is a list of Repositories you have already set up
Where Married : - Address where marriage took place e.g. Parish Church (if known)
Marriage Place (Required) : Place married - either select from drop down for existing place or type new place
which will be added as a new place
Entry Number: - Entry number of certificate (if known)
Date of Marriage (Required): - Date marriage took place
Name and Surname: -Pre selected on loading form - can be amended
Age : -Age when married (can be text e.g. Full Age)
Condition : - Dropdown list of condition (e.g. Bachelor, Spinster etc)
Rank or Profession: - Description of job (if known)
Residence at time of marriage: - Address of husband/wife living when married (if known)
Place : - Place husband/wife were living (if known)
Fathers name and surname: - Pre selected on loading form - can be amended
Rank of Profession (father): - Description of job (if known)
Rites and Ceremonies : - if stated (e.g. Established Church)
Marriage Type : - Dropdown list of marriage types (e.g. After Banns, By Licence etc)
In the Presence of : - List of witnesses to marriage
Married By (Required) : - Name of person performing the marriage
Assessment : - Dropdown list of valid assessments
Image Directory : - Directory to initiate search for image of certificate
Media Directory (Required): - Directory where image will be saved
As Source : - Dropdown list to determine name given to file when saved in the media directory
Options are As Source - filename same as source title
As Filename - filename same as original filename
My Choice - type your own filename in Image File field
Media : - Button to invoke windows file dialog to identify certificate image to be copied
Image File (Required): - name of media file to be created
Status : - status of form - e.g. errors or certificate saved
When you press the save button, the form is validated and any errors reported in the status bar.
If the action is successful, then the appropriate message is shown in that status bar.
When the certificate is saved, the ini file is updated to retain the Region, Repository, Assessment, Image Directory
and Media Directory fields.
Saving a Certificate will create a source record for the marriage certificate and create a formatted 'text from source'
and a link to a newly created media record. The source record is linked to the Marriage Fact.
The text written to the ‘text from source’ contains the values derived from the form as you have entered them.
This text can later be amended in the Citation record in Family Historian to correct any textual errors.
If the information has been provided, then the appropriate occupation and residence facts are created and linked to the source record.
These can be for the husband, wife and their fathers (occupation only). Age will only saved as a text if a valid age (e.g. 25) is entered.
You will need to press the Exit button, after saving, to exit the form and return back to Family Historian.
]]
-- << Comment in the next 2 lines if you need to use IUP >>
require("iuplua");
iup.SetGlobal("CUSTOMQUITMESSAGE","YES");
fh = require("fhUtils");
fhfu =require("fhFileUtils")
local plugIn="Simple Marriage Certificate" -- plugin name
local hasUsed="No" -- variable to decide to show welcome screen
local dlgSize="440x350"
fhInitialise(7); -- implies users will need version 7 as a minimum; change if that is not the case
local iniFile=""
local templateID=-1
local currPtr = fhNewItemPtr()
local ptrFamily=fhNewItemPtr();
local husbandPtr = fhNewItemPtr()
local wifePtr = fhNewItemPtr()
local husbandFatherPtr = fhNewItemPtr()
local wifeFatherPtr = fhNewItemPtr()
local curPerson=""
local curDates=""
local ptrTemplate=fhNewItemPtr()
local ptrRepos=fhNewItemPtr()
local region=""
local type="Marriage"
local assessment=""
local address=""
local source=-1
local haveCitation=false
local Places={}
local Families={}
local selFile=""
-------------------------------------------------------
-- Define Dialog Fields
-------------------------------------------------------
local color = {error = '255 200 200',red = '255 0 0',green = '0 128 0', clear='255 255 255'}
local dte_Today = iup.datepick{name='TodaysDate',size='1'}
local lst_Region = iup.list{name='Region',expand='HORIZONTAL', dropdown="YES"}
local lst_Repos = iup.list{name='Repository',expand='HORIZONTAL', dropdown="YES"}
local txt_Address = iup.text{name='Address',expand='HORIZONTAL' }
local lst_MarriagePlace = iup.list{name='MarriagePlace',expand='HORIZONTAL',editbox='YES', dropdown="NO",visiblelines=3}
local txt_EntryNo = iup.text{name='EntryNo',expand='HORIZONTAL' }
local dte_Marriagedate = iup.datepick{name='MarriageDate',expand='HORIZONTAL'}
local txt_Husband = iup.text{name='Husband',size='150' }
local txt_Wife = iup.text{name='Wife',size='150'}
local txt_HusbandAge = iup.text{name='HusbandAge',size='150' }
local txt_WifeAge = iup.text{name='WifeAge',size='150' }
local lst_HusbandCond = iup.list{name='HusbandCond',size='150', dropdown="YES" }
local lst_WifeCond = iup.list{name='WifeCond',size='150', dropdown="YES"}
local txt_HusbandOcc = iup.text{name='HusbandOcc',size='150' }
local txt_WifeOcc = iup.text{name='WifeOcc',size='150'}
local txt_HusbandAddress = iup.text{name='HusbandAddress',size='150'}
local txt_WifeAddress = iup.text{name='WifeAddress',size='150'}
local lst_HusbandPlace = iup.list{name='HusbandPlace',size='150',editbox='YES', dropdown="NO",visiblelines=3}
local lst_WifePlace = iup.list{name='WifePlace',size='150',editbox='YES', dropdown="NO",visiblelines=3}
local txt_HusbandFather = iup.text{name='HusbandFather',size='150' }
local txt_WifeFather = iup.text{name='WifeFather',size='150'}
local txt_HusbandFatherOcc = iup.text{name='HusbandFatherOcc',size='150' }
local txt_WifeFatherOcc = iup.text{name='WifeFatherOcc',size='150' }
local txt_Rites = iup.text{name='Rites',expand='HORIZONTAL' }
local lst_MarriageType = iup.list{name='MarriageType',expand='HORIZONTAL', dropdown="YES"}
local txt_Informant = iup.text{name='Informant',expand='HORIZONTAL', multiline='YES',visiblelines=2}
local lst_Assessment = iup.list{name='Assessment',expand='HORIZONTAL', dropdown="YES"}
local txt_Registrar = iup.text{name='Notes',expand='HORIZONTAL'}
local lab_message = iup.label{title=' ',fgcolor=color.red, expand='HORIZONTAL'}
local lab_husband = iup.label{title='Husband ',size='150'}
local lab_wife = iup.label{title='Wife ',size='150'}
local inp_img_dir = iup.text{name='ImageDir',expand='HORIZONTAL' }
local inp_Media_dir = iup.text{name='MediaDir', expand='HORIZONTAL', }
local inp_name = iup.text{Name='Filter', expand='HORIZONTAL',readonly="YES" }
local inp_file_list = iup.label{name='FileList',expand="HORIZONTAL", }
local lst_name = iup.list{name='Filename',"As Source","As Filename","My Choice",value=1; dropdown="YES"}
local lab_Mess = iup.label{title='Please select a file to select the image to copy ',fgcolor=color.blue, expand='HORIZONTAL'}
local bt_Save = iup.button{name='save', title='Save'}
local btn_Cancel = iup.button{name='cancel', title='Cancel'}
local btn_Media = iup.button{name='source', title='Media'}
local btn_help = iup.button {name='help', title='Help'}
local btn_mediaDir=iup.button{name='MediaDir', title='Media Directory>>'}
local btn_imageDir=iup.button{name='ImageDir', title='Image Directory>>'}
local info_Mess = iup.label{title='---------------Marriage Certificate Details-------------------',fgcolor=color.blue, expand='HORIZONTAL'}
local image_Mess = iup.label{title='----------------Marriage Certificate File--------------------',fgcolor=color.blue, expand='HORIZONTAL'}
function main()
local iniDir=fhGetContextInfo("CI_PROJECT_DATA_FOLDER").."\\Plugin Data\\"
-- check that plugin data folder exists
if not fhfu.folderExists(iniDir) then
fhfu.createFolder (iniDir)
end
iniFile=fhGetContextInfo("CI_PROJECT_DATA_FOLDER").."\\Plugin Data\\"..fhGetContextInfo("CI_PLUGIN_NAME")..".dat"
hasUsed=fhGetIniFileValue(iniFile, "Defaults", "Welcome", "text")
dlgSize=fhGetIniFileValue(iniFile, "Defaults", "Dialog Size", "text",dlgSize)
-- do I need to display welcome screen
if hasUsed~="Yes" then
Welcome()
end
local ptrParents=fhNewItemPtr();
templateID=FindTemplate('Civil Registration Certificate')
-- check that template exists
if templateID~=-1 then
--Try to get the Current Individual, Can't continue if not selected
currPtr=fh.getCurrentIndividual ()
if currPtr:IsNotNull() then
curPerson=fhGetItemText(currPtr,'INDI.NAME:GIVEN_ALL')..' '
curDates=fhGetItemText(currPtr,'INDI.BIRT.DATE')..' - '..fhGetItemText(currPtr,'INDI.DEAT.DATE')
-- get husband and wife
ptrFamily:MoveTo(currPtr, "INDI.FAMS")
if ptrFamily:IsNull() then
fhMessageBox("No marriage exists for person selected")
else
ptrFamily = fhGetValueAsLink(ptrFamily)
husbandPtr=fhGetValueAsLink(fhGetItemPtr(ptrFamily,'~.HUSB'))
wifePtr=fhGetValueAsLink(fhGetItemPtr(ptrFamily,'~.WIFE'))
curPerson=curPerson..fhGetItemText(husbandPtr,'INDI.NAME:SURNAME')
-- get fathers
if husbandPtr:IsNotNull() then
ptrParents:MoveTo(husbandPtr, "INDI.FAMC")
if ptrParents:IsNotNull() then
ptrParents = fhGetValueAsLink(ptrParents)
husbandFatherPtr=fhGetValueAsLink(fhGetItemPtr(ptrParents,'~.HUSB'))
end
end
if wifePtr:IsNotNull() then
ptrParents:MoveTo(wifePtr, "INDI.FAMC")
if ptrParents:IsNotNull() then
ptrParents = fhGetValueAsLink(ptrParents)
wifeFatherPtr=fhGetValueAsLink(fhGetItemPtr(ptrParents,'~.HUSB'))
end
end
-- show dialog screen
MainDialog()
end
else
fhMessageBox("No person selected")
end
else
fhMessageBox("Requires Civil Registration Index source template from the Essentials collection")
end
end
-------------------------------------------------------
-- identify media record
-------------------------------------------------------
function btn_Media:action()
res=self.name
-- validate form
selFile=ListFiles(inp_img_dir.value)
inp_file_list.title = selFile
ShowFilename()
end
-------------------------------------------------------
-- Select media directory from window dialog
-------------------------------------------------------
function btn_mediaDir:action()
local dirName=""
res=self.name
-- get directory name
dirName=ListDir(true)
if dirName~="" then
inp_Media_dir.value=dirName
end
end
-------------------------------------------------------
-- Select image directory from window dialog
-------------------------------------------------------
function btn_imageDir:action()
local dirName=""
res=self.name
-- get directory name
dirName=ListDir(false)
if dirName~="" then
inp_img_dir.value=dirName
end
end
-------------------------------------------------------
-- show help screen
-------------------------------------------------------
function btn_help:action()
Help()
end
function lst_name:action(t,i,v)
if i==3 then
inp_name.readonly="NO"
else
inp_name.readonly="YES"
end
ShowFilename()
end
-------------------------------------------------------
-- validate dialog and close screen if valid
-------------------------------------------------------
function bt_Save:action()
-- validate
lab_message.title = ''
-- validate form
if lst_Region.value=='0' then
lab_message.title = 'No region selected'
lst_Region.bgcolor = color.error
elseif lst_MarriagePlace.value=='' then
lab_message.title = 'No Marriage Place selected'
lst_MarriagePlace.bgcolor = color.error
elseif IsToday(dte_Marriagedate) then
lab_message.title = 'No Marriage Date selected'
dte_Marriagedate.bgcolor = color.error
elseif txt_Registrar.value=='' then
lab_message.title = 'No celebrant selected'
txt_Registrar.bgcolor = color.error
elseif inp_Media_dir.value=='' then
lab_message.title = 'Please provide a media directory to copy file to'
inp_Media_dir.bgcolor = color.error
elseif inp_file_list.title=='' then
lab_message.title = 'No media file selected'
inp_file_list.bgcolor = color.error
elseif inp_name.value=='' and inp_name.readonly=="NO" then
lab_message.title = 'No filename for image file'
elseif selFile=='' then
lab_message.title = 'No image selected'
else
SaveEntry()
end
end
function btn_Cancel:action()
local exit=true
if btn_Cancel.title=="Cancel" then
res = fhMessageBox("Do you wish to cancel saving this certificate?", "MB_YESNO", "MB_ICONQUESTION")
if res == "No" then
exit=false
dlg:show()
end
end
if exit then
return iup.CLOSE
end
end
-- << insert additional functions here >>
----------------------------------------------------
-- Function: MainDialog - display dialog
-- This is the Main Dialog Screen
---------------------------------------------------
function MainDialog()
-------------------------------------------------------
-- Dialog field actions
-------------------------------------------------------
function Exit()
return iup.CLOSE
end
dlg = iup.dialog{
iup.vbox{
iup.hbox{iup.label{title='Region',size='140'},dte_Today,lst_Region},
iup.hbox{iup.label{title='Repository',size='140'},lst_Repos},
iup.hbox{iup.label{title='',size='140'},info_Mess},
iup.scrollbox{
iup.vbox{
iup.hbox{iup.label{title='Where Married',size='140'},txt_Address},
iup.hbox{iup.label{title='Marriage Place',size='140'}, lst_MarriagePlace},
iup.hbox{iup.label{title='Entry Number',size='140'},txt_EntryNo},
iup.hbox{iup.label{title='Date of Marriage',size='140'},dte_Marriagedate},
iup.hbox{iup.label{title=' ',size='140'},lab_husband,lab_wife,gap='5'},
iup.hbox{iup.label{title='Name and Surname',size='140'},txt_Husband,txt_Wife,gap='5'},
iup.hbox{iup.label{title='Age',size='140'},txt_HusbandAge,txt_WifeAge,gap='5'},
iup.hbox{iup.label{title='Condition',size='140'},lst_HusbandCond,lst_WifeCond,gap='5'},
iup.hbox{iup.label{title='Rank or Profession',size='140'},txt_HusbandOcc,txt_WifeOcc,gap='5'},
iup.hbox{iup.label{title='Residence at time of marriage',size='140'},txt_HusbandAddress,txt_WifeAddress,gap='5'},
iup.hbox{iup.label{title='Place',size='140'},lst_HusbandPlace,lst_WifePlace,gap='5'},
iup.hbox{iup.label{title='Fathers Name and Surname',size='140'},txt_HusbandFather,txt_WifeFather,gap='5'},
iup.hbox{iup.label{title='Rank or Profession (Father)',size='140'},txt_HusbandFatherOcc,txt_WifeFatherOcc,gap='5'},
iup.hbox{iup.label{title='Rites and Ceremonies ',size='140'}, txt_Rites},
iup.hbox{iup.label{title='Marriage Type',size='140'}, lst_MarriageType},
iup.hbox{iup.label{title='In the Prescence of',size='140'}, txt_Informant},
iup.hbox{iup.label{title='Married by',size='140'},txt_Registrar},
iup.hbox{iup.label{title='Assessment',size='140'}, lst_Assessment},
},
canfocus = "NO",
scrollbar = "VERTICAL",
xmax = "0",
dy = "334",
ymax = "583",
wheeldropfocus = "YES",
},
iup.hbox{iup.label{title='',size='140'},image_Mess},
iup.hbox{btn_imageDir,iup.label{title='',size='1'},inp_img_dir},
iup.hbox{btn_mediaDir,iup.label{title='',size='1'},inp_Media_dir},
iup.hbox{iup.label{title=''},lst_name,size='70',inp_name,gap='25'},
iup.hbox{btn_Media,lab_Mess},
iup.hbox{iup.label{title='Image File',size='70'}, inp_file_list},
iup.hbox{iup.label{title=' ',size='140'}},
iup.label{title='Status'},lab_message,
iup.hbox{bt_Save,iup.label{title='',size='120'},btn_Cancel,iup.label{title='',size='120'},btn_help;padding='10',gap='5'}
;padding='5',gap='5',nmargin='20x20'
},
title='Add Marriage Certificate for '..curPerson..' '..curDates,padding='10',gap='5', size='500',
close_cb=function() res='closed' return iup.CLOSE end}
-- populate list with defaults
PopulateList(lst_Region,GetRegions(templateID))
PopulateList(lst_Repos,GetRepositories())
PopulateList(lst_MarriagePlace,fh.createPlaceList())
PopulateList(lst_HusbandPlace,fh.createPlaceList())
PopulateList(lst_WifePlace,fh.createPlaceList())
ListCondition(lst_HusbandCond)
ListCondition(lst_WifeCond)
ListAssessments(lst_Assessment)
ListMarriageTypes(lst_MarriageType)
inp_file_list.title=''
-- populate name
txt_Husband.value=fhGetItemText(husbandPtr,'INDI.NAME')
txt_Wife.value=fhGetItemText(wifePtr,'INDI.NAME')
txt_HusbandFather.value=fhGetItemText(husbandFatherPtr,'INDI.NAME')
txt_WifeFather.value=fhGetItemText(wifeFatherPtr,'INDI.NAME')
-- read ini file and populate accordingly
inp_img_dir.value=fhGetIniFileValue(iniFile, "Directories", "Images", "text")
inp_Media_dir.value=fhGetIniFileValue(iniFile, "Directories", "Marriage", "text")
region=fhGetIniFileValue(iniFile, "Defaults", "Region", "text","")
lst_Region.valuestring=region
repos=fhGetIniFileValue(iniFile, region, "Repository", "text",'')
lst_Repos.valuestring=repos
assessment=fhGetIniFileValue(iniFile, region, "Assessment", "text",'')
lst_Assessment.valuestring=assessment
dlg:show() -- Show the dialog
-- size the dialog screen appropriately
dlg.size=dlgSize
iup.Map(dlg)
iup.MainLoop() -- Process the dialog
dlg:destroy() -- Clean up the dialog, note all dialog controls are destroyed as well
end
----------------------------------------------------
-- Function: SaveEntry - Saves ini file settings
-- and creates citation
-- then updates events and saves citation
---------------------------------------------------
function SaveEntry()
local txt=""
local region=lst_Region.valuestring
local ptrLink =fhNewItemPtr();
local ptrMarriage=fhNewItemPtr();
local ptrTextFromSource=fhNewItemPtr();
local ptrInfo =fhNewItemPtr();
local dtMyDate,yr
-- save ini file settings
fhSetIniFileValue(iniFile, "Defaults", "Dialog Size", "text",dlg.Size)
fhSetIniFileValue(iniFile, "Defaults", "Region", "text",region)
fhSetIniFileValue(iniFile, region, "Assessment", "text",lst_Assessment.valuestring)
fhSetIniFileValue(iniFile, region, "Repository", "text",lst_Repos.valuestring)
if CheckDirectory(inp_img_dir.value) then
fhSetIniFileValue(iniFile, "Directories", "Images", "text",inp_img_dir.value)
end
if CheckDirectory(inp_Media_dir.value) then
fhSetIniFileValue(iniFile, "Directories", "Marriage", "text",inp_Media_dir.value)
end
lab_message.title = ''
-- create a templated source record
sourcePtr= fhCreateItem("SOUR")
ptrLink = fhCreateItem("_SRCT", sourcePtr)
fhSetValueAsLink(ptrLink, ptrTemplate)
ptrLink = fhCreateItem("TITL", sourcePtr)
-- add fields
AddInfo(sourcePtr, '~NM-PRINCIPAL', txt_Husband.value)
AddInfo(sourcePtr, '~NM-PRINCIPAL_2', txt_Wife.value)
AddInfo(sourcePtr, '~EN-TYPE', 'Marriage')
AddInfo(sourcePtr, '~EN-REGION', region)
dtMyDate,yr=CalenderToDate(dte_Marriagedate.value)
AddInfoAsDate(sourcePtr, '~DT-DATE', dtMyDate)
AddInfo(sourcePtr, '~PL-LOCATION', lst_MarriagePlace.value)
AddInfo(sourcePtr, '~AD-ADDRESS', txt_Address.value)
AddInfo(sourcePtr, '~TX-REFERENCE', txt_EntryNo.value)
if lst_Repos.valuestring~=nil then
ptrLink = fhCreateItem("~RP-REPOSITORY", sourcePtr)
fhSetValueAsLink(ptrLink, FindRepository(lst_Repos.valuestring))
end
AddInfo(sourcePtr, 'TITL', 'Marriage certificate of '..fhGetItemText(sourcePtr,'~.~NM-PRINCIPAL')..' and '..fhGetItemText(sourcePtr,'~.~NM-PRINCIPAL_2')..', '..fhGetItemText(sourcePtr,'~.~DT-DATE'))
-- Create text from Source
AddTextFromSource(sourcePtr)
-- Add Media Record
if inp_name.value=='' then
inp_name.value=fhGetItemText(sourcePtr,'~.TITL')
end
filename= SaveImageFile(inp_file_list.title,inp_Media_dir.value, inp_name.value)
if filename~="" then
-- copied file , now create object
if CreateObject(sourcePtr,filename) ==false then
lab_message.title = 'Failed to link image to source'
end
else
lab_message.title = 'Failed to copy file'
end
-- create / update Marriage event
ptrMarriage=fhGetItemPtr(ptrFamily,'~.MARR')
if ptrMarriage:IsNull() then
-- create Marriage Event
ptrMarriage = fhCreateItem("MARR", ptrFamily)
end
AddInfo(ptrMarriage, 'DATE', fhGetItemText(sourcePtr,'~.~DT-DATE'))
AddInfo(ptrMarriage, "PLAC", lst_MarriagePlace.value)
AddInfo(ptrMarriage, "ADDR", txt_Address.value)
ptrLink = fhCreateItem("SOUR", ptrMarriage)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
-- add ages
if txt_HusbandAge.value ~="" then
ptrInfo= fhCreateItem("HUSB", ptrMarriage)
AddInfo(ptrInfo, 'AGE', txt_HusbandAge.value)
end
if txt_WifeAge.value ~="" then
ptrInfo= fhCreateItem("WIFE", ptrMarriage)
AddInfo(ptrInfo, 'AGE', txt_WifeAge.value)
end
-- add witness
if txt_Informant.value ~="" then
local sWitness=Split(txt_Informant.value,'\n')
for i,v in ipairs(sWitness) do
if v ~="" then
ptrInfo= fhCreateItem("_SHAN", ptrMarriage)
fhSetValueAsText(ptrInfo, v)
AddInfo(ptrInfo, 'ROLE', "Witness")
ptrLink = fhCreateItem("SOUR", ptrInfo)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
end
end
-- Add Residence
if lst_HusbandPlace.value ~="" then
ptrOcc=fhCreateItem("RESI", husbandPtr)
AddInfo(ptrOcc, "ADDR", txt_HusbandAddress.value)
AddInfo(ptrOcc, "PLAC", lst_HusbandPlace.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
if txt_HusbandAge.value ~="" then
AddInfo(ptrOcc, 'AGE', txt_HusbandAge.value)
end
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if lst_WifePlace.value ~="" then
ptrOcc=fhCreateItem("RESI", wifePtr)
AddInfo(ptrOcc, "ADDR", txt_WifeAddress.value)
AddInfo(ptrOcc, "PLAC", lst_WifePlace.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
if txt_WifeAge.value ~="" then
AddInfo(ptrOcc, 'AGE', txt_WifeAge.value)
end
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
-- add occupation(s)
if txt_HusbandOcc.value ~="" then
ptrOcc=fhCreateItem("OCCU", husbandPtr)
fhSetValueAsText(ptrOcc, txt_HusbandOcc.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
if txt_HusbandAge.value ~="" then
AddInfo(ptrOcc, 'AGE', txt_HusbandAge.value)
end
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if txt_WifeOcc.value ~="" then
ptrOcc=fhCreateItem("OCCU", wifePtr)
fhSetValueAsText(ptrOcc, txt_WifeOcc.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
if txt_WifeAge.value ~="" then
AddInfo(ptrOcc, 'AGE', txt_WifeAge.value)
end
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if txt_HusbandFatherOcc.value ~="" then
ptrOcc=fhCreateItem("OCCU", husbandFatherPtr)
fhSetValueAsText(ptrOcc, txt_HusbandFatherOcc.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if txt_WifeFatherOcc.value ~="" then
ptrOcc=fhCreateItem("OCCU", wifeFatherPtr)
fhSetValueAsText(ptrOcc, txt_WifeFatherOcc.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if lab_message.title == '' then
lab_message.fgcolor=color.green
lab_message.title = 'Marriage Certificate Saved'
btn_Cancel.title="Exit"
end
end
-------------------------------------------------------
-- ListFiles - display windows file dialog screen to select image file
-- - passes default directory to windows dialog screen
-------------------------------------------------------
function ListFiles(defDir)
f, err = iup.GetFile(defDir.."/".."*.jpg;*.png")
if err == 1 then
iup.Message("New file", f)
elseif err == 0 then
return f
end
end
function ListDir(projectDir)
local dataDir=""
if projectDir then dataDir=fhGetContextInfo("CI_PROJECT_DATA_FOLDER") end
filedlg = iup.filedlg{directory=dataDir,dialogtype = "DIR", title = "Select Directory"}
iup.Popup(filedlg)
-- Gets file dialog status
status = filedlg.status
if status == "0" or status == "1" then
return filedlg.value
end
return ""
end
----------------------------------------------------
-- Function: ShowFilename - display new filename to copy to
---------------------------------------------------
function ShowFilename()
local path=""
local file=""
local extension=""
if lst_name.value=="1" then
-- display source name
inp_name.value=""
elseif lst_name.value=="2" then
path,file,extension = SplitFilename(selFile)
inp_name.value=string.gsub(file,"."..extension, "")
else
-- allow to overwrite
end
end
---------------------------------------
-- Function: SaveImageFile - copies source image file to media directory
-- renaming to source title if requested
-- returns filename to be written as object file
---------------------------------------
function SaveImageFile(fromFile,ToDirectory, Title)
local path=""
local file=""
local extension=""
local toFile=""
path,file,extension = SplitFilename(fromFile)
if fhfu.fileExists (fromFile) then
toFile=ToDirectory.."\\"..Title.."."..extension
if fhfu.fileExists (toFile) then
fhMessageBox("Source already has image added")
else
-- does directory exist
if CheckDirectory(ToDirectory) then
-- copy file to new directory changing its name
if fhfu.copyFile (fromFile, toFile, false) then
return string.gsub(toFile, fhGetContextInfo("CI_PROJECT_DATA_FOLDER").."\\", "")
end
end
end
end
return ""
end
---------------------------------------
-- Function: CreateObject - creates a new object
-- and links to source record
---------------------------------------
function CreateObject(SourcePtr,Filename)
local ptrObj= fhNewItemPtr()
local ptrFile= fhNewItemPtr()
local ptrLink= fhNewItemPtr()
local newFile=""
if SourcePtr:IsNotNull() then
-- now create object
ptrObj= fhCreateItem("OBJE")
ptrFile= fhCreateItem("FILE", ptrObj,true)
if ptrFile:IsNotNull() then
fhSetValueAsText(ptrFile,Filename)
AddInfo(ptrFile,"FORM",PictureFormat(Filename))
AddInfo(ptrFile,"TITL",fhGetItemText(SourcePtr,"SOUR.TITL"))
AddInfo(ptrObj,"_DATE",fhGetItemText(SourcePtr,"SOUR.~DT-DATE"))
AddInfo(ptrObj,"_KEYS","Picture")
-- now link object to source
ptrLink = fhCreateItem("OBJE", SourcePtr ) -- create a OBJE field
fhSetValueAsLink(ptrLink, ptrObj)
return true
end
end
return false
end
---------------------------------------
-- Function: AddTextFromSource
-- add source text in rich text format
---------------------------------------
function AddTextFromSource(SourcePtr)
local txt='Certified Copy of an Entry of Marriage\n'
local txtPtr=fhNewItemPtr();
local dtMyDate,yr=CalenderToDate(dte_Marriagedate.value)
local district=Split(lst_MarriagePlace.value ,',')
local rt = fhNewRichText() -- create a new rich text object
txt=txt..yr..' Marriage solemnized at '..txt_Address.value..'\n'
txt=txt..'of '..district[1]..' in the county of '..district[2]..' \n\n'
txt=txt..''
txt=txt..' No. | When Married. | Name and Surname. | Age. | Condition. | Rank or Profession. | Residence at the time of Marriage. | Fathers Name and Surname. | Rank or Profession of Father.
\n'
txt=txt..' '
txt=txt..' | '
txt=txt..' | '
txt=txt..txt_Husband.value..' | '
txt=txt..txt_HusbandAge.value..' | '
txt=txt..lst_HusbandCond.valuestring..' | '
txt=txt..txt_HusbandOcc.value..' | '
txt=txt..txt_HusbandAddress.value..'\n'..lst_HusbandPlace.value..' | '
txt=txt..txt_HusbandFather.value..' | '
txt=txt..txt_HusbandFatherOcc.value..' | '
txt=txt..'
'
txt=txt..' '
txt=txt..txt_EntryNo.value..' | '
txt=txt..dtMyDate:GetDisplayText()..' | '
txt=txt..txt_Wife.value..' | '
txt=txt..txt_WifeAge.value..' | '
txt=txt..lst_WifeCond.valuestring..' | '
txt=txt..txt_WifeOcc.value..' | '
txt=txt..txt_WifeAddress.value..'\n'..lst_WifePlace.value..' | '
txt=txt..txt_WifeFather.value..' | '
txt=txt..txt_WifeFatherOcc.value..' | '
txt=txt..'
'
txt=txt..'
'
txt=txt..'\nMarried in the '..txt_Address.value..' according to the Rites and Ceremonies of the '..txt_Rites.value..' '..lst_MarriageType.valuestring..' by me.\n'
txt=txt..''
txt=txt..''
txt=txt..'This marriage was solemnized between us, | '..txt_Husband.value..'\n'..txt_Wife.value..' | '
txt=txt..' In the presence of us, | '..txt_Informant.value..' | '
txt=txt..txt_Registrar.value
txt=txt..'
'
txt=txt..'
'
txtPtr= fhCreateItem("TEXT", sourcePtr)
rt:SetText(txt)
fhSetValueAsRichText(txtPtr , rt) -- set value of the note using passed in parameter
end
---------------------------------------
-- Function: AddInfo - add info to fact, updating if fact exists
---------------------------------------
function AddInfo(ptr, Type, Value)
if Type and Value then
local infoPtr=fhGetItemPtr(ptr,'~.'..Type)
if infoPtr:IsNull() then
infoPtr= fhCreateItem(Type, ptr)
end
fhSetValueAsText(infoPtr, Value)
end
end
---------------------------------------
-- Function: AddInfoAsDate - add info to fact, updating if fact exists
---------------------------------------
function AddInfoAsDate(ptr, Type, Value)
if Type and Value then
local infoPtr=fhGetItemPtr(ptr,'~.'..Type)
if infoPtr:IsNull() then
infoPtr= fhCreateItem(Type, ptr)
end
fhSetValueAsDate(infoPtr, Value)
end
end
---------------------------------------------------
--function FindTemplate(template name)
-------------------------------------------------------
function FindTemplate(tName)
local ptr=fhNewItemPtr();
ptr:MoveToFirstRecord('_SRCT')
while ptr:IsNotNull() do
if fhGetItemText(ptr,'~.NAME')==tName then
ptrTemplate=ptr
return fhGetRecordId(ptr)
end
ptr:MoveNext()
end
return -1
end
---------------------------------------------------
--function FindRepository(Repository name)
-------------------------------------------------------
function FindRepository(tName)
local ptr=fhNewItemPtr();
ptr:MoveToFirstRecord('REPO')
while ptr:IsNotNull() do
if fhGetItemText(ptr,'~.NAME')==tName then
ptrRepos=ptr
return ptr
end
ptr:MoveNext()
end
return -1
end
---------------------------------------
-- Function: GetRegions - returns table of regions for CRI
---------------------------------------
function GetRegions(ID)
local array={}
local ptrTemplate = fhNewItemPtr() -- declare pointer
local ptrFDef=fhNewItemPtr()
local strRegions=""
ptrTemplate:MoveToFirstRecord("_SRCT") -- point to the first record
while not ptrTemplate:IsNull() do
if fhGetRecordId(ptrTemplate)==ID then
-- loop through regions
ptrFDef= fhGetItemPtr(ptrTemplate,'~.FDEF')
while not ptrFDef:IsNull() do
if fhGetItemText(ptrFDef,'~.NAME')=='Region' then
-- found field definiton
strRegions =fhGetItemText(ptrFDef,'~.PROM')
return Split(strRegions,'|')
end
ptrFDef:MoveNext('SAME_TAG')
end
end
ptrTemplate:MoveNext()
end
return array
end
---------------------------------------
-- Function: GetRepositories - returns table of repositories
---------------------------------------
function GetRepositories()
local array={}
local ptrRepos = fhNewItemPtr() -- declare pointer
local strRepos=""
ptrRepos:MoveToFirstRecord("REPO") -- point to the first record
while not ptrRepos:IsNull() do
-- For each Repository Add the Name to the list
strRepos =fhGetItemText(ptrRepos,'REPO.NAME')
table.insert(array,strRepos )
ptrRepos:MoveNext()
end
return array
end
---------------------------------------
-- Function: ListAssessment - returns table of regions for CRI
---------------------------------------
function ListAssessments(l)
local array ={}
table.insert(array,'Unreliable')
table.insert(array,'Questionable')
table.insert(array,'Secondary information')
table.insert(array,'Primary information')
table.insert(array,'')
PopulateList(l,array)
end
---------------------------------------
-- Function: ListCondition - returns table of Marriage Status
---------------------------------------
function ListCondition(l)
local array ={}
table.insert(array,'Bachelor')
table.insert(array,'Spinster')
table.insert(array,'Widower')
table.insert(array,'Widow')
table.insert(array,'Divorced')
PopulateList(l,array)
end
---------------------------------------
-- Function: ListMarriageTypes - returns table of Marriage Types
---------------------------------------
function ListMarriageTypes(l)
local array ={}
table.insert(array,'After Banns')
table.insert(array,'By Banns')
table.insert(array,'By Certificate')
table.insert(array,'By Declaration')
table.insert(array,'By Licence')
table.insert(array,'By Publication')
PopulateList(l,array)
end
-------------------------------------------------------
-- PopulateList populates a dialog list with table values
-------------------------------------------------------
function PopulateList(l, tblVals)
local is_indexed = (rawget( tblVals, 1 ) ~= nil)
l.REMOVEITEM = "ALL"
if not is_indexed then
local i=1
for k, _ in pairs(tblVals) do
l[tostring(i)]=k
i=i+1
end
else
for i, v in ipairs(tblVals) do
l[tostring(i)]=v
end
end
end
---------------------------------------
-- Function: Split - splits a string by delimter
-- and returns a table of strings
---------------------------------------
function Split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, trim(match));
end
return result;
end
---------------------------------------
-- Function: trim - removes leading and trailing spaces
---------------------------------------
function trim(s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
---------------------------------------
-- Function: PictureFormat - returns format of image file
---------------------------------------
function PictureFormat(fromFile)
local path=""
local file=""
local extension=""
path,file,extension = SplitFilename(fromFile)
if string.upper(extension)=='JPG' then
return 'jpeg'
elseif string.upper(extension)=='TIF' then
return 'tiff'
end
return extension
end
---------------------------------------
-- Function: SplitFilename - Path, Filename, and Extension as 3 values
---------------------------------------
function SplitFilename(strFilename)
-- Returns the Path, Filename, and Extension as 3 values
if lfs.attributes(strFilename,"mode") == "directory" then
local strPath = strFilename:gsub("[\\/]$","")
return strPath.."\\","",""
end
strFilename = strFilename.."."
return strFilename:match("^(.-)([^\\/]-%.([^\\/%.]-))%.?$")
end
---------------------------------------
-- Function: CheckDirectory - checks that directory exits
---------------------------------------
function CheckDirectory(Directory)
if fhfu.folderExists(Directory) then
return true
else
-- create folder
if fhfu.createFolder(Directory) then
return true
end
end
return false
end
---------------------------------------
-- Function: trims a sting;
-- ensures that files do not have leading or trailing spaces
---------------------------------------
function trim(s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
---------------------------------------
-- Function: CalenderToDate returns a FH date from Calender date
-- yr is year from Calender date
---------------------------------------
function CalenderToDate(dteCal)
local dt=Split(dteCal,'/')
return fhNewDate(dt[1],dt[2],dt[3]),tostring(dt[1])
end
---------------------------------------
-- Function: IsToday checks Calender date for today
---------------------------------------
function IsToday(dteCal)
return dte_Today.value==dteCal.value
end
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
-------------------------------------------------------
-- Welcome Dialog
-------------------------------------------------------
local chk_hasUsed=iup.toggle{title = "Show this screen next time", value="OFF"}
local btn_OKW = iup.button{name='ok', title='OK'}
local btn_welHelp = iup.button {name='welHelp', title='Help'}
function chk_hasUsed:action(t,i,v)
if t==1 then
hasUsed="No"
else
hasUsed="Yes"
end
end
function btn_OKW:action()
res=self.name
return iup.CLOSE
end
function btn_welHelp:action()
Help()
end
---------------------------------------------------
--Welcome Dialog
-------------------------------------------------------
function Welcome()
hasUsed="Yes"
txt="Thank you for using "..plugIn .."\n\n"
txt=txt.."To cater for different screen resolutions, there is a scroll bar for the certificate details\n"
txt=txt.."By changing the size of the form (dragging down at the bottom of the form), more fields\n"
txt=txt.."will become visible until the scroll bar disappears (if your screen supports that resolution)\n"
txt=txt.."When you save a certificate, the current resolution of the screen is preserved for next time you run.\n"
txt=txt..""
txt=txt.."Help for this plugin can be shown by pressing the help key in the main (or this) screen\n\n"
txt=txt.."For further support please post in the relevant Family Historian User Group forum\n"
txt=txt.."or on the page for this plugin in the Family Historian store\n"
txt=txt.."where the plugin author will answer your questions\n"
txt=txt.."which can be supplemented with screenshots if necessary.\n\n"
txt=txt.."Links to these sites are available on the help page for this plugin\n\n"
dlgWel = iup.dialog{
iup.vbox{
iup.hbox{iup.label{title=txt}},
iup.hbox{iup.label{title=''},chk_hasUsed},
iup.hbox{btn_OKW,btn_welHelp;padding='10',gap='5'}
;padding='5',gap='5',nmargin='20x20'
},
title=plugIn..' welcome ',padding='10',gap='5', size='500',
close_cb=function() res='closed' return iup.CLOSE end}
dlgWel:show() -- Show the dialog
iup.MainLoop() -- Process the dialog
dlgWel:destroy() -- Clean up the dialog, note all dialog controls are destroyed as well
fhSetIniFileValue(iniFile, "Defaults", "Welcome", "text",hasUsed)
end
---------------------------------------------------
--Help Dialog
-------------------------------------------------------
local btn_OKH = iup.button{name='ok', title='OK'}
function btn_OKH:action()
res=self.name
return iup.CLOSE
end
function Help()
local txt_Help = iup.text{name='Help',expand='HORIZONTAL',multiline='YES',visiblelines=20}
txt_Help.value= help
local txt="For further support please post in the relevant Family Historian User Group forum or on the page for this plugin in the Family Historian store\n"
txt=txt.."where the plugin author will answer your questions which can be supplemented with screenshots if necessary."
txt=txt.."Links to these sites are below\n\n"
local resHelp="To cater for different screen resolutions, there is a scroll bar for the certificate details\n"
resHelp=resHelp.."By changing the size of the form (dragging down at the bottom of the form), more fields\n"
resHelp=resHelp.."will become visible until the scroll bar disappears (if your screen supports that resolution)\n"
resHelp=resHelp.."When you save a certificate, the current resolution of the screen is preserved for the next time you run.\n"
dlgHelp = iup.dialog{
iup.vbox{
iup.hbox{iup.label{title='',size='10'},txt_Help},
iup.hbox{iup.label{title=''}},
iup.hbox{iup.label{title=resHelp}},
iup.hbox{iup.link{url="https://pluginstore.family-historian.co.uk/page/plugin/Simple-Marriage-Certificate",title="A User Guide may be available in Family Historian Plugin store"}},
iup.hbox{iup.label{title=txt}},
iup.hbox{iup.link{url="https://pluginstore.family-historian.co.uk/page/plugin/Simple-Marriage-Certificate",title="Family Historian Plugin store"}},
iup.hbox{iup.link{url="https://www.fhug.org.uk/forum/viewtopic.php?t=22976",title="Family Historian User Group forums"}},
iup.hbox{btn_OKH;padding='10',gap='5'}
;padding='5',gap='5',nmargin='20x20'
},
title=plugIn..' help ',padding='10',gap='5', size='500',
close_cb=function() res='closed' return iup.CLOSE end}
dlgHelp:show() -- Show the dialog
iup.MainLoop() -- Process the dialog
dlgHelp:destroy() -- Clean up the dialog, note all dialog controls are destroyed as well
end
main();
--[[
@Title: Simple Marriage Certificate
@Type: Standard
@Author: [Norman Martin]
@Version: 1.1
@Keywords:
@LastUpdated: 14 April 2024
@Licence: This plugin is copyright (c) Norman Martin 2024 and contributors, and is licensed under the MIT License
which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence)
@Description: Designed to work with 'Civil Registration Certificate' Source Template from the Essentials collection,
it will record the details of a marriage certificate, for the current individual, based on the format of the
England and Wales Marriage Certificate/Parish Register since 1837.
Where the information is provided, it will also the residence and occupation of the husband,
and the occupations of their respective fathers at the time of the marriage.
For further support please post in the appropriate Family Historian User Group forums (FHUG) topic or a reply at the end of this download page,
where the plugin author will answer your questions which can be supplemented with screenshots if necessary.
@changes:
1.2 Added Vertical Scroll bar for certificate deatils to cater for different screen resolutions.
1.1 Amended Help and Support Options
]]
local help=[[
This plugin records a Marriage Certificate based on the format of the England and Wales Marriage Certificate/Parish Register since 1837.
It also creates of marriage, occupation and residence facts. To ensure consistency, it uses the Civil Registration Certificate Template
for the source.
Prerequisites
Before it can be used, the "Civil Registration Certificate" template from the Essentials collection
must have already been added to the project. This can be done by selecting Tools>Source Template Definitions
and then highlight the template(s) and add to project.
This plugin does NOT create any individuals. Before it is called, It requires that a person is first selected
and that that person is married.
Any fathers should be created before the plugin is called, as any name changed on the form will be considered as information
printed on the certificate (text from source).
To avoid replication of input, the following fields are saved to be displayed next time the plugin is used:
Region, Repository, Assessment, Image Directory and Media Directory.
The Region is a dropdown list of Regions declared in the source template; Repository is a dropdown list of Repositories you have set up;
and Assessment is a dropdown list of valid assessments for the source.
Image Directory is the windows directory where the marriage certificate image can be found. It can be populated by typing the directory
name in manually, or found by pressing the 'Image Directory' button to the left of the field and showing a Windows Folder Dialog screen.
Media Directory is where the image of the Marriage Certificate will be saved. It can be populated in the same method for the
Image Directory. Note you can create the appropriate media directory in the Windows Folder Dialog screen.
Form Fields
Region (Required):- this is a list of Regions declared in the source template
Repository : - this is a list of Repositories you have already set up
Where Married : - Address where marriage took place e.g. Parish Church (if known)
Marriage Place (Required) : Place married - either select from drop down for existing place or type new place
which will be added as a new place
Entry Number: - Entry number of certificate (if known)
Date of Marriage (Required): - Date marriage took place
Name and Surname: -Pre selected on loading form - can be amended
Age : -Age when married (can be text e.g. Full Age)
Condition : - Dropdown list of condition (e.g. Bachelor, Spinster etc)
Rank or Profession: - Description of job (if known)
Residence at time of marriage: - Address of husband/wife living when married (if known)
Place : - Place husband/wife were living (if known)
Fathers name and surname: - Pre selected on loading form - can be amended
Rank of Profession (father): - Description of job (if known)
Rites and Ceremonies : - if stated (e.g. Established Church)
Marriage Type : - Dropdown list of marriage types (e.g. After Banns, By Licence etc)
In the Presence of : - List of witnesses to marriage
Married By (Required) : - Name of person performing the marriage
Assessment : - Dropdown list of valid assessments
Image Directory : - Directory to initiate search for image of certificate
Media Directory (Required): - Directory where image will be saved
As Source : - Dropdown list to determine name given to file when saved in the media directory
Options are As Source - filename same as source title
As Filename - filename same as original filename
My Choice - type your own filename in Image File field
Media : - Button to invoke windows file dialog to identify certificate image to be copied
Image File (Required): - name of media file to be created
Status : - status of form - e.g. errors or certificate saved
When you press the save button, the form is validated and any errors reported in the status bar.
If the action is successful, then the appropriate message is shown in that status bar.
When the certificate is saved, the ini file is updated to retain the Region, Repository, Assessment, Image Directory
and Media Directory fields.
Saving a Certificate will create a source record for the marriage certificate and create a formatted 'text from source'
and a link to a newly created media record. The source record is linked to the Marriage Fact.
The text written to the ‘text from source’ contains the values derived from the form as you have entered them.
This text can later be amended in the Citation record in Family Historian to correct any textual errors.
If the information has been provided, then the appropriate occupation and residence facts are created and linked to the source record.
These can be for the husband, wife and their fathers (occupation only). Age will only saved as a text if a valid age (e.g. 25) is entered.
You will need to press the Exit button, after saving, to exit the form and return back to Family Historian.
]]
-- << Comment in the next 2 lines if you need to use IUP >>
require("iuplua");
iup.SetGlobal("CUSTOMQUITMESSAGE","YES");
fh = require("fhUtils");
fhfu =require("fhFileUtils")
local plugIn="Simple Marriage Certificate" -- plugin name
local hasUsed="No" -- variable to decide to show welcome screen
local dlgSize="440x350"
fhInitialise(7); -- implies users will need version 7 as a minimum; change if that is not the case
local iniFile=""
local templateID=-1
local currPtr = fhNewItemPtr()
local ptrFamily=fhNewItemPtr();
local husbandPtr = fhNewItemPtr()
local wifePtr = fhNewItemPtr()
local husbandFatherPtr = fhNewItemPtr()
local wifeFatherPtr = fhNewItemPtr()
local curPerson=""
local curDates=""
local ptrTemplate=fhNewItemPtr()
local ptrRepos=fhNewItemPtr()
local region=""
local type="Marriage"
local assessment=""
local address=""
local source=-1
local haveCitation=false
local Places={}
local Families={}
local selFile=""
-------------------------------------------------------
-- Define Dialog Fields
-------------------------------------------------------
local color = {error = '255 200 200',red = '255 0 0',green = '0 128 0', clear='255 255 255'}
local dte_Today = iup.datepick{name='TodaysDate',size='1'}
local lst_Region = iup.list{name='Region',expand='HORIZONTAL', dropdown="YES"}
local lst_Repos = iup.list{name='Repository',expand='HORIZONTAL', dropdown="YES"}
local txt_Address = iup.text{name='Address',expand='HORIZONTAL' }
local lst_MarriagePlace = iup.list{name='MarriagePlace',expand='HORIZONTAL',editbox='YES', dropdown="NO",visiblelines=3}
local txt_EntryNo = iup.text{name='EntryNo',expand='HORIZONTAL' }
local dte_Marriagedate = iup.datepick{name='MarriageDate',expand='HORIZONTAL'}
local txt_Husband = iup.text{name='Husband',size='150' }
local txt_Wife = iup.text{name='Wife',size='150'}
local txt_HusbandAge = iup.text{name='HusbandAge',size='150' }
local txt_WifeAge = iup.text{name='WifeAge',size='150' }
local lst_HusbandCond = iup.list{name='HusbandCond',size='150', dropdown="YES" }
local lst_WifeCond = iup.list{name='WifeCond',size='150', dropdown="YES"}
local txt_HusbandOcc = iup.text{name='HusbandOcc',size='150' }
local txt_WifeOcc = iup.text{name='WifeOcc',size='150'}
local txt_HusbandAddress = iup.text{name='HusbandAddress',size='150'}
local txt_WifeAddress = iup.text{name='WifeAddress',size='150'}
local lst_HusbandPlace = iup.list{name='HusbandPlace',size='150',editbox='YES', dropdown="NO",visiblelines=3}
local lst_WifePlace = iup.list{name='WifePlace',size='150',editbox='YES', dropdown="NO",visiblelines=3}
local txt_HusbandFather = iup.text{name='HusbandFather',size='150' }
local txt_WifeFather = iup.text{name='WifeFather',size='150'}
local txt_HusbandFatherOcc = iup.text{name='HusbandFatherOcc',size='150' }
local txt_WifeFatherOcc = iup.text{name='WifeFatherOcc',size='150' }
local txt_Rites = iup.text{name='Rites',expand='HORIZONTAL' }
local lst_MarriageType = iup.list{name='MarriageType',expand='HORIZONTAL', dropdown="YES"}
local txt_Informant = iup.text{name='Informant',expand='HORIZONTAL', multiline='YES',visiblelines=2}
local lst_Assessment = iup.list{name='Assessment',expand='HORIZONTAL', dropdown="YES"}
local txt_Registrar = iup.text{name='Notes',expand='HORIZONTAL'}
local lab_message = iup.label{title=' ',fgcolor=color.red, expand='HORIZONTAL'}
local lab_husband = iup.label{title='Husband ',size='150'}
local lab_wife = iup.label{title='Wife ',size='150'}
local inp_img_dir = iup.text{name='ImageDir',expand='HORIZONTAL' }
local inp_Media_dir = iup.text{name='MediaDir', expand='HORIZONTAL', }
local inp_name = iup.text{Name='Filter', expand='HORIZONTAL',readonly="YES" }
local inp_file_list = iup.label{name='FileList',expand="HORIZONTAL", }
local lst_name = iup.list{name='Filename',"As Source","As Filename","My Choice",value=1; dropdown="YES"}
local lab_Mess = iup.label{title='Please select a file to select the image to copy ',fgcolor=color.blue, expand='HORIZONTAL'}
local bt_Save = iup.button{name='save', title='Save'}
local btn_Cancel = iup.button{name='cancel', title='Cancel'}
local btn_Media = iup.button{name='source', title='Media'}
local btn_help = iup.button {name='help', title='Help'}
local btn_mediaDir=iup.button{name='MediaDir', title='Media Directory>>'}
local btn_imageDir=iup.button{name='ImageDir', title='Image Directory>>'}
local info_Mess = iup.label{title='---------------Marriage Certificate Details-------------------',fgcolor=color.blue, expand='HORIZONTAL'}
local image_Mess = iup.label{title='----------------Marriage Certificate File--------------------',fgcolor=color.blue, expand='HORIZONTAL'}
function main()
local iniDir=fhGetContextInfo("CI_PROJECT_DATA_FOLDER").."\\Plugin Data\\"
-- check that plugin data folder exists
if not fhfu.folderExists(iniDir) then
fhfu.createFolder (iniDir)
end
iniFile=fhGetContextInfo("CI_PROJECT_DATA_FOLDER").."\\Plugin Data\\"..fhGetContextInfo("CI_PLUGIN_NAME")..".dat"
hasUsed=fhGetIniFileValue(iniFile, "Defaults", "Welcome", "text")
dlgSize=fhGetIniFileValue(iniFile, "Defaults", "Dialog Size", "text",dlgSize)
-- do I need to display welcome screen
if hasUsed~="Yes" then
Welcome()
end
local ptrParents=fhNewItemPtr();
templateID=FindTemplate('Civil Registration Certificate')
-- check that template exists
if templateID~=-1 then
--Try to get the Current Individual, Can't continue if not selected
currPtr=fh.getCurrentIndividual ()
if currPtr:IsNotNull() then
curPerson=fhGetItemText(currPtr,'INDI.NAME:GIVEN_ALL')..' '
curDates=fhGetItemText(currPtr,'INDI.BIRT.DATE')..' - '..fhGetItemText(currPtr,'INDI.DEAT.DATE')
-- get husband and wife
ptrFamily:MoveTo(currPtr, "INDI.FAMS")
if ptrFamily:IsNull() then
fhMessageBox("No marriage exists for person selected")
else
ptrFamily = fhGetValueAsLink(ptrFamily)
husbandPtr=fhGetValueAsLink(fhGetItemPtr(ptrFamily,'~.HUSB'))
wifePtr=fhGetValueAsLink(fhGetItemPtr(ptrFamily,'~.WIFE'))
curPerson=curPerson..fhGetItemText(husbandPtr,'INDI.NAME:SURNAME')
-- get fathers
if husbandPtr:IsNotNull() then
ptrParents:MoveTo(husbandPtr, "INDI.FAMC")
if ptrParents:IsNotNull() then
ptrParents = fhGetValueAsLink(ptrParents)
husbandFatherPtr=fhGetValueAsLink(fhGetItemPtr(ptrParents,'~.HUSB'))
end
end
if wifePtr:IsNotNull() then
ptrParents:MoveTo(wifePtr, "INDI.FAMC")
if ptrParents:IsNotNull() then
ptrParents = fhGetValueAsLink(ptrParents)
wifeFatherPtr=fhGetValueAsLink(fhGetItemPtr(ptrParents,'~.HUSB'))
end
end
-- show dialog screen
MainDialog()
end
else
fhMessageBox("No person selected")
end
else
fhMessageBox("Requires Civil Registration Index source template from the Essentials collection")
end
end
-------------------------------------------------------
-- identify media record
-------------------------------------------------------
function btn_Media:action()
res=self.name
-- validate form
selFile=ListFiles(inp_img_dir.value)
inp_file_list.title = selFile
ShowFilename()
end
-------------------------------------------------------
-- Select media directory from window dialog
-------------------------------------------------------
function btn_mediaDir:action()
local dirName=""
res=self.name
-- get directory name
dirName=ListDir(true)
if dirName~="" then
inp_Media_dir.value=dirName
end
end
-------------------------------------------------------
-- Select image directory from window dialog
-------------------------------------------------------
function btn_imageDir:action()
local dirName=""
res=self.name
-- get directory name
dirName=ListDir(false)
if dirName~="" then
inp_img_dir.value=dirName
end
end
-------------------------------------------------------
-- show help screen
-------------------------------------------------------
function btn_help:action()
Help()
end
function lst_name:action(t,i,v)
if i==3 then
inp_name.readonly="NO"
else
inp_name.readonly="YES"
end
ShowFilename()
end
-------------------------------------------------------
-- validate dialog and close screen if valid
-------------------------------------------------------
function bt_Save:action()
-- validate
lab_message.title = ''
-- validate form
if lst_Region.value=='0' then
lab_message.title = 'No region selected'
lst_Region.bgcolor = color.error
elseif lst_MarriagePlace.value=='' then
lab_message.title = 'No Marriage Place selected'
lst_MarriagePlace.bgcolor = color.error
elseif IsToday(dte_Marriagedate) then
lab_message.title = 'No Marriage Date selected'
dte_Marriagedate.bgcolor = color.error
elseif txt_Registrar.value=='' then
lab_message.title = 'No celebrant selected'
txt_Registrar.bgcolor = color.error
elseif inp_Media_dir.value=='' then
lab_message.title = 'Please provide a media directory to copy file to'
inp_Media_dir.bgcolor = color.error
elseif inp_file_list.title=='' then
lab_message.title = 'No media file selected'
inp_file_list.bgcolor = color.error
elseif inp_name.value=='' and inp_name.readonly=="NO" then
lab_message.title = 'No filename for image file'
elseif selFile=='' then
lab_message.title = 'No image selected'
else
SaveEntry()
end
end
function btn_Cancel:action()
local exit=true
if btn_Cancel.title=="Cancel" then
res = fhMessageBox("Do you wish to cancel saving this certificate?", "MB_YESNO", "MB_ICONQUESTION")
if res == "No" then
exit=false
dlg:show()
end
end
if exit then
return iup.CLOSE
end
end
-- << insert additional functions here >>
----------------------------------------------------
-- Function: MainDialog - display dialog
-- This is the Main Dialog Screen
---------------------------------------------------
function MainDialog()
-------------------------------------------------------
-- Dialog field actions
-------------------------------------------------------
function Exit()
return iup.CLOSE
end
dlg = iup.dialog{
iup.vbox{
iup.hbox{iup.label{title='Region',size='140'},dte_Today,lst_Region},
iup.hbox{iup.label{title='Repository',size='140'},lst_Repos},
iup.hbox{iup.label{title='',size='140'},info_Mess},
iup.scrollbox{
iup.vbox{
iup.hbox{iup.label{title='Where Married',size='140'},txt_Address},
iup.hbox{iup.label{title='Marriage Place',size='140'}, lst_MarriagePlace},
iup.hbox{iup.label{title='Entry Number',size='140'},txt_EntryNo},
iup.hbox{iup.label{title='Date of Marriage',size='140'},dte_Marriagedate},
iup.hbox{iup.label{title=' ',size='140'},lab_husband,lab_wife,gap='5'},
iup.hbox{iup.label{title='Name and Surname',size='140'},txt_Husband,txt_Wife,gap='5'},
iup.hbox{iup.label{title='Age',size='140'},txt_HusbandAge,txt_WifeAge,gap='5'},
iup.hbox{iup.label{title='Condition',size='140'},lst_HusbandCond,lst_WifeCond,gap='5'},
iup.hbox{iup.label{title='Rank or Profession',size='140'},txt_HusbandOcc,txt_WifeOcc,gap='5'},
iup.hbox{iup.label{title='Residence at time of marriage',size='140'},txt_HusbandAddress,txt_WifeAddress,gap='5'},
iup.hbox{iup.label{title='Place',size='140'},lst_HusbandPlace,lst_WifePlace,gap='5'},
iup.hbox{iup.label{title='Fathers Name and Surname',size='140'},txt_HusbandFather,txt_WifeFather,gap='5'},
iup.hbox{iup.label{title='Rank or Profession (Father)',size='140'},txt_HusbandFatherOcc,txt_WifeFatherOcc,gap='5'},
iup.hbox{iup.label{title='Rites and Ceremonies ',size='140'}, txt_Rites},
iup.hbox{iup.label{title='Marriage Type',size='140'}, lst_MarriageType},
iup.hbox{iup.label{title='In the Prescence of',size='140'}, txt_Informant},
iup.hbox{iup.label{title='Married by',size='140'},txt_Registrar},
iup.hbox{iup.label{title='Assessment',size='140'}, lst_Assessment},
},
canfocus = "NO",
scrollbar = "VERTICAL",
xmax = "0",
dy = "334",
ymax = "583",
wheeldropfocus = "YES",
},
iup.hbox{iup.label{title='',size='140'},image_Mess},
iup.hbox{btn_imageDir,iup.label{title='',size='1'},inp_img_dir},
iup.hbox{btn_mediaDir,iup.label{title='',size='1'},inp_Media_dir},
iup.hbox{iup.label{title=''},lst_name,size='70',inp_name,gap='25'},
iup.hbox{btn_Media,lab_Mess},
iup.hbox{iup.label{title='Image File',size='70'}, inp_file_list},
iup.hbox{iup.label{title=' ',size='140'}},
iup.label{title='Status'},lab_message,
iup.hbox{bt_Save,iup.label{title='',size='120'},btn_Cancel,iup.label{title='',size='120'},btn_help;padding='10',gap='5'}
;padding='5',gap='5',nmargin='20x20'
},
title='Add Marriage Certificate for '..curPerson..' '..curDates,padding='10',gap='5', size='500',
close_cb=function() res='closed' return iup.CLOSE end}
-- populate list with defaults
PopulateList(lst_Region,GetRegions(templateID))
PopulateList(lst_Repos,GetRepositories())
PopulateList(lst_MarriagePlace,fh.createPlaceList())
PopulateList(lst_HusbandPlace,fh.createPlaceList())
PopulateList(lst_WifePlace,fh.createPlaceList())
ListCondition(lst_HusbandCond)
ListCondition(lst_WifeCond)
ListAssessments(lst_Assessment)
ListMarriageTypes(lst_MarriageType)
inp_file_list.title=''
-- populate name
txt_Husband.value=fhGetItemText(husbandPtr,'INDI.NAME')
txt_Wife.value=fhGetItemText(wifePtr,'INDI.NAME')
txt_HusbandFather.value=fhGetItemText(husbandFatherPtr,'INDI.NAME')
txt_WifeFather.value=fhGetItemText(wifeFatherPtr,'INDI.NAME')
-- read ini file and populate accordingly
inp_img_dir.value=fhGetIniFileValue(iniFile, "Directories", "Images", "text")
inp_Media_dir.value=fhGetIniFileValue(iniFile, "Directories", "Marriage", "text")
region=fhGetIniFileValue(iniFile, "Defaults", "Region", "text","")
lst_Region.valuestring=region
repos=fhGetIniFileValue(iniFile, region, "Repository", "text",'')
lst_Repos.valuestring=repos
assessment=fhGetIniFileValue(iniFile, region, "Assessment", "text",'')
lst_Assessment.valuestring=assessment
dlg:show() -- Show the dialog
-- size the dialog screen appropriately
dlg.size=dlgSize
iup.Map(dlg)
iup.MainLoop() -- Process the dialog
dlg:destroy() -- Clean up the dialog, note all dialog controls are destroyed as well
end
----------------------------------------------------
-- Function: SaveEntry - Saves ini file settings
-- and creates citation
-- then updates events and saves citation
---------------------------------------------------
function SaveEntry()
local txt=""
local region=lst_Region.valuestring
local ptrLink =fhNewItemPtr();
local ptrMarriage=fhNewItemPtr();
local ptrTextFromSource=fhNewItemPtr();
local ptrInfo =fhNewItemPtr();
local dtMyDate,yr
-- save ini file settings
fhSetIniFileValue(iniFile, "Defaults", "Dialog Size", "text",dlg.Size)
fhSetIniFileValue(iniFile, "Defaults", "Region", "text",region)
fhSetIniFileValue(iniFile, region, "Assessment", "text",lst_Assessment.valuestring)
fhSetIniFileValue(iniFile, region, "Repository", "text",lst_Repos.valuestring)
if CheckDirectory(inp_img_dir.value) then
fhSetIniFileValue(iniFile, "Directories", "Images", "text",inp_img_dir.value)
end
if CheckDirectory(inp_Media_dir.value) then
fhSetIniFileValue(iniFile, "Directories", "Marriage", "text",inp_Media_dir.value)
end
lab_message.title = ''
-- create a templated source record
sourcePtr= fhCreateItem("SOUR")
ptrLink = fhCreateItem("_SRCT", sourcePtr)
fhSetValueAsLink(ptrLink, ptrTemplate)
ptrLink = fhCreateItem("TITL", sourcePtr)
-- add fields
AddInfo(sourcePtr, '~NM-PRINCIPAL', txt_Husband.value)
AddInfo(sourcePtr, '~NM-PRINCIPAL_2', txt_Wife.value)
AddInfo(sourcePtr, '~EN-TYPE', 'Marriage')
AddInfo(sourcePtr, '~EN-REGION', region)
dtMyDate,yr=CalenderToDate(dte_Marriagedate.value)
AddInfoAsDate(sourcePtr, '~DT-DATE', dtMyDate)
AddInfo(sourcePtr, '~PL-LOCATION', lst_MarriagePlace.value)
AddInfo(sourcePtr, '~AD-ADDRESS', txt_Address.value)
AddInfo(sourcePtr, '~TX-REFERENCE', txt_EntryNo.value)
if lst_Repos.valuestring~=nil then
ptrLink = fhCreateItem("~RP-REPOSITORY", sourcePtr)
fhSetValueAsLink(ptrLink, FindRepository(lst_Repos.valuestring))
end
AddInfo(sourcePtr, 'TITL', 'Marriage certificate of '..fhGetItemText(sourcePtr,'~.~NM-PRINCIPAL')..' and '..fhGetItemText(sourcePtr,'~.~NM-PRINCIPAL_2')..', '..fhGetItemText(sourcePtr,'~.~DT-DATE'))
-- Create text from Source
AddTextFromSource(sourcePtr)
-- Add Media Record
if inp_name.value=='' then
inp_name.value=fhGetItemText(sourcePtr,'~.TITL')
end
filename= SaveImageFile(inp_file_list.title,inp_Media_dir.value, inp_name.value)
if filename~="" then
-- copied file , now create object
if CreateObject(sourcePtr,filename) ==false then
lab_message.title = 'Failed to link image to source'
end
else
lab_message.title = 'Failed to copy file'
end
-- create / update Marriage event
ptrMarriage=fhGetItemPtr(ptrFamily,'~.MARR')
if ptrMarriage:IsNull() then
-- create Marriage Event
ptrMarriage = fhCreateItem("MARR", ptrFamily)
end
AddInfo(ptrMarriage, 'DATE', fhGetItemText(sourcePtr,'~.~DT-DATE'))
AddInfo(ptrMarriage, "PLAC", lst_MarriagePlace.value)
AddInfo(ptrMarriage, "ADDR", txt_Address.value)
ptrLink = fhCreateItem("SOUR", ptrMarriage)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
-- add ages
if txt_HusbandAge.value ~="" then
ptrInfo= fhCreateItem("HUSB", ptrMarriage)
AddInfo(ptrInfo, 'AGE', txt_HusbandAge.value)
end
if txt_WifeAge.value ~="" then
ptrInfo= fhCreateItem("WIFE", ptrMarriage)
AddInfo(ptrInfo, 'AGE', txt_WifeAge.value)
end
-- add witness
if txt_Informant.value ~="" then
local sWitness=Split(txt_Informant.value,'\n')
for i,v in ipairs(sWitness) do
if v ~="" then
ptrInfo= fhCreateItem("_SHAN", ptrMarriage)
fhSetValueAsText(ptrInfo, v)
AddInfo(ptrInfo, 'ROLE', "Witness")
ptrLink = fhCreateItem("SOUR", ptrInfo)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
end
end
-- Add Residence
if lst_HusbandPlace.value ~="" then
ptrOcc=fhCreateItem("RESI", husbandPtr)
AddInfo(ptrOcc, "ADDR", txt_HusbandAddress.value)
AddInfo(ptrOcc, "PLAC", lst_HusbandPlace.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
if txt_HusbandAge.value ~="" then
AddInfo(ptrOcc, 'AGE', txt_HusbandAge.value)
end
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if lst_WifePlace.value ~="" then
ptrOcc=fhCreateItem("RESI", wifePtr)
AddInfo(ptrOcc, "ADDR", txt_WifeAddress.value)
AddInfo(ptrOcc, "PLAC", lst_WifePlace.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
if txt_WifeAge.value ~="" then
AddInfo(ptrOcc, 'AGE', txt_WifeAge.value)
end
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
-- add occupation(s)
if txt_HusbandOcc.value ~="" then
ptrOcc=fhCreateItem("OCCU", husbandPtr)
fhSetValueAsText(ptrOcc, txt_HusbandOcc.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
if txt_HusbandAge.value ~="" then
AddInfo(ptrOcc, 'AGE', txt_HusbandAge.value)
end
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if txt_WifeOcc.value ~="" then
ptrOcc=fhCreateItem("OCCU", wifePtr)
fhSetValueAsText(ptrOcc, txt_WifeOcc.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
if txt_WifeAge.value ~="" then
AddInfo(ptrOcc, 'AGE', txt_WifeAge.value)
end
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if txt_HusbandFatherOcc.value ~="" then
ptrOcc=fhCreateItem("OCCU", husbandFatherPtr)
fhSetValueAsText(ptrOcc, txt_HusbandFatherOcc.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if txt_WifeFatherOcc.value ~="" then
ptrOcc=fhCreateItem("OCCU", wifeFatherPtr)
fhSetValueAsText(ptrOcc, txt_WifeFatherOcc.value)
AddInfoAsDate(ptrOcc, "DATE", dtMyDate)
ptrLink = fhCreateItem("SOUR", ptrOcc)
AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
fhSetValueAsLink(ptrLink, sourcePtr)
end
if lab_message.title == '' then
lab_message.fgcolor=color.green
lab_message.title = 'Marriage Certificate Saved'
btn_Cancel.title="Exit"
end
end
-------------------------------------------------------
-- ListFiles - display windows file dialog screen to select image file
-- - passes default directory to windows dialog screen
-------------------------------------------------------
function ListFiles(defDir)
f, err = iup.GetFile(defDir.."/".."*.jpg;*.png")
if err == 1 then
iup.Message("New file", f)
elseif err == 0 then
return f
end
end
function ListDir(projectDir)
local dataDir=""
if projectDir then dataDir=fhGetContextInfo("CI_PROJECT_DATA_FOLDER") end
filedlg = iup.filedlg{directory=dataDir,dialogtype = "DIR", title = "Select Directory"}
iup.Popup(filedlg)
-- Gets file dialog status
status = filedlg.status
if status == "0" or status == "1" then
return filedlg.value
end
return ""
end
----------------------------------------------------
-- Function: ShowFilename - display new filename to copy to
---------------------------------------------------
function ShowFilename()
local path=""
local file=""
local extension=""
if lst_name.value=="1" then
-- display source name
inp_name.value=""
elseif lst_name.value=="2" then
path,file,extension = SplitFilename(selFile)
inp_name.value=string.gsub(file,"."..extension, "")
else
-- allow to overwrite
end
end
---------------------------------------
-- Function: SaveImageFile - copies source image file to media directory
-- renaming to source title if requested
-- returns filename to be written as object file
---------------------------------------
function SaveImageFile(fromFile,ToDirectory, Title)
local path=""
local file=""
local extension=""
local toFile=""
path,file,extension = SplitFilename(fromFile)
if fhfu.fileExists (fromFile) then
toFile=ToDirectory.."\\"..Title.."."..extension
if fhfu.fileExists (toFile) then
fhMessageBox("Source already has image added")
else
-- does directory exist
if CheckDirectory(ToDirectory) then
-- copy file to new directory changing its name
if fhfu.copyFile (fromFile, toFile, false) then
return string.gsub(toFile, fhGetContextInfo("CI_PROJECT_DATA_FOLDER").."\\", "")
end
end
end
end
return ""
end
---------------------------------------
-- Function: CreateObject - creates a new object
-- and links to source record
---------------------------------------
function CreateObject(SourcePtr,Filename)
local ptrObj= fhNewItemPtr()
local ptrFile= fhNewItemPtr()
local ptrLink= fhNewItemPtr()
local newFile=""
if SourcePtr:IsNotNull() then
-- now create object
ptrObj= fhCreateItem("OBJE")
ptrFile= fhCreateItem("FILE", ptrObj,true)
if ptrFile:IsNotNull() then
fhSetValueAsText(ptrFile,Filename)
AddInfo(ptrFile,"FORM",PictureFormat(Filename))
AddInfo(ptrFile,"TITL",fhGetItemText(SourcePtr,"SOUR.TITL"))
AddInfo(ptrObj,"_DATE",fhGetItemText(SourcePtr,"SOUR.~DT-DATE"))
AddInfo(ptrObj,"_KEYS","Picture")
-- now link object to source
ptrLink = fhCreateItem("OBJE", SourcePtr ) -- create a OBJE field
fhSetValueAsLink(ptrLink, ptrObj)
return true
end
end
return false
end
---------------------------------------
-- Function: AddTextFromSource
-- add source text in rich text format
---------------------------------------
function AddTextFromSource(SourcePtr)
local txt='Certified Copy of an Entry of Marriage\n'
local txtPtr=fhNewItemPtr();
local dtMyDate,yr=CalenderToDate(dte_Marriagedate.value)
local district=Split(lst_MarriagePlace.value ,',')
local rt = fhNewRichText() -- create a new rich text object
txt=txt..yr..' Marriage solemnized at '..txt_Address.value..'\n'
txt=txt..'of '..district[1]..' in the county of '..district[2]..' \n\n'
txt=txt..''
txt=txt..' No. | When Married. | Name and Surname. | Age. | Condition. | Rank or Profession. | Residence at the time of Marriage. | Fathers Name and Surname. | Rank or Profession of Father.
\n'
txt=txt..' '
txt=txt..' | '
txt=txt..' | '
txt=txt..txt_Husband.value..' | '
txt=txt..txt_HusbandAge.value..' | '
txt=txt..lst_HusbandCond.valuestring..' | '
txt=txt..txt_HusbandOcc.value..' | '
txt=txt..txt_HusbandAddress.value..'\n'..lst_HusbandPlace.value..' | '
txt=txt..txt_HusbandFather.value..' | '
txt=txt..txt_HusbandFatherOcc.value..' | '
txt=txt..'
'
txt=txt..' '
txt=txt..txt_EntryNo.value..' | '
txt=txt..dtMyDate:GetDisplayText()..' | '
txt=txt..txt_Wife.value..' | '
txt=txt..txt_WifeAge.value..' | '
txt=txt..lst_WifeCond.valuestring..' | '
txt=txt..txt_WifeOcc.value..' | '
txt=txt..txt_WifeAddress.value..'\n'..lst_WifePlace.value..' | '
txt=txt..txt_WifeFather.value..' | '
txt=txt..txt_WifeFatherOcc.value..' | '
txt=txt..'
'
txt=txt..'
'
txt=txt..'\nMarried in the '..txt_Address.value..' according to the Rites and Ceremonies of the '..txt_Rites.value..' '..lst_MarriageType.valuestring..' by me.\n'
txt=txt..''
txt=txt..''
txt=txt..'This marriage was solemnized between us, | '..txt_Husband.value..'\n'..txt_Wife.value..' | '
txt=txt..' In the presence of us, | '..txt_Informant.value..' | '
txt=txt..txt_Registrar.value
txt=txt..'
'
txt=txt..'
'
txtPtr= fhCreateItem("TEXT", sourcePtr)
rt:SetText(txt)
fhSetValueAsRichText(txtPtr , rt) -- set value of the note using passed in parameter
end
---------------------------------------
-- Function: AddInfo - add info to fact, updating if fact exists
---------------------------------------
function AddInfo(ptr, Type, Value)
if Type and Value then
local infoPtr=fhGetItemPtr(ptr,'~.'..Type)
if infoPtr:IsNull() then
infoPtr= fhCreateItem(Type, ptr)
end
fhSetValueAsText(infoPtr, Value)
end
end
---------------------------------------
-- Function: AddInfoAsDate - add info to fact, updating if fact exists
---------------------------------------
function AddInfoAsDate(ptr, Type, Value)
if Type and Value then
local infoPtr=fhGetItemPtr(ptr,'~.'..Type)
if infoPtr:IsNull() then
infoPtr= fhCreateItem(Type, ptr)
end
fhSetValueAsDate(infoPtr, Value)
end
end
---------------------------------------------------
--function FindTemplate(template name)
-------------------------------------------------------
function FindTemplate(tName)
local ptr=fhNewItemPtr();
ptr:MoveToFirstRecord('_SRCT')
while ptr:IsNotNull() do
if fhGetItemText(ptr,'~.NAME')==tName then
ptrTemplate=ptr
return fhGetRecordId(ptr)
end
ptr:MoveNext()
end
return -1
end
---------------------------------------------------
--function FindRepository(Repository name)
-------------------------------------------------------
function FindRepository(tName)
local ptr=fhNewItemPtr();
ptr:MoveToFirstRecord('REPO')
while ptr:IsNotNull() do
if fhGetItemText(ptr,'~.NAME')==tName then
ptrRepos=ptr
return ptr
end
ptr:MoveNext()
end
return -1
end
---------------------------------------
-- Function: GetRegions - returns table of regions for CRI
---------------------------------------
function GetRegions(ID)
local array={}
local ptrTemplate = fhNewItemPtr() -- declare pointer
local ptrFDef=fhNewItemPtr()
local strRegions=""
ptrTemplate:MoveToFirstRecord("_SRCT") -- point to the first record
while not ptrTemplate:IsNull() do
if fhGetRecordId(ptrTemplate)==ID then
-- loop through regions
ptrFDef= fhGetItemPtr(ptrTemplate,'~.FDEF')
while not ptrFDef:IsNull() do
if fhGetItemText(ptrFDef,'~.NAME')=='Region' then
-- found field definiton
strRegions =fhGetItemText(ptrFDef,'~.PROM')
return Split(strRegions,'|')
end
ptrFDef:MoveNext('SAME_TAG')
end
end
ptrTemplate:MoveNext()
end
return array
end
---------------------------------------
-- Function: GetRepositories - returns table of repositories
---------------------------------------
function GetRepositories()
local array={}
local ptrRepos = fhNewItemPtr() -- declare pointer
local strRepos=""
ptrRepos:MoveToFirstRecord("REPO") -- point to the first record
while not ptrRepos:IsNull() do
-- For each Repository Add the Name to the list
strRepos =fhGetItemText(ptrRepos,'REPO.NAME')
table.insert(array,strRepos )
ptrRepos:MoveNext()
end
return array
end
---------------------------------------
-- Function: ListAssessment - returns table of regions for CRI
---------------------------------------
function ListAssessments(l)
local array ={}
table.insert(array,'Unreliable')
table.insert(array,'Questionable')
table.insert(array,'Secondary information')
table.insert(array,'Primary information')
table.insert(array,'')
PopulateList(l,array)
end
---------------------------------------
-- Function: ListCondition - returns table of Marriage Status
---------------------------------------
function ListCondition(l)
local array ={}
table.insert(array,'Bachelor')
table.insert(array,'Spinster')
table.insert(array,'Widower')
table.insert(array,'Widow')
table.insert(array,'Divorced')
PopulateList(l,array)
end
---------------------------------------
-- Function: ListMarriageTypes - returns table of Marriage Types
---------------------------------------
function ListMarriageTypes(l)
local array ={}
table.insert(array,'After Banns')
table.insert(array,'By Banns')
table.insert(array,'By Certificate')
table.insert(array,'By Declaration')
table.insert(array,'By Licence')
table.insert(array,'By Publication')
PopulateList(l,array)
end
-------------------------------------------------------
-- PopulateList populates a dialog list with table values
-------------------------------------------------------
function PopulateList(l, tblVals)
local is_indexed = (rawget( tblVals, 1 ) ~= nil)
l.REMOVEITEM = "ALL"
if not is_indexed then
local i=1
for k, _ in pairs(tblVals) do
l[tostring(i)]=k
i=i+1
end
else
for i, v in ipairs(tblVals) do
l[tostring(i)]=v
end
end
end
---------------------------------------
-- Function: Split - splits a string by delimter
-- and returns a table of strings
---------------------------------------
function Split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, trim(match));
end
return result;
end
---------------------------------------
-- Function: trim - removes leading and trailing spaces
---------------------------------------
function trim(s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
---------------------------------------
-- Function: PictureFormat - returns format of image file
---------------------------------------
function PictureFormat(fromFile)
local path=""
local file=""
local extension=""
path,file,extension = SplitFilename(fromFile)
if string.upper(extension)=='JPG' then
return 'jpeg'
elseif string.upper(extension)=='TIF' then
return 'tiff'
end
return extension
end
---------------------------------------
-- Function: SplitFilename - Path, Filename, and Extension as 3 values
---------------------------------------
function SplitFilename(strFilename)
-- Returns the Path, Filename, and Extension as 3 values
if lfs.attributes(strFilename,"mode") == "directory" then
local strPath = strFilename:gsub("[\\/]$","")
return strPath.."\\","",""
end
strFilename = strFilename.."."
return strFilename:match("^(.-)([^\\/]-%.([^\\/%.]-))%.?$")
end
---------------------------------------
-- Function: CheckDirectory - checks that directory exits
---------------------------------------
function CheckDirectory(Directory)
if fhfu.folderExists(Directory) then
return true
else
-- create folder
if fhfu.createFolder(Directory) then
return true
end
end
return false
end
---------------------------------------
-- Function: trims a sting;
-- ensures that files do not have leading or trailing spaces
---------------------------------------
function trim(s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
---------------------------------------
-- Function: CalenderToDate returns a FH date from Calender date
-- yr is year from Calender date
---------------------------------------
function CalenderToDate(dteCal)
local dt=Split(dteCal,'/')
return fhNewDate(dt[1],dt[2],dt[3]),tostring(dt[1])
end
---------------------------------------
-- Function: IsToday checks Calender date for today
---------------------------------------
function IsToday(dteCal)
return dte_Today.value==dteCal.value
end
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
-------------------------------------------------------
-- Welcome Dialog
-------------------------------------------------------
local chk_hasUsed=iup.toggle{title = "Show this screen next time", value="OFF"}
local btn_OKW = iup.button{name='ok', title='OK'}
local btn_welHelp = iup.button {name='welHelp', title='Help'}
function chk_hasUsed:action(t,i,v)
if t==1 then
hasUsed="No"
else
hasUsed="Yes"
end
end
function btn_OKW:action()
res=self.name
return iup.CLOSE
end
function btn_welHelp:action()
Help()
end
---------------------------------------------------
--Welcome Dialog
-------------------------------------------------------
function Welcome()
hasUsed="Yes"
txt="Thank you for using "..plugIn .."\n\n"
txt=txt.."To cater for different screen resolutions, there is a scroll bar for the certificate details\n"
txt=txt.."By changing the size of the form (dragging down at the bottom of the form), more fields\n"
txt=txt.."will become visible until the scroll bar disappears (if your screen supports that resolution)\n"
txt=txt.."When you save a certificate, the current resolution of the screen is preserved for next time you run.\n"
txt=txt..""
txt=txt.."Help for this plugin can be shown by pressing the help key in the main (or this) screen\n\n"
txt=txt.."For further support please post in the relevant Family Historian User Group forum\n"
txt=txt.."or on the page for this plugin in the Family Historian store\n"
txt=txt.."where the plugin author will answer your questions\n"
txt=txt.."which can be supplemented with screenshots if necessary.\n\n"
txt=txt.."Links to these sites are available on the help page for this plugin\n\n"
dlgWel = iup.dialog{
iup.vbox{
iup.hbox{iup.label{title=txt}},
iup.hbox{iup.label{title=''},chk_hasUsed},
iup.hbox{btn_OKW,btn_welHelp;padding='10',gap='5'}
;padding='5',gap='5',nmargin='20x20'
},
title=plugIn..' welcome ',padding='10',gap='5', size='500',
close_cb=function() res='closed' return iup.CLOSE end}
dlgWel:show() -- Show the dialog
iup.MainLoop() -- Process the dialog
dlgWel:destroy() -- Clean up the dialog, note all dialog controls are destroyed as well
fhSetIniFileValue(iniFile, "Defaults", "Welcome", "text",hasUsed)
end
---------------------------------------------------
--Help Dialog
-------------------------------------------------------
local btn_OKH = iup.button{name='ok', title='OK'}
function btn_OKH:action()
res=self.name
return iup.CLOSE
end
function Help()
local txt_Help = iup.text{name='Help',expand='HORIZONTAL',multiline='YES',visiblelines=20}
txt_Help.value= help
local txt="For further support please post in the relevant Family Historian User Group forum or on the page for this plugin in the Family Historian store\n"
txt=txt.."where the plugin author will answer your questions which can be supplemented with screenshots if necessary."
txt=txt.."Links to these sites are below\n\n"
local resHelp="To cater for different screen resolutions, there is a scroll bar for the certificate details\n"
resHelp=resHelp.."By changing the size of the form (dragging down at the bottom of the form), more fields\n"
resHelp=resHelp.."will become visible until the scroll bar disappears (if your screen supports that resolution)\n"
resHelp=resHelp.."When you save a certificate, the current resolution of the screen is preserved for the next time you run.\n"
dlgHelp = iup.dialog{
iup.vbox{
iup.hbox{iup.label{title='',size='10'},txt_Help},
iup.hbox{iup.label{title=''}},
iup.hbox{iup.label{title=resHelp}},
iup.hbox{iup.link{url="https://pluginstore.family-historian.co.uk/page/plugin/Simple-Marriage-Certificate",title="A User Guide may be available in Family Historian Plugin store"}},
iup.hbox{iup.label{title=txt}},
iup.hbox{iup.link{url="https://pluginstore.family-historian.co.uk/page/plugin/Simple-Marriage-Certificate",title="Family Historian Plugin store"}},
iup.hbox{iup.link{url="https://www.fhug.org.uk/forum/viewtopic.php?t=22976",title="Family Historian User Group forums"}},
iup.hbox{btn_OKH;padding='10',gap='5'}
;padding='5',gap='5',nmargin='20x20'
},
title=plugIn..' help ',padding='10',gap='5', size='500',
close_cb=function() res='closed' return iup.CLOSE end}
dlgHelp:show() -- Show the dialog
iup.MainLoop() -- Process the dialog
dlgHelp:destroy() -- Clean up the dialog, note all dialog controls are destroyed as well
end
main();
Source:Simple-Marriage-Certificate-1.fh_lua