Keyword Update.fh_lua--[[
@Title: Keyword Update
@Type: Standard
@Author: Peter Richmond
@Contributors: Mike Tate
@Version:1.5
@LastUpdated: 08Feb2021
@Licence: This plugin is copyright (c) 2020 Peter Richmond & 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: Update Keywords for a selection of Multimedia Object records.
Existing used keywords are shown alphabetically, with counts, and the user can add further keywords.
Then the user selects one or more keywords to be added to the selection of multimedia records,
replacing any existing keywords on those records.
If the plugin was started without selecting the required Multimedia records,
the user is prompted to make a selection.
The updated records are displayed as a Result Set.
@V1.5: Updated link to Help (thanks to Mike Tate).
@V1.4: Tested for FHv7.
@V1.3: Minor tweak.
@V1.2: (Thanks to Mike Tate) Unicode characters outside the ANSI/CP1252 set now preserved.
@V1.1: Button added for Online Help.
]]
require("iuplua") -- To access GUI window builder
if fhGetAppVersion() > 5 then -- To preserve Unicode characters outside the ANSI/CP1252 set.
fhSetStringEncoding("UTF-8")
iup.SetGlobal("UTF8MODE","YES")
end
---------------------------------- Additional Functions
function inc(i,s)
if i then i = i + s else i = s end
return i
end ---------------function inc()
function sort(t)
tSorted = {}
for sKey in pairs(t) do
table.insert(tSorted,sKey)
end
table.sort(tSorted)
return tSorted
end ---------------function sort()
function param_action(dialog, param_index) ---- to react to the Help button
if (param_index == -4) then
fhShellExecute("https://pluginstore.family-historian.co.uk/page/help/keyword-update","","","open")
end
return 1
end ----------------function param_action()
--- Main process - 1st list existing keywords
tKeywords = {} -- Define array for Keywords
pO = fhNewItemPtr() -- declare pointer
pO:MoveToFirstRecord("OBJE") -- set pointer to the first Media Object record
while pO:IsNotNull() do -- For each Object add the Keywords to the list
sKeywords = fhGetItemText(pO,'~._KEYS')
for sKeyword in string.gmatch(sKeywords, "[^%s,][^,]*") do -- separate multiple keywords
tKeywords[sKeyword] = inc(tKeywords[sKeyword],1)
end
pO:MoveNext()
end
----------------------------- Sort the individual existing keywords alphabetically
tKeyword = sort(tKeywords)
sPicklist = ""
tTicks={}
for index, sKeyword in pairs(tKeyword) do
sPicklist = sPicklist .. sKeyword .. " \t" .. string.format("%6u",tKeywords[sKeyword]) .. "\n"
end
---------------------------------------- List existing keywords and input any new keywords
sTitle="Existing and New Keywords"
sTitle1="Exisiting Keywords used in "..fhGetContextInfo('CI_PROJECT_NAME')
sNew=""
bOK, sPicklist,sNew = iup.GetParam(sTitle, param_action, sTitle1..":%m\n"
.."Expand window or scroll to see all keywords %t\n"
.."Add New Keywords not in above list:%m\n"
.."In the next window hold down Ctrl and click on each keyword %t\n"
.."to be added to all of the selected multimedia records %t\n"
.."%u[OK,Cancel,Online Help]\n", sPicklist, sNew) -- %u for Help button
if bOK ~= true then return end
for sKey in string.gmatch(sNew, "[^%c]*") do -- separate multiple keywords
tKeywords[sKey] = inc(tKeywords[sKey],0)
end
----------------------------- Sort the full set of keywords alphabetically
tKeyword = sort(tKeywords)
iSize=#tKeyword
for index, sKeyword in pairs(tKeyword) do
tTicks[index]=0
end
------------------------------------ Select required keywords to be applied to seleted multimedia records
sTitle2 = "Ctrl+click Keywords"
sKeys = ""
bOK = 1
while sKeys == "" and bOK == 1 do -- await selection of required keywords
bOK = iup.ListDialog(2,sTitle2,iSize,tKeyword,0,1,math.min(iSize,25),tTicks)
if bOK ~= 1 then return end
for i, iTick in pairs(tTicks) do
if tTicks[iTick] then
sKeys=sKeys..", "..tKeyword[i]
end
end
end
sKeys = string.gsub(sKeys, ", ", "", 1)
------------------------Get selection of Multimedia records to be updated
pKeys=fhNewItemPtr()
pList = fhGetCurrentRecordSel('OBJE')
if #pList < 1 then
a = fhMessageBox("You need to select Multimedia records for keyword input", "MB_OKCancel")
if a ~= "OK" then return end
pList = fhPromptUserForRecordSel('OBJE')
if #pList < 1 then return end
end
a = fhMessageBox("OK to update "..#pList.." Multimedia record"
..string.rep("s",math.min(1,#pList-1)).." replacing any old keywords with\n\n"
..sKeys,"MB_OKCancel","MB_ICONQUESTION")
if a ~= "OK" then return end
-------------------------------- Make changes and output result set
tObje={}
tOldKeys={}
tNewKeys={}
iChanges=0
for i, pObje in pairs(pList) do
pKeys:MoveTo(pObje,'~._KEYS')
sOld=fhGetValueAsText(pKeys)
if sOld == "" then pKeys=fhCreateItem('_KEYS',pObje,true) end -- Ensure there is a _KEYS tag
if sOld ~= sKeys then -- Skip record if no change needed
fhSetValueAsText(pKeys,sKeys)
table.insert(tObje,pObje:Clone())
table.insert(tOldKeys,sOld)
table.insert(tNewKeys,sKeys)
iChanges = iChanges + 1
end
end
if iChanges > 0 then
sUndo = "\n\nYou can use FH menu option Edit > Undo Plugin Updates if you don't like the result."
fhMessageBox(iChanges.." Multimedia records updated."..sUndo)
fhOutputResultSetColumn("Multimedia Record", "item", tObje, #tObje,300)
fhOutputResultSetColumn("Old Keywords", "text", tOldKeys, #tOldKeys,120)
fhOutputResultSetColumn("New Keywords", "text", tNewKeys, #tNewKeys,120)
else fhMessageBox("No changes.")
end
--[[
@Title: Keyword Update
@Type: Standard
@Author: Peter Richmond
@Contributors: Mike Tate
@Version:1.5
@LastUpdated: 08Feb2021
@Licence: This plugin is copyright (c) 2020 Peter Richmond & 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: Update Keywords for a selection of Multimedia Object records.
Existing used keywords are shown alphabetically, with counts, and the user can add further keywords.
Then the user selects one or more keywords to be added to the selection of multimedia records,
replacing any existing keywords on those records.
If the plugin was started without selecting the required Multimedia records,
the user is prompted to make a selection.
The updated records are displayed as a Result Set.
@V1.5: Updated link to Help (thanks to Mike Tate).
@V1.4: Tested for FHv7.
@V1.3: Minor tweak.
@V1.2: (Thanks to Mike Tate) Unicode characters outside the ANSI/CP1252 set now preserved.
@V1.1: Button added for Online Help.
]]
require("iuplua") -- To access GUI window builder
if fhGetAppVersion() > 5 then -- To preserve Unicode characters outside the ANSI/CP1252 set.
fhSetStringEncoding("UTF-8")
iup.SetGlobal("UTF8MODE","YES")
end
---------------------------------- Additional Functions
function inc(i,s)
if i then i = i + s else i = s end
return i
end ---------------function inc()
function sort(t)
tSorted = {}
for sKey in pairs(t) do
table.insert(tSorted,sKey)
end
table.sort(tSorted)
return tSorted
end ---------------function sort()
function param_action(dialog, param_index) ---- to react to the Help button
if (param_index == -4) then
fhShellExecute("https://pluginstore.family-historian.co.uk/page/help/keyword-update","","","open")
end
return 1
end ----------------function param_action()
--- Main process - 1st list existing keywords
tKeywords = {} -- Define array for Keywords
pO = fhNewItemPtr() -- declare pointer
pO:MoveToFirstRecord("OBJE") -- set pointer to the first Media Object record
while pO:IsNotNull() do -- For each Object add the Keywords to the list
sKeywords = fhGetItemText(pO,'~._KEYS')
for sKeyword in string.gmatch(sKeywords, "[^%s,][^,]*") do -- separate multiple keywords
tKeywords[sKeyword] = inc(tKeywords[sKeyword],1)
end
pO:MoveNext()
end
----------------------------- Sort the individual existing keywords alphabetically
tKeyword = sort(tKeywords)
sPicklist = ""
tTicks={}
for index, sKeyword in pairs(tKeyword) do
sPicklist = sPicklist .. sKeyword .. " \t" .. string.format("%6u",tKeywords[sKeyword]) .. "\n"
end
---------------------------------------- List existing keywords and input any new keywords
sTitle="Existing and New Keywords"
sTitle1="Exisiting Keywords used in "..fhGetContextInfo('CI_PROJECT_NAME')
sNew=""
bOK, sPicklist,sNew = iup.GetParam(sTitle, param_action, sTitle1..":%m\n"
.."Expand window or scroll to see all keywords %t\n"
.."Add New Keywords not in above list:%m\n"
.."In the next window hold down Ctrl and click on each keyword %t\n"
.."to be added to all of the selected multimedia records %t\n"
.."%u[OK,Cancel,Online Help]\n", sPicklist, sNew) -- %u for Help button
if bOK ~= true then return end
for sKey in string.gmatch(sNew, "[^%c]*") do -- separate multiple keywords
tKeywords[sKey] = inc(tKeywords[sKey],0)
end
----------------------------- Sort the full set of keywords alphabetically
tKeyword = sort(tKeywords)
iSize=#tKeyword
for index, sKeyword in pairs(tKeyword) do
tTicks[index]=0
end
------------------------------------ Select required keywords to be applied to seleted multimedia records
sTitle2 = "Ctrl+click Keywords"
sKeys = ""
bOK = 1
while sKeys == "" and bOK == 1 do -- await selection of required keywords
bOK = iup.ListDialog(2,sTitle2,iSize,tKeyword,0,1,math.min(iSize,25),tTicks)
if bOK ~= 1 then return end
for i, iTick in pairs(tTicks) do
if tTicks[iTick] then
sKeys=sKeys..", "..tKeyword[i]
end
end
end
sKeys = string.gsub(sKeys, ", ", "", 1)
------------------------Get selection of Multimedia records to be updated
pKeys=fhNewItemPtr()
pList = fhGetCurrentRecordSel('OBJE')
if #pList < 1 then
a = fhMessageBox("You need to select Multimedia records for keyword input", "MB_OKCancel")
if a ~= "OK" then return end
pList = fhPromptUserForRecordSel('OBJE')
if #pList < 1 then return end
end
a = fhMessageBox("OK to update "..#pList.." Multimedia record"
..string.rep("s",math.min(1,#pList-1)).." replacing any old keywords with\n\n"
..sKeys,"MB_OKCancel","MB_ICONQUESTION")
if a ~= "OK" then return end
-------------------------------- Make changes and output result set
tObje={}
tOldKeys={}
tNewKeys={}
iChanges=0
for i, pObje in pairs(pList) do
pKeys:MoveTo(pObje,'~._KEYS')
sOld=fhGetValueAsText(pKeys)
if sOld == "" then pKeys=fhCreateItem('_KEYS',pObje,true) end -- Ensure there is a _KEYS tag
if sOld ~= sKeys then -- Skip record if no change needed
fhSetValueAsText(pKeys,sKeys)
table.insert(tObje,pObje:Clone())
table.insert(tOldKeys,sOld)
table.insert(tNewKeys,sKeys)
iChanges = iChanges + 1
end
end
if iChanges > 0 then
sUndo = "\n\nYou can use FH menu option Edit > Undo Plugin Updates if you don't like the result."
fhMessageBox(iChanges.." Multimedia records updated."..sUndo)
fhOutputResultSetColumn("Multimedia Record", "item", tObje, #tObje,300)
fhOutputResultSetColumn("Old Keywords", "text", tOldKeys, #tOldKeys,120)
fhOutputResultSetColumn("New Keywords", "text", tNewKeys, #tNewKeys,120)
else fhMessageBox("No changes.")
endSource:Keyword-Update-1.fh_lua