Script to Find Collections holding an Image
***Edit*** 2020/07/05 The migrated version of this script likely will not complile because the Applescript symbols for "not equal", "less than" and "greater than" are not supported in the new forum
Here is my applescript which finds all the user collection which contain a set of selected images, updated for Capture One 11.
This script creates a textedit file containing the results. The search time is about 27 seconds for each variant in a catalog of 15000 images.-- Applescript to search a COP 10 Catalog for Collections containing the Image of a selected variant
-- Version 1.14 !! NO SUPPORT !! Eric Valk, Ottawa, Canada
-- ***To Initialise
-- Start Script Editor, open a new (blank) file, copy and paste all of this code into the file, compile (hammer symbol) and save.
-- Best if you make "Scripts" folder somewhere handy in your Douments or Desktop
-- *** Operation
-- Open the compiled and saved file
-- Open the Script Editor log window, and select the messages tab
-- Select only a small number of variants, from any collection.
-- Run the script
-- Results appear first in the AppleScript Log when the search for each variant is completed, and in Display Dialog Windows when all searching is completed
-- This script does not write or delete any information in the COP Catalog or Session or the image file
set debug to 0
set Results_max_debug to 3
set maxSearchlevel to 100
property searchTimePerVariant : 0
set WarnMaxVariants to 3
set WarnSearchTime to 30
set SearchDiskFileSystem to false
set SearchRecentImports to false
set SearchRecentCaptures to false
set SearchTrash to false
if SearchDiskFileSystem then
set ExcludedTopCollectionKinds to {""}
else
set ExcludedTopCollectionKinds to {"catalog folder"}
end if
set ExcludedTopCollectionNames to {"In Catalog", "Catalog", "All Images"}
set ExcludedSubCollectionNames to {""} -- used for testing
set StopSearchAtProject to false
if not SearchRecentImports then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Recent Imports"
if not SearchRecentCaptures then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Recent Captures"
if not SearchTrash then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Trash"
tell application "System Events" to set parent_name to name of current application
tell application "Finder"
set script_path to path to me
set Script_Title to name of file script_path as text
end tell
set SE_Logging to (parent_name = "Script Editor")
set Result_DocName to "COP_Image_Search.txt"
set Result_Doc_Path_p to my open_TextDoc(Result_DocName)
my loq_TextDoc("Action: Find collections where images are located", false, 0)
my loq_TextDoc(Script_Title & " started from: " & parent_name, false, 0)
set minCOPversion to "11.0.1"
validateCOP(minCOPversion)
set {COPDocName, COPDocRef} to validateCOPdoc({"catalog", "session"})
set options_display_string to "Debug Level: " & debug
if SE_Logging then set options_display_string to options_display_string & return & "Highest Debug Class in Result File: " & Results_max_debug
set options_display_string to options_display_string & return & "Maximum Search Level: " & maxSearchlevel
set options_display_string to options_display_string & return & "Estimated Search Time per Variant: "
if searchTimePerVariant = 0 then
set options_display_string to options_display_string & "unknown"
else
set options_display_string to options_display_string & searchTimePerVariant
end if
set options_display_string to options_display_string & return & "Search Managed Files: " & false
set options_display_string to options_display_string & return & "Search Referenced Files: " & SearchDiskFileSystem
set options_display_string to options_display_string & return & "Search Recent Imports: " & SearchRecentImports
set options_display_string to options_display_string & return & "Search Recent Captures: " & SearchRecentCaptures
set options_display_string to options_display_string & return & "Search All Images: " & false
set options_display_string to options_display_string & return & "Search COP Trash: " & false
set options_display_string to options_display_string & return & "Other Excluded Collections: " & ExcludedSubCollectionNames
set options_display_string to options_display_string & return & "Do Not Search below Projects: " & StopSearchAtProject
set options_display_string to options_display_string & return & "Results File: " & Result_Doc_Path_p
tell application "System Events" to set frontmost of process parent_name to true
try
set dialog_result to display dialog options_display_string with title Script_Title
on error errmess
my loqqed_exit("User Cancelled the Script")
end try
if debug ≥ 1 then my loq_TextDoc((return & "Options:" & return & options_display_string & return), true, 1)
tell application "Capture One 11" to set selectedVariants to (get selected variants)
set countSelectedVariants to count of selectedVariants
if debug ≥ 3 then my loq_TextDoc(("In this window " & (count of selectedVariants) & " Selected Variants"), false, 3)
if countSelectedVariants = 0 then
display alert "No images selected - select one or more images"
my loqqed_exit("No images selected")
else
set estimatedDuration to countSelectedVariants * searchTimePerVariant
tell application "System Events" to set frontmost of process parent_name to true
try
if countSelectedVariants > WarnMaxVariants and searchTimePerVariant = 0 then
display dialog "Are you sure you want to search for " & countSelectedVariants & " variants? " with icon caution
else if estimatedDuration > WarnSearchTime then
display dialog "Are you sure you want to search for " & countSelectedVariants & " variants? Estimated time: " & estimatedDuration & " seconds" with icon caution
end if
on error errmess
my loqqed_exit("User Cancelled the Script")
end try
set nameSelectedVariants to {}
set idParentSelectedVariants to {}
repeat with v_Counter from 1 to countSelectedVariants
set thisVariant to item v_Counter of selectedVariants
tell application "Capture One 11"
set nameSelectedVariants to nameSelectedVariants & (get name of thisVariant)
set idParentSelectedVariants to idParentSelectedVariants & (get id of parent image of thisVariant)
end tell
end repeat
if debug ≥ 3 then
log nameSelectedVariants
log idParentSelectedVariants
end if
set startTime to get time of (get current date)
tell application "Capture One 11" to set everyCollection to get every collection of document COPDocName
set max_search_coll_index to get ((count of everyCollection) - 1)
set selected_collection_index to max_search_coll_index + 1
set allResults to {}
set search_executed to false
set progress total steps to countSelectedVariants
set progress completed steps to 0
set progress description to "Searching for Variants ..."
repeat with v_Counter from 1 to countSelectedVariants
set thisVariant to item v_Counter of selectedVariants
set searchedImageName to item v_Counter of nameSelectedVariants
set searchedImageID to item v_Counter of idParentSelectedVariants
set progress completed steps to v_Counter
set progress description to "Searching for Variant " & searchedImageName
if debug ≥ 2 then my loq_TextDoc((return & "Searching for " & searchedImageName & " ID: " & searchedImageID), false, 2)
set isFound to false
set foundPaths to ""
set pathSeparator to ""
set searchLevel to 0
set nextSearchLevel to searchLevel + 1
if nextSearchLevel ≤ maxSearchlevel then
repeat with c_Counter from 1 to max_search_coll_index
set thisTopCollection to item c_Counter of everyCollection
tell application "Capture One 11" to tell document COPDocName to tell thisTopCollection
set {topCollName, topCollKind} to {name as text, kind as text}
end tell
if (ExcludedTopCollectionNames does not contain topCollName) and ¬
(ExcludedTopCollectionKinds does not contain topCollKind) then
set search_executed to true
if debug ≥ 3 then my loq_TextDoc(("Search: " & topCollKind & " " & topCollName), false, 3)
set resultPaths to my search_collection(thisTopCollection, nextSearchLevel)
set resultCount to count of resultPaths
if debug ≥ 3 then my loq_TextDoc(("Result of search in " & topCollName & " (" & topCollKind & ") is: " & resultPaths), false, 3)
if resultCount > 0 then
set isFound to true
repeat with p_counter from 1 to count of resultPaths
set foundPaths to foundPaths & pathSeparator & item p_counter of resultPaths
set pathSeparator to return -- after the first path is added the separator become the newline character /r
end repeat
end if
else
if debug ≥ 3 then my loq_TextDoc(("Reject: " & topCollKind & " " & topCollName), false, 3)
end if
end repeat
end if
if not search_executed then -- there are no top level collections to search - don't keep searching
display notification "No Top Level Collections to Search"
my loqqed_exit("No Top Level Collections to Search")
end if
if isFound then
set thisResult to {v_Counter, searchedImageName, true, foundPaths}
my loq_TextDoc((return & searchedImageName & " was found in:" & return & foundPaths), true, 0)
if debug ≥ 2 then display notification searchedImageName & " was found"
else
set thisResult to {v_Counter, searchedImageName, false, foundPaths}
my loq_TextDoc((return & searchedImageName & " was not found"), true, 0)
display notification searchedImageName & " was not found"
end if
set allResults to allResults & thisResult
end repeat
set stopTime to get time of (get current date)
if stopTime < startTime then set startTime to startTime - 86400 -- the search started yesterday and ended today
set elapsedtime to stopTime - startTime
set searchTimePerVariant to elapsedtime / countSelectedVariants
my loq_TextDoc((return & "This search took " & elapsedtime & " seconds (" & searchTimePerVariant & "s per variant)" & return & return & "Done"), true, 0)
say "Finished!"
end if
tell application "System Events" to set frontmost of process "Capture One 11" to true
tell application "System Events" to set frontmost of process "TextEdit" to true
--Handlers -------------------
on search_collection(thisCollection, searchLevel)
-- recursive handler to search a collection and it's subcollections
-- if successful, returns a list of paths each as a text string
global debug, maxSearchlevel, searchedImageID, COPDocName, StopSearchAtProject, ExcludedSubCollectionNames, selected_collection_index
set found_paths to {} -- initialise the list
tell application "Capture One 11" to tell document COPDocName to tell thisCollection to set {thisCollName, thisCollKind} to {name as text, kind as text}
set progress additional description to thisCollKind & " " & thisCollName
if ExcludedSubCollectionNames contains thisCollName then return found_paths
tell application "Capture One 11" to tell document COPDocName to tell thisCollection
set searchImageIDhits to count of (get every image whose id is searchedImageID)
end tell
if searchImageIDhits > 0 then
set found_paths to found_paths & (thisCollName & "(" & thisCollKind & ")")
if debug ≥ 4 then my loq_TextDoc(("Found " & searchImageIDhits & " hits in " & thisCollKind & " " & thisCollName), false, 4)
end if
if debug ≥ 5 then
tell application "Capture One 11" to tell document COPDocName to tell thisCollection
set countImages to count of every image
set countVariants to count of every variant
set countCollsthisColl to count of every collection
end tell
my loq_TextDoc(("In " & thisCollKind & " " & thisCollName & " at level " & searchLevel & " found " & countImages & " images ," & countVariants & " variants ," & countCollsthisColl & " collections"), false, 5)
end if
set nextSearchLevel to searchLevel + 1
if (nextSearchLevel ≤ maxSearchlevel) and ¬
(not (StopSearchAtProject and thisCollKind = "project")) then
tell application "Capture One 11" to tell document COPDocName to tell thisCollection to set countCollsthisColl to count of every collection
if debug ≥ 5 then my loq_TextDoc(("Searching Collections in " & thisCollKind & " " & thisCollName & " at level " & searchLevel & " found " & countCollsthisColl & " collections"), false, 5)
repeat with c_Counter from 1 to countCollsthisColl
## generate an error to capture the error text
tell application "Capture One 11" to tell document COPDocName to tell thisCollection
try
|| of {(get collection c_Counter)}
on error CO11_errtxt number CO11_errnbr
end try
end tell
## extract the collection number from the error text
if CO11_errtxt contains "collection" and CO11_errnbr = -1728 then
set CollNum to (get last word of item 2 of splitStringToList(CO11_errtxt, "of")) as integer
else
loq_TextDoc(("*****" & CO11_errtxt & "; number " & CO11_errnbr), false, 4)
loqqed_exit("Unexpected error when checking collection integrity")
end if
if debug ≥ 5 then loq_TextDoc(("***Error Message " & CO11_errtxt & "; number " & CO11_errnbr & " Collection: " & CollNum & " of " & thisCollKind & " " & thisCollName), false, 4)
if CollNum ≠c_Counter then
## this is the selected collection, and is present as the last collection in the document
if selected_collection_index ≠CollNum then
loq_TextDoc(("*****" & CO11_errtxt & "; number " & CO11_errnbr), false, 4)
loqqed_exit("Unexpected collection index when checking collection integrity: " & CollNum)
end if
tell application "Capture One 11" to tell document COPDocName
set searchColl to collection CollNum
set collNumMismatch to true
if debug ≥ 3 then my loq_TextDoc(("Top Level Collection number:" & CollNum & "replaces Sub collection " & c_Counter & " of " & thisCollKind & " " & thisCollName), false, 3)
end tell
else
tell application "Capture One 11" to tell document COPDocName to tell thisCollection
set searchColl to collection CollNum
set collNumMismatch to false
if debug ≥ 4 then my loq_TextDoc(("Verified sub-Collection " & CollNum & "of " & thisCollKind & " " & thisCollName), false, 4)
end tell
end if
tell application "Capture One 11" to tell document COPDocName to tell searchColl to set {searchCollName, searchCollKind} to {name as text, kind as text}
if debug ≥ 4 then loq_TextDoc(("Starting search in " & searchCollName & " (" & searchCollKind & ") "), false, 4)
set resultPaths to my search_collection(searchColl, nextSearchLevel)
set countResultPaths to count of resultPaths
## if collNumMismatch then error
if debug ≥ 3 then loq_TextDoc(("Result of search in " & searchCollName & " (" & searchCollKind & ") is: " & resultPaths), false, 4)
if countResultPaths > 0 then
repeat with p_counter from 1 to countResultPaths
set found_paths to found_paths & (thisCollName & "<" & item p_counter of resultPaths)
end repeat
end if
end repeat
end if
if (count of found_paths) > 0 then log found_paths
return found_paths
end search_collection
on validateCOP(minCOPversionstr)
global debug
tell application "System Events"
set COPProcList to every process whose name contains "Capture One" and background only is false
if debug ≥ 2 then
set COPProcNameList to name of every process whose name contains "Capture One" and background only is false
my loq_TextDoc(COPProcNameList, false, 2)
end if
end tell
if (count of COPProcList) = 0 then my loqqed_exit("COP is not running")
if (count of COPProcList) ≠1 then my loqqed_exit("Unexpected: >1 COP instances")
set theAppRef to item 1 of COPProcList
tell application "System Events" to set theAppName to ((get name of theAppRef) as text)
tell application "System Events" to set copDetailedVersion to get version of my application theAppName
tell application "Capture One 11" to set copVersion to (get app version)
if debug ≥ 2 then
--properties of application "Capture One 11"
tell application "System Events"
my loq_TextDoc((get name of every process whose background only is false), false, 2)
end tell
my loq_TextDoc(("theAppName: " & theAppName), false, 2)
my loq_TextDoc(("COP Version: " & copVersion), false, 2)
my loq_TextDoc(("COP Detailed Version: " & copDetailedVersion), false, 2)
end if
if the theAppName ≠"Capture One 11" then
display notification "Wrong COP Application"
my loqqed_exit("Found COP Application " & theAppName & " The only supported COP application is Capture One 11")
end if
set numCOPversion to (splitStringToList((word -1 of copVersion), "."))
set minCOPversion to (splitStringToList(minCOPversionstr, "."))
set digit_mult to 1000000
set Version_digit to 0
repeat with dig_ctr from 1 to count of numCOPversion
set digit_mult to digit_mult / 100
set Version_digit to Version_digit + (get item dig_ctr of numCOPversion as integer) * digit_mult
end repeat
set digit_mult to 1000000
set min_digit to 0
repeat with dig_ctr from 1 to count of minCOPversion
set digit_mult to digit_mult / 100
set min_digit to min_digit + (get item dig_ctr of minCOPversion as integer) * digit_mult
end repeat
if Version_digit < min_digit then
display notification "COP Version is too low"
my loqqed_exit("This COP Version is " & (word -1 of copVersion) & " - the minimum supported COP version is " & minCOPversionstr)
end if
tell application "System Events" to set frontmost of process theAppName to true
my loq_TextDoc(("Capture One Version " & copDetailedVersion), false, 0)
end validateCOP
on validateCOPdoc(COP_kind_list)
global debug
tell application "Capture One 11"
set {current_doc_name, current_doc_kind} to (get {name, kind} of current document)
set current_doc_abs_list to (get every document whose name is current_doc_name and kind is current_doc_kind)
end tell
set current_doc_kind_s to current_doc_kind as text
if COP_kind_list does not contain current_doc_kind_s then my loqqed_exit(current_doc_name & " is a " & current_doc_kind_s & " unsupported type", true)
set number_of_hits to count of current_doc_abs_list
if number_of_hits = 0 then
my loqqed_exit("Could not find find " & current_doc_kind_s & current_doc_name)
else if number_of_hits > 1 then
my loqqed_exit("Found more than one " & current_doc_kind_s & " with the name " & current_doc_name)
else
set current_doc_abs to item 1 of current_doc_abs_list
end if
my loq_TextDoc(("Capture One " & current_doc_kind_s & ": " & current_doc_name), false, 0)
return {current_doc_name, current_doc_abs}
end validateCOPdoc
on open_TextDoc(DocName_Ext)
global debug, Script_Title, Result_Doc_ref, SE_Logging
set target_folder_name to "ScriptReports"
tell current application to set date_string to (current date) as text
set target_folder_p to ((POSIX path of (get path to desktop as text)) & target_folder_name)
set target_folder_a to (POSIX file target_folder_p) as string
set Result_Doc_Path_p to target_folder_p & "/" & DocName_Ext
set Result_Doc_Path_a to (POSIX file Result_Doc_Path_p) as string
tell application "System Events" to if not (exists (alias (target_folder_a))) then ¬
tell application "Finder" to make new folder at desktop with properties {name:target_folder_name}
tell application "System Events" to if not (exists (alias (Result_Doc_Path_a))) then
set First_line to ("Created " & date_string & return)
do shell script "echo " & First_line & " > " & """ & Result_Doc_Path_p & """
if (debug ≥ 1) and SE_Logging then log Result_Doc_Path_p & First_line
end if
tell application "TextEdit" to activate
tell application "TextEdit" to set Result_Doc_ref to open Result_Doc_Path_a as alias
my loq_TextDoc((return & "Started on: " & date_string), false, 0)
return Result_Doc_Path_p
end open_TextDoc
on loq_TextDoc(logText, MakeFront, debug_class)
global Result_Doc_ref, debug, SE_Logging, Results_max_debug
set logText_class to ((get class of logText) as text)
if logText_class ≠"text" then
try
if logText_class = "list" then
set new_logText to joinListToString(logText, ", ")
else
set new_logText to logText as text
end if
set logText to new_logText
set logText_class to "text"
on error errmess
set logText to errmess
set logText_class to "text"
end try
end if
if (debug_class ≤ Results_max_debug) or not SE_Logging then
tell application "TextEdit"
set numPara to count paragraphs of the text of Result_Doc_ref
set paragraph (numPara + 1) of the text of Result_Doc_ref to ((logText as text) & return)
end tell
end if
if (debug ≥ 1) and SE_Logging then log (logText as text)
tell application "System Events" to if MakeFront then set frontmost of process "TextEdit" to true
end loq_TextDoc
on loqqed_exit(error_text)
global debug, Script_Title
my loq_TextDoc(("Script "" & Script_Title & "" has exited." & return & "Reason: " & error_text & return & return & "Halted"), true, 0)
display notification error_text
error error_text
end loqqed_exit
on splitStringToList(theString, theDelim)
set astid to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to theDelim
set theList to text items of theString
on error
set AppleScript's text item delimiters to astid
end try
set AppleScript's text item delimiters to astid
return theList
end splitStringToList
to joinListToString(theList, theDelim)
set theString to ""
set astid to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to theDelim
set theString to theList as string
on error
set AppleScript's text item delimiters to astid
end try
set AppleScript's text item delimiters to astid
return theString
end joinListToString
-
Improved version 16. It handles the crash caused by the user selecting a user collection more fully, and reduces the serch time per image to about 9 seconds for a 15000 image catalog.
-- Applescript to search a COP 11 Catalog for Collections containing the Image of a selected variant
-- Version 1.16 !! NO SUPPORT !! Eric Valk, Ottawa, Canada
-- ***To Initialise
-- Start Script Editor, open a new (blank) file, copy and paste all of this code into the file, compile (hammer symbol) and save.
-- Best if you make "Scripts" folder somewhere handy in your Douments or Desktop
-- *** Operation
-- Open the compiled and saved file
-- Open the Script Editor log window, and select the messages tab
-- Select only a small number of variants, from any collection.
-- Run the script
-- Results appear first in the AppleScript Log when the search for each variant is completed, and in Display Dialog Windows when all searching is completed
-- This script does not write or delete any information in the COP Catalog or Session or the image file
set debug to 1
set Results_max_debug to 3
set maxProgressLevel to 3
set maxSearchlevel to 100
property searchTimePerVariant : 0
set WarnMaxVariants to 3
set WarnSearchTime to 30
set SearchDiskFileSystem to false
set SearchRecentImports to false
set SearchRecentCaptures to false
set SearchTrash to false
if SearchDiskFileSystem then
set ExcludedTopCollectionKinds to {""}
else
set ExcludedTopCollectionKinds to {"catalog folder"}
end if
set ExcludedTopCollectionNames to {"In Catalog", "Catalog", "All Images"}
set ExcludedSubCollectionNames to {""} -- used for testing
set StopSearchAtProject to false
if not SearchRecentImports then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Recent Imports"
if not SearchRecentCaptures then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Recent Captures"
if not SearchTrash then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Trash"
tell application "System Events" to set parent_name to name of current application
tell application "Finder"
set script_path to path to me
set Script_Title to name of file script_path as text
end tell
set SE_Logging to (parent_name = "Script Editor")
set Result_DocName to "COP_Image_Search.txt"
set Result_Doc_Path_p to my open_TextDoc(Result_DocName)
my loq_TextDoc("Action: Find collections where images are located", false, 0)
my loq_TextDoc(Script_Title & " started from: " & parent_name, false, 0)
set minCOPversion to "11.0.1"
validateCOP(minCOPversion)
set {COPDocName, COPDocRef} to validateCOPdoc({"catalog", "session"})
set options_display_string to "Debug Level: " & debug
if SE_Logging then set options_display_string to options_display_string & return & "Highest Debug Class in Result File: " & Results_max_debug
set options_display_string to options_display_string & return & "Maximum Search Level: " & maxSearchlevel
set options_display_string to options_display_string & return & "Maximum Level in Progress Bar: " & maxProgressLevel
set options_display_string to options_display_string & return & "Estimated Search Time per Variant: "
if searchTimePerVariant = 0 then
set options_display_string to options_display_string & "unknown"
else
set options_display_string to options_display_string & searchTimePerVariant
end if
set options_display_string to options_display_string & return & "Search Managed Files: " & false
set options_display_string to options_display_string & return & "Search Referenced Files: " & SearchDiskFileSystem
set options_display_string to options_display_string & return & "Search Recent Imports: " & SearchRecentImports
set options_display_string to options_display_string & return & "Search Recent Captures: " & SearchRecentCaptures
set options_display_string to options_display_string & return & "Search All Images: " & false
set options_display_string to options_display_string & return & "Search COP Trash: " & false
set options_display_string to options_display_string & return & "Other Excluded Collections: " & ExcludedSubCollectionNames
set options_display_string to options_display_string & return & "Do Not Search below Projects: " & StopSearchAtProject
set options_display_string to options_display_string & return & "Results File: " & Result_Doc_Path_p
tell application "System Events" to set frontmost of process parent_name to true
try
set dialog_result to display dialog options_display_string with title Script_Title
on error errmess
my loqqed_exit("User Cancelled the Script")
end try
if debug ≥ 1 then my loq_TextDoc((return & "Options:" & return & options_display_string & return), true, 1)
tell application "Capture One 11" to tell document COPDocName
set everyTopCollection to get every collection
set {namesTopCollections, kindsTopCollections} to {name, kind} of every collection
set lastCollectionIndex to count of everyTopCollection
set kindOfLastCollection to (get kind of collection lastCollectionIndex) as text
set nameOfLastCollection to (get name of collection lastCollectionIndex) as text
set kindOf2ndLastCollection to (get kind of collection (lastCollectionIndex - 1)) as text
set nameOf2ndLastCollection to (get name of collection (lastCollectionIndex - 1)) as text
end tell
if kindOfLastCollection = "catalog folder" then
## last collection definitely is NOT the selected collection
set max_search_coll_index to lastCollectionIndex
set selected_collection_index to 0
else if kindOf2ndLastCollection = "catalog folder" then
## last collection definitely IS the selected collection
set max_search_coll_index to lastCollectionIndex - 1
set selected_collection_index to lastCollectionIndex
else
## The last two collections are not catalog folders. Likely there are no catalog folders, all images are stored in the catalog
if nameOfLastCollection = "In Catalog" then
## last collection definitely is NOT the selected collection
set max_search_coll_index to lastCollectionIndex
set selected_collection_index to 0
else if nameOf2ndLastCollection = "In Catalog" then
## last collection definitely IS the selected collection
set max_search_coll_index to lastCollectionIndex - 1
set selected_collection_index to lastCollectionIndex
else
## Undetermined and unexpected collection arrangement
loq_TextDoc(("Unexpected Collection Structure #" & ¬
(lastCollectionIndex - 1) & " " & kindOf2ndLastCollection & " " & nameOf2ndLastCollection & ¬
" #" & lastCollectionIndex & " " & kindOfLastCollection & " " & nameOfLastCollection), false, 0)
set max_search_coll_index to lastCollectionIndex
set selected_collection_index to lastCollectionIndex
end if
end if
tell application "Capture One 11" to set selectedVariants to (get selected variants)
set countSelectedVariants to count of selectedVariants
if debug ≥ 3 then my loq_TextDoc(("In this window " & (count of selectedVariants) & " Selected Variants"), false, 3)
if countSelectedVariants = 0 then
display alert "No images selected - select one or more images"
my loqqed_exit("No images selected")
else
set estimatedDuration to countSelectedVariants * searchTimePerVariant
tell application "System Events" to set frontmost of process parent_name to true
try
if countSelectedVariants > WarnMaxVariants and searchTimePerVariant = 0 then
display dialog "Are you sure you want to search for " & countSelectedVariants & " variants? " with icon caution
else if estimatedDuration > WarnSearchTime then
display dialog "Are you sure you want to search for " & countSelectedVariants & " variants? Estimated time: " & estimatedDuration & " seconds" with icon caution
end if
on error errmess
my loqqed_exit("User Cancelled the Script")
end try
set nameSelectedVariants to {}
set idParentSelectedVariants to {}
repeat with v_Counter from 1 to countSelectedVariants
set thisVariant to item v_Counter of selectedVariants
tell application "Capture One 11"
set nameSelectedVariants to nameSelectedVariants & (get name of thisVariant)
set idParentSelectedVariants to idParentSelectedVariants & (get id of parent image of thisVariant)
end tell
end repeat
if debug ≥ 3 then
log nameSelectedVariants
log idParentSelectedVariants
end if
set startTime to get time of (get current date)
set allResults to {}
set search_executed to false
set progress total steps to countSelectedVariants
set progress completed steps to 0
set progress description to "Searching for Variants ..."
repeat with v_Counter from 1 to countSelectedVariants
set thisVariant to item v_Counter of selectedVariants
set searchedImageName to item v_Counter of nameSelectedVariants
set searchedImageID to item v_Counter of idParentSelectedVariants
set progress completed steps to v_Counter
set progress description to "Searching for Variant " & searchedImageName
if debug ≥ 2 then my loq_TextDoc((return & "Searching for " & searchedImageName & " ID: " & searchedImageID), false, 2)
set isFound to false
set foundPaths to ""
set pathSeparator to ""
set searchLevel to 0
set nextSearchLevel to searchLevel + 1
if nextSearchLevel ≤ maxSearchlevel then
repeat with c_Counter from 1 to max_search_coll_index
set thisTopCollection to item c_Counter of everyTopCollection
set topCollName to item c_Counter of namesTopCollections
set topCollKind to (item c_Counter of kindsTopCollections) as text
if (ExcludedTopCollectionNames does not contain topCollName) and ¬
(ExcludedTopCollectionKinds does not contain topCollKind) then
set search_executed to true
if debug ≥ 3 then my loq_TextDoc(("Search: " & topCollKind & " " & topCollName), false, 3)
set resultPaths to my search_collection(thisTopCollection, nextSearchLevel, topCollName, topCollKind)
set resultCount to count of resultPaths
if debug ≥ 3 then my loq_TextDoc(("Result of search in " & topCollName & " (" & topCollKind & ") is: " & resultPaths), false, 3)
if resultCount > 0 then
set isFound to true
repeat with p_counter from 1 to count of resultPaths
set foundPaths to foundPaths & pathSeparator & item p_counter of resultPaths
set pathSeparator to return -- after the first path is added the separator become the newline character /r
end repeat
end if
else
if debug ≥ 3 then my loq_TextDoc(("Reject: " & topCollKind & " " & topCollName), false, 3)
end if
end repeat
end if
if not search_executed then -- there are no top level collections to search - don't keep searching
display notification "No Top Level Collections to Search"
my loqqed_exit("No Top Level Collections to Search")
end if
if isFound then
set thisResult to {v_Counter, searchedImageName, true, foundPaths}
my loq_TextDoc((return & searchedImageName & " was found in:" & return & foundPaths), true, 0)
if debug ≥ 2 then display notification searchedImageName & " was found"
else
set thisResult to {v_Counter, searchedImageName, false, foundPaths}
my loq_TextDoc((return & searchedImageName & " was not found"), true, 0)
display notification searchedImageName & " was not found"
end if
set allResults to allResults & thisResult
end repeat
set stopTime to get time of (get current date)
if stopTime < startTime then set startTime to startTime - 86400 -- the search started yesterday and ended today
set elapsedtime to stopTime - startTime
set searchTimePerVariant to elapsedtime / countSelectedVariants
my loq_TextDoc((return & "This search took " & elapsedtime & " seconds (" & searchTimePerVariant & "s per variant)" & return & return & "Done"), true, 0)
say "Finished!"
end if
tell application "System Events" to set frontmost of process "Capture One 11" to true
tell application "System Events" to set frontmost of process "TextEdit" to true
--Handlers -------------------
on search_collection(thisCollection, searchLevel, thisCollName, thisCollKind)
-- recursive handler to search a collection and it's subcollections
-- if successful, returns a list of paths each as a text string
global debug, maxSearchlevel, searchedImageID, COPDocName, StopSearchAtProject, ExcludedSubCollectionNames, selected_collection_index, maxProgressLevel
set found_paths to {} -- initialise the list
## tell application "Capture One 11" to tell document COPDocName to tell thisCollection to set {thisCollName, thisCollKind} to {name as text, kind as text}
if ExcludedSubCollectionNames contains thisCollName then return found_paths
if searchLevel ≤ maxProgressLevel then set progress additional description to thisCollKind & " " & thisCollName
tell application "Capture One 11" to tell document COPDocName to tell thisCollection
set searchImageIDhits to count of (get every image whose id is searchedImageID)
set listSubcollsthisColl to every collection
tell me to set countSubcollsthisColl to count of listSubcollsthisColl
if countSubcollsthisColl > 0 then set {namesSubcollsthisColl, kindsSubcollsthisColl} to {name, kind} of every collection
end tell
if searchImageIDhits > 0 then
set found_paths to found_paths & (thisCollName & "(" & thisCollKind & ")")
if debug ≥ 4 then my loq_TextDoc(("Found " & searchImageIDhits & " hits in " & thisCollKind & " " & thisCollName), false, 4)
end if
if debug ≥ 5 then
tell application "Capture One 11" to tell document COPDocName to tell thisCollection
set countImages to count of every image
set countVariants to count of every variant
end tell
my loq_TextDoc(("In " & thisCollKind & " " & thisCollName & " at level " & searchLevel & " found " & countImages & " images ," & countVariants & " variants ," & countSubcollsthisColl & " collections"), false, 5)
end if
set nextSearchLevel to searchLevel + 1
if (nextSearchLevel ≤ maxSearchlevel) and ¬
(not (StopSearchAtProject and thisCollKind = "project")) then
if debug ≥ 5 then my loq_TextDoc(("Searching Collections in " & thisCollKind & " " & thisCollName & " at level " & searchLevel & " found " & countSubcollsthisColl & " collections"), false, 5)
repeat with c_Counter from 1 to countSubcollsthisColl
## tell application "Capture One 11" to tell document COPDocName to tell thisCollection to set searchColl to collection c_Counter
set searchColl to item c_Counter of listSubcollsthisColl
set searchCollName to item c_Counter of namesSubcollsthisColl
set searchCollKind to (get item c_Counter of kindsSubcollsthisColl) as text
if selected_collection_index ≠0 then
## A user sub-collection has been selected
## Check the collection number to trap the error caused by the selected subcollection returning an invalid referencee
try
|| of {searchColl} -- generate an error to capture error text containing the collection reference
on error CO11_errtxt number CO11_errnbr
end try
if debug ≥ 4 then loq_TextDoc(("***Error Message " & CO11_errtxt & "; number " & CO11_errnbr & " Collection: " & c_Counter & " of " & thisCollKind & " " & thisCollName), false, 4)
## extract the collection number from the error text
if CO11_errtxt contains "collection" and CO11_errnbr = -1728 then
set CollNum to (get last word of item 2 of splitStringToList(CO11_errtxt, "of")) as integer
else
loq_TextDoc(("*****" & CO11_errtxt & "; number " & CO11_errnbr), false, 4)
loqqed_exit("Unexpected error when checking collection integrity")
end if
if CollNum ≠c_Counter then
## this is the selected sub collection, and must be accesed as the last top level collection in the document
if selected_collection_index ≠CollNum then
## the collection reference is wrong in some other unexpected way
loq_TextDoc(("*****" & CO11_errtxt & "; number " & CO11_errnbr), false, 4)
loqqed_exit("Unexpected collection index when checking collection integrity: " & CollNum)
end if
## Set the collection reference to the last top level collection
tell application "Capture One 11" to tell document COPDocName to set searchColl to collection CollNum
if debug ≥ 3 then my loq_TextDoc(("Top Level Collection number:" & CollNum & "replaces Sub collection " & c_Counter & " of " & thisCollKind & " " & thisCollName), false, 3)
end if
if debug ≥ 4 then my loq_TextDoc(("Verified sub-Collection " & c_Counter & "of " & thisCollKind & " " & thisCollName), false, 4)
end if
## tell application "Capture One 11" to tell document COPDocName to tell searchColl to set {searchCollName, searchCollKind} to {name as text, kind as text}
if debug ≥ 4 then loq_TextDoc(("Starting search in " & searchCollName & " (" & searchCollKind & ") "), false, 4)
set resultPaths to my search_collection(searchColl, nextSearchLevel, searchCollName, searchCollKind) -- the search
set countResultPaths to count of resultPaths
if debug ≥ 3 then loq_TextDoc(("Result of search in " & searchCollName & " (" & searchCollKind & ") is: " & resultPaths), false, 4)
if countResultPaths > 0 then
repeat with p_counter from 1 to countResultPaths
set found_paths to found_paths & (thisCollName & "<" & item p_counter of resultPaths)
end repeat
end if
end repeat
end if
if (count of found_paths) > 0 then log found_paths
return found_paths
end search_collection
on validateCOP(minCOPversionstr)
global debug
tell application "System Events"
set COPProcList to every process whose name contains "Capture One" and background only is false
if debug ≥ 2 then
set COPProcNameList to name of every process whose name contains "Capture One" and background only is false
my loq_TextDoc(COPProcNameList, false, 2)
end if
end tell
if (count of COPProcList) = 0 then my loqqed_exit("COP is not running")
if (count of COPProcList) ≠1 then my loqqed_exit("Unexpected: >1 COP instances")
set theAppRef to item 1 of COPProcList
tell application "System Events" to set theAppName to ((get name of theAppRef) as text)
tell application "System Events" to set copDetailedVersion to get version of my application theAppName
tell application "Capture One 11" to set copVersion to (get app version)
if debug ≥ 2 then
--properties of application "Capture One 11"
tell application "System Events"
my loq_TextDoc((get name of every process whose background only is false), false, 2)
end tell
my loq_TextDoc(("theAppName: " & theAppName), false, 2)
my loq_TextDoc(("COP Version: " & copVersion), false, 2)
my loq_TextDoc(("COP Detailed Version: " & copDetailedVersion), false, 2)
end if
if the theAppName ≠"Capture One 11" then
display notification "Wrong COP Application"
my loqqed_exit("Found COP Application " & theAppName & " The only supported COP application is Capture One 11")
end if
set numCOPversion to (splitStringToList((word -1 of copVersion), "."))
set minCOPversion to (splitStringToList(minCOPversionstr, "."))
set digit_mult to 1000000
set Version_digit to 0
repeat with dig_ctr from 1 to count of numCOPversion
set digit_mult to digit_mult / 100
set Version_digit to Version_digit + (get item dig_ctr of numCOPversion as integer) * digit_mult
end repeat
set digit_mult to 1000000
set min_digit to 0
repeat with dig_ctr from 1 to count of minCOPversion
set digit_mult to digit_mult / 100
set min_digit to min_digit + (get item dig_ctr of minCOPversion as integer) * digit_mult
end repeat
if Version_digit < min_digit then
display notification "COP Version is too low"
my loqqed_exit("This COP Version is " & (word -1 of copVersion) & " - the minimum supported COP version is " & minCOPversionstr)
end if
tell application "System Events" to set frontmost of process theAppName to true
my loq_TextDoc(("Capture One Version " & copDetailedVersion), false, 0)
end validateCOP
on validateCOPdoc(COP_kind_list)
global debug
tell application "Capture One 11"
set {current_doc_name, current_doc_kind} to (get {name, kind} of current document)
set current_doc_abs_list to (get every document whose name is current_doc_name and kind is current_doc_kind)
end tell
set current_doc_kind_s to current_doc_kind as text
if COP_kind_list does not contain current_doc_kind_s then my loqqed_exit(current_doc_name & " is a " & current_doc_kind_s & " unsupported type", true)
set number_of_hits to count of current_doc_abs_list
if number_of_hits = 0 then
my loqqed_exit("Could not find find " & current_doc_kind_s & current_doc_name)
else if number_of_hits > 1 then
my loqqed_exit("Found more than one " & current_doc_kind_s & " with the name " & current_doc_name)
else
set current_doc_abs to item 1 of current_doc_abs_list
end if
my loq_TextDoc(("Capture One " & current_doc_kind_s & ": " & current_doc_name), false, 0)
return {current_doc_name, current_doc_abs}
end validateCOPdoc
on open_TextDoc(DocName_Ext)
global debug, Script_Title, Result_Doc_ref, SE_Logging
set target_folder_name to "ScriptReports"
tell current application to set date_string to (current date) as text
set target_folder_p to ((POSIX path of (get path to desktop as text)) & target_folder_name)
set target_folder_a to (POSIX file target_folder_p) as string
set Result_Doc_Path_p to target_folder_p & "/" & DocName_Ext
set Result_Doc_Path_a to (POSIX file Result_Doc_Path_p) as string
tell application "System Events" to if not (exists (alias (target_folder_a))) then ¬
tell application "Finder" to make new folder at desktop with properties {name:target_folder_name}
tell application "System Events" to if not (exists (alias (Result_Doc_Path_a))) then
set First_line to ("Created " & date_string & return)
do shell script "echo " & First_line & " > " & """ & Result_Doc_Path_p & """
if (debug ≥ 1) and SE_Logging then log Result_Doc_Path_p & First_line
end if
tell application "TextEdit" to activate
tell application "TextEdit" to set Result_Doc_ref to open Result_Doc_Path_a as alias
my loq_TextDoc((return & "Started on: " & date_string), false, 0)
return Result_Doc_Path_p
end open_TextDoc
on loq_TextDoc(logText, MakeFront, debug_class)
global Result_Doc_ref, debug, SE_Logging, Results_max_debug
set logText_class to ((get class of logText) as text)
if logText_class ≠"text" then
try
if logText_class = "list" then
set new_logText to joinListToString(logText, ", ")
else
set new_logText to logText as text
end if
set logText to new_logText
set logText_class to "text"
on error errmess
set logText to errmess
set logText_class to "text"
end try
end if
if (debug_class ≤ Results_max_debug) or not SE_Logging then
tell application "TextEdit"
set numPara to count paragraphs of the text of Result_Doc_ref
set paragraph (numPara + 1) of the text of Result_Doc_ref to ((logText as text) & return)
end tell
end if
if (debug ≥ 1) and SE_Logging then log (logText as text)
tell application "System Events" to if MakeFront then set frontmost of process "TextEdit" to true
end loq_TextDoc
on loqqed_exit(error_text)
global debug, Script_Title
my loq_TextDoc(("Script "" & Script_Title & "" has exited." & return & "Reason: " & error_text & return & return & "Halted"), true, 0)
display notification error_text
error error_text
end loqqed_exit
on splitStringToList(theString, theDelim)
set astid to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to theDelim
set theList to text items of theString
on error
set AppleScript's text item delimiters to astid
end try
set AppleScript's text item delimiters to astid
return theList
end splitStringToList
to joinListToString(theList, theDelim)
set theString to ""
set astid to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to theDelim
set theString to theList as string
on error
set AppleScript's text item delimiters to astid
end try
set AppleScript's text item delimiters to astid
return theString
end joinListToString
on indexof(theItem, theList) -- credits Emmanuel Levy
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set theList to return & theList & return
set AppleScript's text item delimiters to astid
try
-1 + (count (paragraphs of (text 1 thru (offset of (return & theItem & return) in theList) of theList)))
on error
0
end try
end indexof0 -
I have a strange issue:
I was working with the script just fine.
I then tried to change the script to display the result in notifications instead of in a text file.
I started getting some strange errors, and I reverted the code back to the original code.
But now I'm getting an error :
Script "Album for variants.scpt" has exited.
Reason: Main Catalog is a «constant ****COct» unsupported type
I restarted C1 with no luck, and even my MacBook, again without the luck.
The funny thing is that if I start the script from inside the script editor, it works just fine.
This error comes up when I start the script from inside C1.
Any ideas anyone?
Thank you,0 -
Hi Harry
I can have a look at that over the next few days. When I say "No support" I don't mean I will not look at problems. But it does mean that I won't commit to solving or fixing any problems, or adapting the script to changes in Applescrript or Capture One Pro. I have family and work commitments that take priority.
When you say you changed it to provide results in notifications, can you explain in a little more detail what you mean by that, and what did you change in the script?
I think this is crashing very early on in the script, the script or something running does not recognise the class of variable which contains the name of the catalog.[quote="Harry25" wrote:
I have a strange issue:
I was working with the script just fine.
I then tried to change the script to display the result in notifications instead of in a text file.
I started getting some strange errors, and I reverted the code back to the original code.
But now I'm getting an error :
Script "Album for variants.scpt" has exited.
Reason: Main Catalog is a «constant ****COct» unsupported type
I restarted C1 with no luck, and even my MacBook, again without the luck.
The funny thing is that if I start the script from inside the script editor, it works just fine.
This error comes up when I start the script from inside C1.
Any ideas anyone?
Thank you,0 -
[quote="Eric Nepean" wrote:
Hi Harry
I can have a look at that over the next few days. When I say "No support" I don't mean I will not look at problems. But it does mean that I won't commit to solving or fixing any problems, or adapting the script to changes in Applescrript or Capture One Pro. I have family and work commitments that take priority.
When you say you changed it to provide results in notifications, can you explain in a little more detail what you mean by that, and what did you change in the script?
I think this is crashing very early on in the script, the script or something running does not recognise the class of variable which contains the name of the catalog.[quote="Harry25" wrote:
I have a strange issue:
I was working with the script just fine.
I then tried to change the script to display the result in notifications instead of in a text file.
I started getting some strange errors, and I reverted the code back to the original code.
But now I'm getting an error :
Script "Album for variants.scpt" has exited.
Reason: Main Catalog is a «constant ****COct» unsupported type
I restarted C1 with no luck, and even my MacBook, again without the luck.
The funny thing is that if I start the script from inside the script editor, it works just fine.
This error comes up when I start the script from inside C1.
Any ideas anyone?
Thank you,
The script is working fine - it was working for me for days now.
today I tried some changes, and because they didn't work I pasted your whole code again.
(I was trying to replace the code that writes to the textedit with "display notification")
Since it's working fine from the editor, I assume that something must have been cached someplace in C1 or the AppleScript engine .
That's why I tried the reboots.
I even created a new script (with a different name) and your code, and I'm still getting the same error.0 -
I found the problem, it's a new Capture One Applescript bug. I will make a workaround, and include an option to not generate a textedit file.
If you run an Applescript from Script Editor, and you execute any of the Applescripts below, then you will get correct behaviour, and current_doc_kind_s will be "catalog" or "session"
But if you execute the same code while running the script as an application from Capture One 11 then you will get unexpected results:
"«constant ****COct»" instead of "catalog" and "«constant ****COsd»" instead of "session"
(There was a similar bug with the kind of a collection in Capture One 10.1)
This of course plays merry hell when determining if the document is a catalog or session "catalog" or "session"tell application "Capture One 11"
set currentDocRef to current document
set current_doc_kind_s to (get kind of currentDocRef) as text
end tell
## or this
tell application "Capture One 11"
set current_doc_kind_s to (get kind of current document) as text
end tell
## or this
tell application "Capture One 11" to set current_doc_kind_s to (get kind of current document) as text0 -
Here is a version that runs from Apple's Script Editor and can run from Capture One Pro's script menu. The recently observed bugs and crashes have been fixed. This version one to choose reporting by a Text Edit file, via a Dialog Window or via Notifications by setting True and False variables in the first few lines of Applescript.
-- Applescript to search a COP 11 Catalog for Collections containing the Image of a selected variant
-- Version 1.18 !! NO SUPPORT !! Eric Valk, Ottawa, Canada
-- ***To Initialise
-- Start Script Editor, open a new (blank) file, copy and paste all of this code into the file, compile (hammer symbol) and save.
-- Best if you make "Scripts" folder somewhere handy in your Douments or Desktop
-- *** Operation
-- Open the compiled and saved file
-- Open the Script Editor log window, and select the messages tab
-- Select only a small number of variants, from any collection.
-- Run the script
-- Results appear first in the AppleScript Log when the search for each variant is completed, and in Display Dialog Windows when all searching is completed
-- This script does not write or delete any information in the COP Catalog or Session or the image file
set debug to 0
set enableResultsFile to true
set enableResultsByDialog to false
set enableNotifications to true
set ResultsFileMaxDebug to 3
set maxProgressLevel to 3
set maxSearchlevel to 100
property searchTimePerVariant : 0
set WarnMaxVariants to 4
set WarnSearchTime to 30
set SearchDiskFileSystem to false
set SearchRecentImports to false
set SearchRecentCaptures to false
set SearchTrash to false
if SearchDiskFileSystem then
set ExcludedTopCollectionKinds to {""}
else
set ExcludedTopCollectionKinds to {"catalog folder"}
end if
set ExcludedTopCollectionNames to {"In Catalog", "Catalog", "All Images"}
set ExcludedSubCollectionNames to {""} -- used for testing
set StopSearchAtProject to false
if not SearchRecentImports then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Recent Imports"
if not SearchRecentCaptures then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Recent Captures"
if not SearchTrash then set ExcludedTopCollectionNames to ExcludedTopCollectionNames & "Trash"
tell application "System Events" to set parent_name to name of current application
tell application "Finder"
set script_path to path to me
set Script_Title to name of file script_path as text
end tell
set SE_Logging to (parent_name = "Script Editor")
if enableResultsFile then
set Result_DocName to "COP_Image_Search.txt"
else
set Result_DocName to "Not Enabled"
end if
set ResultMethod to my InitializeLoqqing(Result_DocName)
my loq_Results("Action: Find collections where images are located", false, 0)
my loq_Results(Script_Title & " started from: " & parent_name, false, 0)
set minCOPversion to "11.0.1"
validateCOP(minCOPversion)
set {COPDocName, COPDocKind_s, COPDocRef} to validateCOPdoc({"catalog", "session"})
set options_display_string to "Debug Level: " & debug
set options_display_string to options_display_string & return & "Highest Debug Class in Result File: " & ResultsFileMaxDebug
set options_display_string to options_display_string & return & "Maximum Search Level: " & maxSearchlevel
set options_display_string to options_display_string & return & "Enable Results in Notifications: " & enableNotifications
set options_display_string to options_display_string & return & "Results: " & ResultMethod
set options_display_string to options_display_string & return & "Maximum Level in Progress Bar: " & maxProgressLevel
set options_display_string to options_display_string & return & "Estimated Search Time per Variant: "
if searchTimePerVariant = 0 then
set options_display_string to options_display_string & "unknown"
else
set options_display_string to options_display_string & searchTimePerVariant
end if
set options_display_string to options_display_string & return & "Search Managed Files: " & false
set options_display_string to options_display_string & return & "Search Referenced Files: " & SearchDiskFileSystem
set options_display_string to options_display_string & return & "Search Recent Imports: " & SearchRecentImports
set options_display_string to options_display_string & return & "Search Recent Captures: " & SearchRecentCaptures
set options_display_string to options_display_string & return & "Search All Images: " & false
set options_display_string to options_display_string & return & "Search COP Trash: " & false
set options_display_string to options_display_string & return & "Other Excluded Collections: " & ExcludedSubCollectionNames
set options_display_string to options_display_string & return & "Do Not Search below Projects: " & StopSearchAtProject
tell application "System Events" to set frontmost of process parent_name to true
try
set dialog_result to display dialog options_display_string with title Script_Title
on error errmess
my loqqed_exit("User Cancelled the Script")
end try
if debug ≥ 1 then my loq_Results((return & "Options:" & return & options_display_string & return), false, 1)
tell application "Capture One 11" to tell document COPDocName
set everyTopCollection to get every collection
set {namesTopCollections, kindsTopCollections_p} to {name, kind} of every collection
set lastCollectionIndex to count of everyTopCollection
set kindOfLastCollection_p to (get kind of collection lastCollectionIndex) as text
set nameOfLastCollection to (get name of collection lastCollectionIndex) as text
set kindOf2ndLastCollection_p to (get kind of collection (lastCollectionIndex - 1)) as text
set nameOf2ndLastCollection to (get name of collection (lastCollectionIndex - 1)) as text
end tell
set kindOfLastCollection_s to convertKind(kindOfLastCollection_p)
set kindOf2ndLastCollection_s to convertKind(kindOf2ndLastCollection_p)
if kindOfLastCollection_s = "catalog folder" then
## last collection definitely is NOT the selected collection
set max_search_coll_index to lastCollectionIndex
set selected_collection_index to 0
else if kindOf2ndLastCollection_s = "catalog folder" then
## last collection definitely IS the selected collection
set max_search_coll_index to lastCollectionIndex - 1
set selected_collection_index to lastCollectionIndex
else
## The last two collections are not catalog folders. Likely there are no catalog folders, all images are stored in the catalog
if nameOfLastCollection = "In Catalog" then
## last collection definitely is NOT the selected collection
set max_search_coll_index to lastCollectionIndex
set selected_collection_index to 0
else if nameOf2ndLastCollection = "In Catalog" then
## last collection definitely IS the selected collection
set max_search_coll_index to lastCollectionIndex - 1
set selected_collection_index to lastCollectionIndex
else
## Undetermined and unexpected collection arrangement
loq_Results(("Unexpected Collection Structure #" & ¬
(lastCollectionIndex - 1) & " " & kindOf2ndLastCollection_p & " " & nameOf2ndLastCollection & ¬
" #" & lastCollectionIndex & " " & kindOfLastCollection_p & " " & nameOfLastCollection), false, 0)
loq_Results(("Unexpected Collection Structure"), false, 0)
loq_Results(("Collection #" & (lastCollectionIndex - 1) & " (" & kindOf2ndLastCollection_p & ") " & kindOf2ndLastCollection_s & " " & nameOf2ndLastCollection), false, 0)
loq_Results(("Collection #" & lastCollectionIndex & " (" & kindOfLastCollection_p & ") " & kindOfLastCollection_s & " " & nameOfLastCollection), false, 0)
set max_search_coll_index to lastCollectionIndex
set selected_collection_index to lastCollectionIndex
end if
end if
tell application "Capture One 11" to set selectedVariants to (get selected variants)
set countSelectedVariants to count of selectedVariants
if debug ≥ 3 then my loq_Results(("In this window " & (count of selectedVariants) & " Selected Variants"), false, 3)
if countSelectedVariants = 0 then
display alert "No images selected - select one or more images"
my loqqed_exit("No images selected")
else
set estimatedDuration to countSelectedVariants * searchTimePerVariant
tell application "System Events" to set frontmost of process parent_name to true
try
if countSelectedVariants > WarnMaxVariants and searchTimePerVariant = 0 then
display dialog "Are you sure you want to search for " & countSelectedVariants & " variants? " with icon caution
else if estimatedDuration > WarnSearchTime then
display dialog "Are you sure you want to search for " & countSelectedVariants & " variants? Estimated time: " & estimatedDuration & " seconds" with icon caution
end if
on error errmess
my loqqed_exit("User Cancelled the Script")
end try
set nameSelectedVariants to {}
set idParentSelectedVariants to {}
repeat with v_Counter from 1 to countSelectedVariants
set thisVariant to item v_Counter of selectedVariants
tell application "Capture One 11"
set nameSelectedVariants to nameSelectedVariants & (get name of thisVariant)
set idParentSelectedVariants to idParentSelectedVariants & (get id of parent image of thisVariant)
end tell
end repeat
if debug ≥ 3 then
log nameSelectedVariants
log idParentSelectedVariants
end if
set startTime to get time of (get current date)
set allResults to {}
set search_executed to false
set progress total steps to countSelectedVariants
set progress completed steps to 0
set progress description to "Searching for Variants ..."
repeat with v_Counter from 1 to countSelectedVariants
set thisVariant to item v_Counter of selectedVariants
set searchedImageName to item v_Counter of nameSelectedVariants
set searchedImageID to item v_Counter of idParentSelectedVariants
set progress completed steps to v_Counter
set progress description to "Searching for Variant " & searchedImageName
if debug ≥ 2 then my loq_Results((return & "Searching for " & searchedImageName & " ID: " & searchedImageID), false, 2)
set isFound to false
set foundPaths to ""
set pathSeparator to ""
set searchLevel to 0
set nextSearchLevel to searchLevel + 1
if nextSearchLevel ≤ maxSearchlevel then
repeat with c_Counter from 1 to max_search_coll_index
set thisTopCollection to item c_Counter of everyTopCollection
set topCollName to item c_Counter of namesTopCollections
set topCollKind_s to convertKind(item c_Counter of kindsTopCollections_p)
if (ExcludedTopCollectionNames does not contain topCollName) and ¬
(ExcludedTopCollectionKinds does not contain topCollKind_s) then
set search_executed to true
if debug ≥ 3 then my loq_Results(("Search: " & topCollKind_s & " " & topCollName), false, 3)
set resultPaths to my search_collection(thisTopCollection, nextSearchLevel, topCollName, topCollKind_s) -- The search
set resultCount to count of resultPaths
if debug ≥ 3 then my loq_Results(("Result of search in " & topCollName & " (" & topCollKind_s & ") is: " & resultPaths), false, 3)
if resultCount > 0 then
set isFound to true
repeat with p_counter from 1 to count of resultPaths
set foundPaths to foundPaths & pathSeparator & item p_counter of resultPaths
set pathSeparator to return -- after the first path is added the separator become the newline character /r
end repeat
end if
else
if debug ≥ 3 then my loq_Results(("Reject: " & topCollKind_s & " " & topCollName), false, 3)
end if
end repeat
end if
if not search_executed then -- there are no top level collections to search - don't keep searching
display notification "No Top Level Collections to Search"
my loqqed_exit("No Top Level Collections to Search")
end if
if isFound then
set thisResult to {v_Counter, searchedImageName, true, foundPaths}
my loq_Results((return & searchedImageName & " was found in:" & return & foundPaths), false, 0)
if debug ≥ 2 then display notification searchedImageName & " was found"
else
set thisResult to {v_Counter, searchedImageName, false, foundPaths}
my loq_Results((return & searchedImageName & " was not found"), false, 0)
display notification searchedImageName & " was not found"
end if
set allResults to allResults & thisResult
end repeat
set stopTime to get time of (get current date)
if stopTime < startTime then set startTime to startTime - 86400 -- the search started yesterday and ended today
set elapsedtime to stopTime - startTime
set searchTimePerVariant to elapsedtime / countSelectedVariants
my loq_Results((return & "This search took " & elapsedtime & " seconds (" & searchTimePerVariant & "s per variant)" & return & return & "Done"), true, 0)
say "Finished!"
end if
tell application "System Events" to set frontmost of process "Capture One 11" to true
if enableResultsFile then tell application "System Events" to set frontmost of process "TextEdit" to true
--Handlers -------------------
on search_collection(thisCollection, searchLevel, thisCollName, thisCollKind)
-- recursive handler to search a collection and it's subcollections
-- if successful, returns a list of paths each as a text string
global debug, maxSearchlevel, searchedImageID, searchedImageName, COPDocName, StopSearchAtProject, ExcludedSubCollectionNames, selected_collection_index, maxProgressLevel, enableNotifications
set found_paths to {} -- initialise the list
if ExcludedSubCollectionNames contains thisCollName then return found_paths
if searchLevel ≤ maxProgressLevel then set progress additional description to thisCollKind & " " & thisCollName
tell application "Capture One 11" to tell document COPDocName to tell thisCollection
set searchImageIDhits to count of (get every image whose id is searchedImageID)
set listSubcollsthisColl to every collection
tell me to set countSubcollsthisColl to count of listSubcollsthisColl
if countSubcollsthisColl > 0 then set {namesSubcollsthisColl, kindsSubcollsthisColl_p} to {name, kind} of every collection
end tell
if searchImageIDhits > 0 then
set found_paths to found_paths & (thisCollName & "(" & thisCollKind & ")")
if enableNotifications then display notification searchedImageName & " found in: " & thisCollKind & " '" & thisCollName & "'"
if debug ≥ 4 then my loq_Results(("Found " & searchImageIDhits & " hits in " & thisCollKind & " " & thisCollName), false, 4)
end if
if debug ≥ 5 then
tell application "Capture One 11" to tell document COPDocName to tell thisCollection
set countImages to count of every image
set countVariants to count of every variant
end tell
my loq_Results(("In " & thisCollKind & " " & thisCollName & " at level " & searchLevel & " found " & countImages & " images ," & countVariants & " variants ," & countSubcollsthisColl & " collections"), false, 5)
end if
set nextSearchLevel to searchLevel + 1
if (nextSearchLevel ≤ maxSearchlevel) and ¬
(not (StopSearchAtProject and thisCollKind = "project")) then
if debug ≥ 5 then my loq_Results(("Searching Collections in " & thisCollKind & " " & thisCollName & " at level " & searchLevel & " found " & countSubcollsthisColl & " collections"), false, 5)
repeat with c_Counter from 1 to countSubcollsthisColl
## tell application "Capture One 11" to tell document COPDocName to tell thisCollection to set searchColl to collection c_Counter
set searchColl to item c_Counter of listSubcollsthisColl
set searchCollName to item c_Counter of namesSubcollsthisColl
set searchCollKind_s to convertKind(get item c_Counter of kindsSubcollsthisColl_p)
if selected_collection_index ≠0 then
## A user sub-collection has been selected
## Check the collection number to trap the error caused by the selected subcollection returning an invalid referencee
try
|| of {searchColl} -- generate an error to capture error text containing the collection reference
on error CO11_errtxt number CO11_errnbr
end try
if debug ≥ 4 then loq_Results(("***Error Message " & CO11_errtxt & "; number " & CO11_errnbr & " Collection: " & c_Counter & " of " & thisCollKind & " " & thisCollName), false, 4)
## extract the collection number from the error text
if CO11_errnbr = -1728 then
set CollNum to (get last word of item 2 of splitStringToList(CO11_errtxt, "of")) as integer
else
loq_Results(("*****" & CO11_errtxt & "; number " & CO11_errnbr), false, 4)
loqqed_exit("Unexpected error when checking collection integrity")
end if
if CollNum ≠c_Counter then
## this is the selected sub collection, and must be accesed as the last top level collection in the document
if selected_collection_index ≠CollNum then
## the collection reference is wrong in some other unexpected way
loq_Results(("*****" & CO11_errtxt & "; number " & CO11_errnbr), false, 4)
loqqed_exit("Unexpected collection index when checking collection integrity: " & CollNum)
end if
## Set the collection reference to the last top level collection
tell application "Capture One 11" to tell document COPDocName to set searchColl to collection CollNum
if debug ≥ 3 then my loq_Results(("Top Level Collection number:" & CollNum & "replaces Sub collection " & c_Counter & " of " & thisCollKind & " " & thisCollName), false, 3)
end if
if debug ≥ 4 then my loq_Results(("Verified sub-Collection " & c_Counter & " of " & thisCollKind & " " & thisCollName), false, 4)
end if
if debug ≥ 4 then loq_Results(("Starting search in " & searchCollName & " (" & searchCollKind_s & ") "), false, 4)
set resultPaths to my search_collection(searchColl, nextSearchLevel, searchCollName, searchCollKind_s) -- the search
set countResultPaths to count of resultPaths
if debug ≥ 3 then loq_Results(("Result of search in " & searchCollName & " (" & searchCollKind_s & ") is: " & resultPaths), false, 4)
if countResultPaths > 0 then
repeat with p_counter from 1 to countResultPaths
set found_paths to found_paths & (thisCollName & "<" & item p_counter of resultPaths)
end repeat
end if
end repeat
end if
## if (count of found_paths) > 0 then log found_paths
return found_paths
end search_collection
on validateCOP(minCOPversionstr)
global debug
tell application "System Events"
set COPProcList to every process whose name contains "Capture One" and background only is false
if debug ≥ 2 then
set COPProcNameList to name of every process whose name contains "Capture One" and background only is false
my loq_Results("COP Processes:" & COPProcNameList, false, 2)
end if
end tell
if (count of COPProcList) = 0 then my loqqed_exit("COP is not running")
if (count of COPProcList) ≠1 then my loqqed_exit("Unexpected: >1 COP instances")
set theAppRef to item 1 of COPProcList
tell application "System Events" to set theAppName to ((get name of theAppRef) as text)
tell application "System Events" to set copDetailedVersion to get version of my application theAppName
tell application "Capture One 11" to set copVersion to (get app version)
if debug ≥ 2 then
--properties of application "Capture One 11"
tell application "System Events"
my loq_Results(("All Processes: " & (get my joinListToString((get name of every process whose background only is false), ", "))), false, 2)
end tell
my loq_Results(("theAppName: " & theAppName), false, 2)
my loq_Results(("COP Version: " & copVersion), false, 2)
my loq_Results(("COP Detailed Version: " & copDetailedVersion), false, 2)
end if
if the theAppName ≠"Capture One 11" then
display notification "Wrong COP Application"
my loqqed_exit("Found COP Application " & theAppName & " The only supported COP application is Capture One 11")
end if
set numCOPversion to (splitStringToList((word -1 of copVersion), "."))
set minCOPversion to (splitStringToList(minCOPversionstr, "."))
set digit_mult to 1000000
set Version_digit to 0
repeat with dig_ctr from 1 to count of numCOPversion
set digit_mult to digit_mult / 100
set Version_digit to Version_digit + (get item dig_ctr of numCOPversion as integer) * digit_mult
end repeat
set digit_mult to 1000000
set min_digit to 0
repeat with dig_ctr from 1 to count of minCOPversion
set digit_mult to digit_mult / 100
set min_digit to min_digit + (get item dig_ctr of minCOPversion as integer) * digit_mult
end repeat
if Version_digit < min_digit then
display notification "COP Version is too low"
my loqqed_exit("This COP Version is " & (word -1 of copVersion) & " - the minimum supported COP version is " & minCOPversionstr)
end if
tell application "System Events" to set frontmost of process theAppName to true
my loq_Results(("Capture One Version " & copDetailedVersion), false, 0)
end validateCOP
on validateCOPdoc(COP_kind_list)
global debug
tell application "Capture One 11"
set {current_doc_name, current_doc_kind_p} to (get {name, kind} of current document)
set current_doc_ref_list to (get every document whose name is current_doc_name and kind is current_doc_kind_p)
set number_of_hits to count of current_doc_ref_list
end tell
set current_doc_kind_s to convertKind(current_doc_kind_p)
if debug ≥ 5 then loq_Results(("Is: " & current_doc_kind_s & " was: " & (get current_doc_kind_p as text)), false, 2)
if debug ≥ 2 then loq_Results(("Found Documents: " & number_of_hits), false, 2)
if COP_kind_list does not contain current_doc_kind_s then loq_Results(current_doc_name & " is a " & current_doc_kind_s & " -- unsupported type of document", false, 0)
if number_of_hits = 0 then
my loqqed_exit("Could not find find " & current_doc_kind_s & current_doc_name)
else if number_of_hits > 1 then
my loqqed_exit("Found more than one " & current_doc_kind_s & " with the name " & current_doc_name)
else
tell application "Capture One 11" to set current_doc_ref to item 1 of current_doc_ref_list
end if
my loq_Results(("Capture One Document: " & current_doc_kind_s & " " & current_doc_name), false, 0)
return {current_doc_name, current_doc_kind_s, current_doc_ref}
end validateCOPdoc
on InitializeLoqqing(DocName_Ext)
global debug, Script_Title, Result_Doc_ref, SE_Logging, enableResultsFile, enableResultsByDialog, DialogTextList
tell current application to set date_string to (current date) as text
set ResultMethod_p to {}
if enableResultsFile then
set target_folder_name to "ScriptReports"
set target_folder_p to ((POSIX path of (get path to desktop as text)) & target_folder_name)
set target_folder_a to (POSIX file target_folder_p) as string
set Result_Doc_Path_p to target_folder_p & "/" & DocName_Ext
set Result_Doc_Path_a to (POSIX file Result_Doc_Path_p) as string
tell application "System Events" to if not (exists (alias (target_folder_a))) then ¬
tell application "Finder" to make new folder at desktop with properties {name:target_folder_name}
tell application "System Events" to if not (exists (alias (Result_Doc_Path_a))) then
set First_line to ("Created " & date_string & return)
do shell script "echo " & First_line & " > " & """ & Result_Doc_Path_p & """
if (debug ≥ 1) and SE_Logging then log Result_Doc_Path_p & First_line
end if
tell application "TextEdit" to activate
tell application "TextEdit" to set Result_Doc_ref to open Result_Doc_Path_a as alias
set ResultMethod_p to ResultMethod_p & Result_Doc_Path_p
end if
if enableResultsByDialog then
set DialogTextList to {}
set ResultMethod_p to ResultMethod_p & "Display Dialog"
end if
my loq_Results(("Started on: " & date_string), false, 0)
return joinListToString(ResultMethod_p, ", ")
end InitializeLoqqing
on loq_Results(logText, MakeFront, debug_class)
global Result_Doc_ref, debug, SE_Logging, ResultsFileMaxDebug, enableResultsFile, enableResultsByDialog, DialogTextList
set logText_class to ((get class of logText) as text)
if logText_class ≠"text" then
try
if logText_class = "list" then
set new_logText to joinListToString(logText, ", ")
else
set new_logText to logText as text
end if
set logText to new_logText
set logText_class to "text"
on error errmess
set logText to errmess
set logText_class to "text"
end try
end if
if ((debug_class ≤ ResultsFileMaxDebug) or not SE_Logging) then
if enableResultsFile then
tell application "TextEdit"
set numPara to count paragraphs of the text of Result_Doc_ref
set paragraph (numPara + 1) of the text of Result_Doc_ref to ((logText as text) & return)
end tell
tell application "System Events" to if MakeFront then set frontmost of process "TextEdit" to true
end if
if enableResultsByDialog then
set DialogTextList to DialogTextList & logText
if MakeFront then display dialog joinListToString(DialogTextList, return)
end if
end if
if SE_Logging then log (logText as text)
end loq_Results
on loqqed_exit(error_text)
global debug, Script_Title
my loq_Results(("Script "" & Script_Title & "" has exited." & return & "Reason: " & error_text & return & return & "Halted"), true, 0)
display notification error_text
error error_text
end loqqed_exit
on splitStringToList(theString, theDelim)
set astid to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to theDelim
set theList to text items of theString
on error
set AppleScript's text item delimiters to astid
end try
set AppleScript's text item delimiters to astid
return theList
end splitStringToList
to joinListToString(theList, theDelim)
set theString to ""
set astid to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to theDelim
set theString to theList as string
on error
set AppleScript's text item delimiters to astid
end try
set AppleScript's text item delimiters to astid
return theString
end joinListToString
on indexof(theItem, theList) -- credits Emmanuel Levy
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set theList to return & theList & return
set AppleScript's text item delimiters to astid
try
-1 + (count (paragraphs of (text 1 thru (offset of (return & theItem & return) in theList) of theList)))
on error
0
end try
end indexof
on convertKind(kind_p)
global debug
set kind_s to kind_p as text
if (get text 1 of kind_s) ≠"«" then
return kind_s
else
set code_start to (get length of kind_s) - 4
set kind_code to get (text code_start thru (code_start + 3) of kind_s)
if kind_code = "CCpj" then
set kind_res to "project"
else if kind_code = "CCgp" then
set kind_res to "group"
else if kind_code = "CCal" then
set kind_res to "album"
else if kind_code = "CCsm" then
set kind_res to "smart album"
else if kind_code = "CCfv" then
set kind_res to "favorite"
else if kind_code = "CCff" then
set kind_res to "catalog folder"
else if kind_code = "COct" then
set kind_res to "catalog"
else if kind_code = "COsd" then
set kind_res to "session"
else
loqqed_exit("Unexpected Kind string: " & kind_s)
end if
end if
return kind_res
end convertKind
For those who haven't tried running Applescript from Capture One Pro's script menu before, you copy the code into Script Editor's window, and save its as as file type Application. Let's say you call it "COP Image Search.app".
Then click on Capture Ones "Scripts" menu, click on "Open Scripts Folder", this opens a new Finder window, for me this is at ~/Library/Scripts/Capture One". Using Finder, copy the the new "COP Image Search.app" file here.
Now click again on Capture Ones "Scripts" menu, click on "Update Scripts".
The new script "COP Image Search" will appear in Capture Ones "Scripts" menu. When you click on it, Capture One runs the Applescript.0 -
This is really useful. Thank you 😄 0
Post is closed for comments.
Comments
7 comments