Filtering objects.

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

Filtering objects.

Postby jason.dour » Mon Jul 01, 2019 2:39 am

I've spent a good while searching through the Scripting forum, as well as finding alternate ways of doing this task, and I'm stuck. Hoping someone else might know something about why I'm unable to get quite what I want...

I'm working on a script to help me automate transitioning my large Lightroom catalogs to Capture One sessions. My goal is to split my large LR catalog into discrete sessions per photoshoot/event/what-have-you. Along the way, I'm running into a hurdle while working on a script to navigate the collections.

In short, I've attempted to filter the collections in the document to find ones that meet criteria, to operate on a select group of collections in the catalog. For example, finding every collection named "Project Photos"; this is due to a large block of these were once in Aperture, and the import into LR from Aperture added a "Project Photos" folder in the hierarchy as such:

Aperture
  • YEAR
    • YEAR.MONTH.DAY - Session

Lightroom Catalog Imported Into Capture One Catalog
  • YEAR
    • YEAR.MONTH.DAY - Session
      • Project Photos

So I'd like to find them and iterate over them to prep them for migration to separate sessions (I already have a script that does the export to a session).

I've tried the following:
Code: Select all
tell application "Capture One 12"
   set currDoc to get current document
   set tgtList to collections of currDoc whose name contains "Project Photos"
end tell


When I run this against a Session, I get a list returned of collections that meet the criteria.

When I run against a Catalog, I get a null list, UNLESS the current collection meets that criteria, and then only the current collection is returned.

So it appears that the behavior of filtering collection objects changes whether in a Session or a Catalog? Is that expected? I don't get that feeling when reading through the application's reference library with Script Editor...

Interestingly, I CAN get ALL collections by removing the filter. And then I have a list of every collection, as expected.

Am I running into a known design/feature of C1? Am I doing something fundamentally wrong from an AppleScript perspective?


Thanks!
Jason
jason.dour
 
Posts: 7
Joined: Tue Apr 04, 2017 1:47 am

Re: Filtering objects.

Postby Eric Nepean » Mon Jul 01, 2019 4:58 am

My first thought was that you had run into a subtle language issue - but now I don't think thats it.
What version of OSX and Appplescriot are you using?
(I'm on OSX12.6, Applescript 2.5 or 2.4 and Capture One 12.1)

I tried this, and it works for me.
Code: Select all
ell application "Capture One 12"
   set currDoc to get current document
   set tgtList to currDoc's collections whose name contains "Japan"
   get {name, kind} of first item of tgtList
end tell

The Replies window of Script Editor's log gives me this:
Code: Select all
tell application "Capture One 12"
   get current document
      --> document "Incoming12"
   get every collection of document "Incoming12" whose name contains "Japan"
      --> {collection id "126" of document "Incoming12"}
   get name of collection id "126" of document "Incoming12"
      --> "Japan"
   get kind of collection id "126" of document "Incoming12"
      --> project
end tell
Result:
{"Japan", project}


You do know that this command only gives the top level collection in a catalog, it doesn't give the collections within collections?

Try starting your script with this
Code: Select all
use AppleScript version "2.5"
use scripting additions
Eric Nepean
 
Posts: 615
Joined: Sat Oct 25, 2014 8:02 am
Location: Ottawa

Re: Filtering objects.

Postby jason.dour » Mon Jul 01, 2019 11:25 pm

Hey Eric. :)

I'm OSX 10.14.5, C1P 12.1.0.150, and AppleScript 2.7. I set 2.5, per your recommendation, but it still reports as 2.7 with a log call.

I did more testing. I think the key thing here is that "every collection" is not recursive...not what I would have assumed. I would have assumed "every" meant every. :D

It's definitely due to the every call not being recursive. Once I implemented a tree walk subroutine, I was able to automate the changes to them that were necessary without issue.

And the Sessions behaving differently is explained by Sessions being flat, without an opportunity for hierarchy. So of course the calls works since there is no recursion necessary.

I wouldn't have thought I'd need to implement a recursive walk subroutine thanks to the existence of "every," but hey if that's what I have to do, that's what I'll do. :)

One interesting final note on this topic. Apparently catalog folders are not hierarchical objects as they get returned as collections from the top level catalog collection from my filter calls...which explains why I was getting weird results in my output in my earlier testing. Confirmed this with log output of collection properties.

Are all AppleScript object hierarchies similarly non-recursive with "every" calls? Is this just something I don't know due to my relative low level of AppleScript knowledge compared to my knowledge in many other languages?

Thanks for the help!
jason.dour
 
Posts: 7
Joined: Tue Apr 04, 2017 1:47 am

Re: Filtering objects.

Postby Eric Nepean » Tue Jul 02, 2019 4:46 am

Hi Jason

I didn't know what version you were at so I reccomended 2.5. But I see no reason not to use 2.7.

On Macscripters forum they reccomend starting all scripts with these two lines.
The first line just ensures that you are using a fixed version, but the line use scripting additions prevents some very odd stuff happening if you have a script within your script. If you search for me there you will find a thread that explains.

As far as I know AppleScript's EVERY is not recursive under any circumstances. It only reports the elements contained by the object you are referencing, not elements contained by those elements.

I use a recursive handler for walking the collection tree, although there is a much faster but more complex way:

This works
Code: Select all
tell application "Capture One 12" to tell current document
   get every collection
   get every collection's every collection
   get every collection's every collection's every collection
end tell

so an implementation like this is possible
Code: Select all
set baseCommand to "tell application \"Capture One 12\" to tell current document to get name of every collection"
set listResult to ""
repeat 15 times
   set thisResult to run script baseCommand
   set theString to thisResult as string
   if "" = theString then exit repeat
   set listResult to listResult & (joinListToString(thisResult, ", "))
   set baseCommand to baseCommand & " of every collection"
end repeat

on joinListToString(theList, theDelim)
   ## Public Domain
   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
   end try
   set AppleScript's text item delimiters to astid
   return theString
end joinListToString

This gets the data very quickly, but I haven't worked out a good way to get that data in useable form.

The other tricky question is "how do I discover the parent collection of this collection". There is no parent property for a collection. I have worked out a way to do this.
Eric Nepean
 
Posts: 615
Joined: Sat Oct 25, 2014 8:02 am
Location: Ottawa

Re: Filtering objects.

Postby jason.dour » Tue Jul 02, 2019 8:59 pm

Oooh, that baseCommand trick is ingenious. I dig it!

I solved it with a more traditional recursive walk:
Code: Select all
on walk(coll, prnt)
   tell application "Capture One 12"
      set allColl to collections of coll
      if (count of allColl) > 0 then
         collFix(coll, prnt)
         repeat with eachColl in allColl
            my walk(eachColl, coll)
         end repeat
      else
         collFix(coll, prnt)
      end if
   end tell
end walk

tell application "Capture One 12"
   set currDoc to get current document
   my walk(current collection of currDoc, currDoc)
end tell


I then had a subroutine that performed the actions on the collections that needed some tweaks, and then exported them as separate Sessions.

Note that I'm solving the parent question by providing it with the walk subroutine. :) Your way of calling for a non-existent property of the object and trapping and parsing the error is also ingenious...well done! I stumbled across it while working on this script for mass exodus of Lightroom. When I won't be using a recursive tree walk solution, your solution will be a great way to get that information!

Always more than one way to solve things...I'll have to play with your baseCommand trick...and I'll be keeping an eye out for more of your work...I like the way you think. I just need to get my AppleScript skills on par with my other programming language skills. :)

Thanks!
jason.dour
 
Posts: 7
Joined: Tue Apr 04, 2017 1:47 am


Return to Scripting



Who is online

Users browsing this forum: No registered users and 1 guest