Replace Selected Source Citations.fh_lua--[[
@Title: Replace Selected Source Citations
@Type: Standard
@Author: Mike Tate
@Contributors:
@Version: 1.2
@Keywords:
@LastUpdated: 19 Dec 2020
@Licence: This plugin is copyright (c) 2020 Mike Tate & 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: Replace one Source Citation with another for chosen Citation criteria conditionally.
@V1.2: Confirm replacements; Root Record & Rec Id in Result Set; FH V7 Lua 3.5 IUP 3.28;
@V1.1: Minor update;
@V1.0: First published in Plugin Store;
]]
local strPluginName = "Replace Selected Source Citations 1.2" -- Update title and version number here
require("iuplua") -- To access GUI window builder
if fhGetAppVersion() > 5 then -- Cater for Unicode UTF-8 from FH Version 6 onwards
fhSetStringEncoding("UTF-8")
iup.SetGlobal("UTF8MODE","YES")
iup.SetGlobal("UTF8MODE_FILE","NO")
iup.SetGlobal("CUSTOMQUITMESSAGE","YES") -- Needed for IUP 3.28
end
if fhGetAppVersion() > 6 then unpack = table.unpack end -- Needed for Lua 5.3
function matches(strTxt,strFind,intInit) -- matches is plain text version of string.match()
local strMagic = "([%^%$%(%)%%%.%[%]%*%+%-%?])" -- UTF-8 replacement for "(%W)"
strFind = tostring(strFind or ""):gsub(strMagic,"%%%1") -- Hide magic pattern symbols
return tostring(strTxt or ""):match(strFind,tonumber(intInit))
end -- function matches
function GetRecord(index) -- Get old/new Source record choice
local ptrGet = nil
local strGet = ""
if index == -1 then
local tblGet = fhPromptUserForRecordSel("SOUR",1) -- Prompt for Source record
if #tblGet == 1 then
ptrGet = tblGet[1] -- Link to record
strGet = fhGetDisplayText(ptrGet) -- Name of record
end
end
return ptrGet,strGet
end -- function GetRecord()
function GetOld(dialog,index)
if index == iup.GETPARAM_MAP then -- Correct button labels needed for IUP 3.28 bug -- V1.2
dialog.Button1.Title = "Select Old Source"
dialog.Button2.Title = "Cancel Plugin"
end
ptrOld,strOld = GetRecord(index) -- Prompt for new Source record link & name
return 1
end -- function GetOld
function GetNew(dialog,index)
if index == iup.GETPARAM_MAP then -- Correct button labels needed for IUP 3.28 bug -- V1.2
dialog.Button1.Title = "Select New Source"
dialog.Button2.Title = "Cancel Plugin"
end
ptrNew,strNew = GetRecord(index) -- Prompt for new Source record link & name
return 1
end -- function GetNew
function GetOpt(dialog,index)
if index == iup.GETPARAM_MAP then -- Correct button labels needed for IUP 3.28 bug -- V1.2
dialog.Button1.Title = "Perform Replace"
dialog.Button2.Title = "Cancel Plugin"
end
return 1
end -- function paramAction
function Main()
if not iup.GetParam("Select Old Source Record",GetOld," Select the Source record that needs to be replaced.%t\n%u[Select Old Source,Cancel Plugin]")
or not ptrOld then return end
if not iup.GetParam("Select New Source Record",GetNew," Select the Source record to replace that old Source.%t\n%u[Select New Source,Cancel Plugin]")
or not ptrNew then return end
local tblForm = {} -- Format strings for iup.GetParam
local tblData = {} -- Parameter values for iup.GetParam
local tblTags = {} -- Data Ref Tags for Citation fields
local tblDel = {} -- Indices for delete & contains actions
local tblCon = {}
local intQuay = 0 -- Cater for 'Assessment' field
local arrQuay = {[0]="","Unreliable","Questionable","Secondary evidence","Primary evidence"}
local strQuay = "| "..table.concat(arrQuay,"|",0).."|" -- GetParam list is 0 based
local intRepl = 0
local strRepl = "Yes" -- Replacement confirmation -- V1.2
local function setTables(strForm,strData,strTags,tblAct) -- Set those lookup table to values below
table.insert(tblForm,strForm)
table.insert(tblData,strData)
table.insert(tblTags,strTags)
if tblAct then table.insert(tblAct,#tblForm) end -- List of indices for delete or contains actions
if intQuay == 0 and matches(strTags,"QUAY") then intQuay = #tblData end
if matches(strTags,"????") then intRepl = #tblData end -- V1.2
end -- local function setTables
setTables( "Old Source to be replaced: %s" , strOld , " " )
setTables( "'Assessment' field contains?%l"..strQuay, 0 , "~.QUAY" , tblCon )
setTables( "'Where within Source' contains: %s" , "" , "~.PAGE" , tblCon )
setTables( "'Text From Source' contains: %m" , "" , "~.DATA.TEXT" , tblCon )
setTables( "Local 'Note' field contains: %m" , "" , "~.NOTE2" , tblCon )
setTables( "If all conditions above match: %t" )
setTables( "New Source as replacement: %s" , strNew , " " )
setTables( "Delete 'Entry Date' field? %b" , 0 , "~.DATA.DATE" , tblDel )
setTables( "Delete 'Assessment' field? %b" , 0 , "~.QUAY" , tblDel )
setTables( "Delete 'Where within Source'? %b" , 0 , "~.PAGE" , tblDel )
setTables( "Delete 'Text From Source'? %b" , 0 , "~.DATA.TEXT" , tblDel )
setTables( "Delete local 'Note' field? %b" , 0 , "~.NOTE2" , tblDel )
setTables( "Confirm each replacement? %b" , 0 , "????" ) -- V1.2
setTables( "%u[Perform Replace, Cancel Plugin]" )
tblData = { iup.GetParam("Source Citation Options",GetOpt,table.concat(tblForm,"\n"),unpack(tblData)) }
if not tblData[1] then return end
table.remove(tblData,1) -- Align data with tables above
tblData[intQuay] = arrQuay[tblData[intQuay]] -- Convert 'Assessment' index to text
local tblRec = {} -- Result Set tables -- V1.2
local tblRid = {}
local tblRoot = {}
local tblItem = {}
local tblDate = {}
local tblQuay = {}
local tblPage = {}
local tblText = {}
local tblNote = {}
local tblType = {"INDI","FAM","NOTE","SOUR","REPO","SUBM","OBJE","_PLAC"} -- Record type tags with Citations
local ptrItem = fhNewItemPtr()
for intType, strType in ipairs(tblType) do -- Scan all record Types that may have Citations
ptrItem:MoveToFirstRecord(strType)
while ptrItem:IsNotNull() do
if fhGetTag(ptrItem) == "SOUR" -- Search items until Source Citation found
and fhHasParentItem(ptrItem) then
if ptrOld:IsSame(fhGetValueAsLink(ptrItem)) then -- Cited Source record matches
local isCon = true
for _, intCon in ipairs (tblCon) do
if not matches(fhGetItemText(ptrItem,tblTags[intCon]),tblData[intCon]) then
isCon = false -- Field does not contain required text
break
end
end
if isCon then -- All fields also match
local ptrRoot = fhNewItemPtr()
ptrRoot:MoveToParentItem(ptrItem) -- Obtain root for Citation -- V1.2
local strRoot = fhGetDisplayText(ptrRoot)
ptrRoot:MoveToRecordItem(ptrItem) -- Obtain record of Citation -- V1.2
local strRecd = fhGetDisplayText(ptrRoot)
if tblData[intRepl] > 0 then -- Confirm each replacement? -- V1.2
strRepl = fhMessageBox("\nIn record "..strRecd.." \ndo you want to replace Source Citation for \n"..strRoot,"MB_YESNOCANCEL")
end
if strRepl == "Yes" then
local isOK = fhSetValueAsLink(ptrItem,ptrNew) -- So replace this record with new Source record
for _, intDel in ipairs (tblDel) do -- Delete chosen fields
if tblData[intDel] == 1 then
local isOK = fhDeleteItem(fhGetItemPtr(ptrItem,tblTags[intDel]))
end
end
table.insert(tblRec ,ptrRoot:Clone()) -- Update Result Set -- V1.2
table.insert(tblRid ,fhGetRecordId(ptrRoot))
table.insert(tblRoot,strRoot)
table.insert(tblItem,ptrItem:Clone())
table.insert(tblDate,fhGetItemPtr(ptrItem,"~.DATA.DATE"))
table.insert(tblQuay,fhGetItemPtr(ptrItem,"~.QUAY"))
table.insert(tblPage,fhGetItemPtr(ptrItem,"~.PAGE"))
table.insert(tblText,fhGetItemPtr(ptrItem,"~.DATA.TEXT"))
table.insert(tblNote,fhGetItemPtr(ptrItem,"~.NOTE2"))
end
end
end
end
ptrItem:MoveNextSpecial()
if strRepl == "Cancel" then break end
end
if strRepl == "Cancel" then break end
end
if #tblItem > 0 then
fhOutputResultSetTitles( strPluginName ) -- V1.2
fhOutputResultSetColumn("Root Record " , "item", tblRec , #tblItem, 180, "align_left") -- V1.2
fhOutputResultSetColumn("Rec Id" , "integer", tblRid , #tblItem, 30, "align_mid" ) -- V1.2
fhOutputResultSetColumn("Citation Root" , "text", tblRoot, #tblItem, 180, "align_left")
fhOutputResultSetColumn("Source Buddy" , "item", tblItem, #tblItem, 180, "align_left", 0, true, "default", "buddy")
fhOutputResultSetColumn("Entry Date" , "item", tblDate, #tblItem, 60, "align_left")
fhOutputResultSetColumn("Assessment" , "item", tblQuay, #tblItem, 60, "align_left")
fhOutputResultSetColumn("Where within Source", "item", tblPage, #tblItem, 180, "align_left")
fhOutputResultSetColumn("Text From Source" , "item", tblText, #tblItem, 180, "align_left")
fhOutputResultSetColumn("Note" , "item", tblNote, #tblItem, 180, "align_left")
else
fhMessageBox("\n No matching Source Citations found. \n")
end
end -- function Main()
Main()
--[[
@Title: Replace Selected Source Citations
@Type: Standard
@Author: Mike Tate
@Contributors:
@Version: 1.2
@Keywords:
@LastUpdated: 19 Dec 2020
@Licence: This plugin is copyright (c) 2020 Mike Tate & 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: Replace one Source Citation with another for chosen Citation criteria conditionally.
@V1.2: Confirm replacements; Root Record & Rec Id in Result Set; FH V7 Lua 3.5 IUP 3.28;
@V1.1: Minor update;
@V1.0: First published in Plugin Store;
]]
local strPluginName = "Replace Selected Source Citations 1.2" -- Update title and version number here
require("iuplua") -- To access GUI window builder
if fhGetAppVersion() > 5 then -- Cater for Unicode UTF-8 from FH Version 6 onwards
fhSetStringEncoding("UTF-8")
iup.SetGlobal("UTF8MODE","YES")
iup.SetGlobal("UTF8MODE_FILE","NO")
iup.SetGlobal("CUSTOMQUITMESSAGE","YES") -- Needed for IUP 3.28
end
if fhGetAppVersion() > 6 then unpack = table.unpack end -- Needed for Lua 5.3
function matches(strTxt,strFind,intInit) -- matches is plain text version of string.match()
local strMagic = "([%^%$%(%)%%%.%[%]%*%+%-%?])" -- UTF-8 replacement for "(%W)"
strFind = tostring(strFind or ""):gsub(strMagic,"%%%1") -- Hide magic pattern symbols
return tostring(strTxt or ""):match(strFind,tonumber(intInit))
end -- function matches
function GetRecord(index) -- Get old/new Source record choice
local ptrGet = nil
local strGet = ""
if index == -1 then
local tblGet = fhPromptUserForRecordSel("SOUR",1) -- Prompt for Source record
if #tblGet == 1 then
ptrGet = tblGet[1] -- Link to record
strGet = fhGetDisplayText(ptrGet) -- Name of record
end
end
return ptrGet,strGet
end -- function GetRecord()
function GetOld(dialog,index)
if index == iup.GETPARAM_MAP then -- Correct button labels needed for IUP 3.28 bug -- V1.2
dialog.Button1.Title = "Select Old Source"
dialog.Button2.Title = "Cancel Plugin"
end
ptrOld,strOld = GetRecord(index) -- Prompt for new Source record link & name
return 1
end -- function GetOld
function GetNew(dialog,index)
if index == iup.GETPARAM_MAP then -- Correct button labels needed for IUP 3.28 bug -- V1.2
dialog.Button1.Title = "Select New Source"
dialog.Button2.Title = "Cancel Plugin"
end
ptrNew,strNew = GetRecord(index) -- Prompt for new Source record link & name
return 1
end -- function GetNew
function GetOpt(dialog,index)
if index == iup.GETPARAM_MAP then -- Correct button labels needed for IUP 3.28 bug -- V1.2
dialog.Button1.Title = "Perform Replace"
dialog.Button2.Title = "Cancel Plugin"
end
return 1
end -- function paramAction
function Main()
if not iup.GetParam("Select Old Source Record",GetOld," Select the Source record that needs to be replaced.%t\n%u[Select Old Source,Cancel Plugin]")
or not ptrOld then return end
if not iup.GetParam("Select New Source Record",GetNew," Select the Source record to replace that old Source.%t\n%u[Select New Source,Cancel Plugin]")
or not ptrNew then return end
local tblForm = {} -- Format strings for iup.GetParam
local tblData = {} -- Parameter values for iup.GetParam
local tblTags = {} -- Data Ref Tags for Citation fields
local tblDel = {} -- Indices for delete & contains actions
local tblCon = {}
local intQuay = 0 -- Cater for 'Assessment' field
local arrQuay = {[0]="","Unreliable","Questionable","Secondary evidence","Primary evidence"}
local strQuay = "| "..table.concat(arrQuay,"|",0).."|" -- GetParam list is 0 based
local intRepl = 0
local strRepl = "Yes" -- Replacement confirmation -- V1.2
local function setTables(strForm,strData,strTags,tblAct) -- Set those lookup table to values below
table.insert(tblForm,strForm)
table.insert(tblData,strData)
table.insert(tblTags,strTags)
if tblAct then table.insert(tblAct,#tblForm) end -- List of indices for delete or contains actions
if intQuay == 0 and matches(strTags,"QUAY") then intQuay = #tblData end
if matches(strTags,"????") then intRepl = #tblData end -- V1.2
end -- local function setTables
setTables( "Old Source to be replaced: %s" , strOld , " " )
setTables( "'Assessment' field contains?%l"..strQuay, 0 , "~.QUAY" , tblCon )
setTables( "'Where within Source' contains: %s" , "" , "~.PAGE" , tblCon )
setTables( "'Text From Source' contains: %m" , "" , "~.DATA.TEXT" , tblCon )
setTables( "Local 'Note' field contains: %m" , "" , "~.NOTE2" , tblCon )
setTables( "If all conditions above match: %t" )
setTables( "New Source as replacement: %s" , strNew , " " )
setTables( "Delete 'Entry Date' field? %b" , 0 , "~.DATA.DATE" , tblDel )
setTables( "Delete 'Assessment' field? %b" , 0 , "~.QUAY" , tblDel )
setTables( "Delete 'Where within Source'? %b" , 0 , "~.PAGE" , tblDel )
setTables( "Delete 'Text From Source'? %b" , 0 , "~.DATA.TEXT" , tblDel )
setTables( "Delete local 'Note' field? %b" , 0 , "~.NOTE2" , tblDel )
setTables( "Confirm each replacement? %b" , 0 , "????" ) -- V1.2
setTables( "%u[Perform Replace, Cancel Plugin]" )
tblData = { iup.GetParam("Source Citation Options",GetOpt,table.concat(tblForm,"\n"),unpack(tblData)) }
if not tblData[1] then return end
table.remove(tblData,1) -- Align data with tables above
tblData[intQuay] = arrQuay[tblData[intQuay]] -- Convert 'Assessment' index to text
local tblRec = {} -- Result Set tables -- V1.2
local tblRid = {}
local tblRoot = {}
local tblItem = {}
local tblDate = {}
local tblQuay = {}
local tblPage = {}
local tblText = {}
local tblNote = {}
local tblType = {"INDI","FAM","NOTE","SOUR","REPO","SUBM","OBJE","_PLAC"} -- Record type tags with Citations
local ptrItem = fhNewItemPtr()
for intType, strType in ipairs(tblType) do -- Scan all record Types that may have Citations
ptrItem:MoveToFirstRecord(strType)
while ptrItem:IsNotNull() do
if fhGetTag(ptrItem) == "SOUR" -- Search items until Source Citation found
and fhHasParentItem(ptrItem) then
if ptrOld:IsSame(fhGetValueAsLink(ptrItem)) then -- Cited Source record matches
local isCon = true
for _, intCon in ipairs (tblCon) do
if not matches(fhGetItemText(ptrItem,tblTags[intCon]),tblData[intCon]) then
isCon = false -- Field does not contain required text
break
end
end
if isCon then -- All fields also match
local ptrRoot = fhNewItemPtr()
ptrRoot:MoveToParentItem(ptrItem) -- Obtain root for Citation -- V1.2
local strRoot = fhGetDisplayText(ptrRoot)
ptrRoot:MoveToRecordItem(ptrItem) -- Obtain record of Citation -- V1.2
local strRecd = fhGetDisplayText(ptrRoot)
if tblData[intRepl] > 0 then -- Confirm each replacement? -- V1.2
strRepl = fhMessageBox("\nIn record "..strRecd.." \ndo you want to replace Source Citation for \n"..strRoot,"MB_YESNOCANCEL")
end
if strRepl == "Yes" then
local isOK = fhSetValueAsLink(ptrItem,ptrNew) -- So replace this record with new Source record
for _, intDel in ipairs (tblDel) do -- Delete chosen fields
if tblData[intDel] == 1 then
local isOK = fhDeleteItem(fhGetItemPtr(ptrItem,tblTags[intDel]))
end
end
table.insert(tblRec ,ptrRoot:Clone()) -- Update Result Set -- V1.2
table.insert(tblRid ,fhGetRecordId(ptrRoot))
table.insert(tblRoot,strRoot)
table.insert(tblItem,ptrItem:Clone())
table.insert(tblDate,fhGetItemPtr(ptrItem,"~.DATA.DATE"))
table.insert(tblQuay,fhGetItemPtr(ptrItem,"~.QUAY"))
table.insert(tblPage,fhGetItemPtr(ptrItem,"~.PAGE"))
table.insert(tblText,fhGetItemPtr(ptrItem,"~.DATA.TEXT"))
table.insert(tblNote,fhGetItemPtr(ptrItem,"~.NOTE2"))
end
end
end
end
ptrItem:MoveNextSpecial()
if strRepl == "Cancel" then break end
end
if strRepl == "Cancel" then break end
end
if #tblItem > 0 then
fhOutputResultSetTitles( strPluginName ) -- V1.2
fhOutputResultSetColumn("Root Record " , "item", tblRec , #tblItem, 180, "align_left") -- V1.2
fhOutputResultSetColumn("Rec Id" , "integer", tblRid , #tblItem, 30, "align_mid" ) -- V1.2
fhOutputResultSetColumn("Citation Root" , "text", tblRoot, #tblItem, 180, "align_left")
fhOutputResultSetColumn("Source Buddy" , "item", tblItem, #tblItem, 180, "align_left", 0, true, "default", "buddy")
fhOutputResultSetColumn("Entry Date" , "item", tblDate, #tblItem, 60, "align_left")
fhOutputResultSetColumn("Assessment" , "item", tblQuay, #tblItem, 60, "align_left")
fhOutputResultSetColumn("Where within Source", "item", tblPage, #tblItem, 180, "align_left")
fhOutputResultSetColumn("Text From Source" , "item", tblText, #tblItem, 180, "align_left")
fhOutputResultSetColumn("Note" , "item", tblNote, #tblItem, 180, "align_left")
else
fhMessageBox("\n No matching Source Citations found. \n")
end
end -- function Main()
Main()
Source:Replace-Selected-Source-Citations-1.fh_lua