Script to Find Collections holding an Image

Discussion regarding all scripting related questions
Please DO NOT post to this thread anything that is not directly related to scripting of Capture One.

Script to Find Collections holding an Image

Postby Eric Nepean » Wed Feb 28, 2018 6:34 am

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.

Code: Select all
-- 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
Cheers, Eric
[late 2015 iMac, 4GHz i7, 24GB RAM, external SSDs. GX8, E-M1, GX7, GM5, GM1 ....]
Eric Nepean
 
Posts: 419
Joined: Sat Oct 25, 2014 8:02 am
Location: Ottawa

Re: Script to Find Collections holding an Image

Postby Eric Nepean » Sat Mar 03, 2018 7:00 am

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.

Code: Select all
-- 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 indexof
Cheers, Eric
[late 2015 iMac, 4GHz i7, 24GB RAM, external SSDs. GX8, E-M1, GX7, GM5, GM1 ....]
Eric Nepean
 
Posts: 419
Joined: Sat Oct 25, 2014 8:02 am
Location: Ottawa

Re: Script to Find Collections holding an Image

Postby Harry25 » Sat Mar 03, 2018 2:06 pm

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,
Harry25
 
Posts: 29
Joined: Thu Feb 26, 2009 8:38 am

Re: Script to Find Collections holding an Image

Postby Eric Nepean » Sat Mar 03, 2018 8:17 pm

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.

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,
Cheers, Eric
[late 2015 iMac, 4GHz i7, 24GB RAM, external SSDs. GX8, E-M1, GX7, GM5, GM1 ....]
Eric Nepean
 
Posts: 419
Joined: Sat Oct 25, 2014 8:02 am
Location: Ottawa

Re: Script to Find Collections holding an Image

Postby Harry25 » Sat Mar 03, 2018 11:00 pm

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.

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.
Harry25
 
Posts: 29
Joined: Thu Feb 26, 2009 8:38 am

Re: Script to Find Collections holding an Image

Postby Eric Nepean » Sat Mar 03, 2018 11:26 pm

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"

Code: Select all
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 text
Cheers, Eric
[late 2015 iMac, 4GHz i7, 24GB RAM, external SSDs. GX8, E-M1, GX7, GM5, GM1 ....]
Eric Nepean
 
Posts: 419
Joined: Sat Oct 25, 2014 8:02 am
Location: Ottawa

Re: Script to Find Collections holding an Image

Postby Eric Nepean » Sun Mar 04, 2018 5:45 am

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.

Code: Select all
-- 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.
Cheers, Eric
[late 2015 iMac, 4GHz i7, 24GB RAM, external SSDs. GX8, E-M1, GX7, GM5, GM1 ....]
Eric Nepean
 
Posts: 419
Joined: Sat Oct 25, 2014 8:02 am
Location: Ottawa

Re: Script to Find Collections holding an Image

Postby Moich » Wed Jun 13, 2018 5:51 am

This is really useful. Thank you :D
Moich
 
Posts: 12
Joined: Sat Feb 21, 2015 11:17 pm


Return to Scripting



Who is online

Users browsing this forum: No registered users and 3 guests