--[[ @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