Skip to main content

⚠️ Please note that this topic or post has been archived. The information contained here may no longer be accurate or up-to-date. ⚠️

Create User Collections to Mitigate 'opaque' Folders in Folders Tab.

Comments

5 comments

  • Eric Valk

    Hi Quentin, nice script.   I compiled it but didn't run it, yet.

    Initially it refused to compile since I don't have the "AS Progress" application. I had to remove all references to "AS Progress" to allow it to complile.  Is there any chance you can post the code for this application?

    I note your limitation to three levels. If you write that part as a recursive handler, you will be able be able to handle an arbitrary number of levels.

    0
  • Eric Valk

    Hi Quentin, I found that if you paste Applescript code, select all the code just pasted, and then click the insert code button, all the selected text, e.g. your entire script, is put into code format.

    All the indentation is lost, which may not be a problem as the Applescript compiler will insert the correct indentation. Its not clear if there will be issues with any special AppleScript symbols.

    0
  • Quentin Black

    Ah, I forgot it wouldn't compile without my supporter app. That app, AS Progress, is something I wrote in Xcode, Objective-C, as my first scriptable cocoa app.  Too much code for here, I suspect! It has rough edges but fills a gaping void left by barebones Applescript.

    Regarding recursion: to be honest, I only just worked out that you can put groups inside projects.  But they behave in slightly weird ways.  The whole point of this project for me (sorry, bad choice of word)... the whole point of this exercise was to give me an expanding view of years and months. If you put a group inside a project, the (photo) contents of that group don't seem to be shown in the browser/viewer until you select a member of that group, such as another album, so the "transparency" benefit is lost.  You may as well select a branch of the Folder view and see only its subfolder names.  Groups never show you their ulitmate photo members when selected, it seems.  Also, you can only have projects at the top level, apparently.  So there is some degree of recursion in this Group/Project/Album model, but it's not very elegant nor consistent.  Another weirdness: if you do have a group inside a project and an album in that group, then selecting the project does indeed show you the members of the bottom album. But selecting the group still doesn't.  So I personally find that of little benefit and am happy with the 3-tier model (with apologies to people in Tier-3 Britain).

    But there's nothing wrong in adapting this and I'd love to learn that I am wrong.

    I'll try to post the script without references to AS Progress the way you detail in your other post.  Sounds like quite an ordeal.  But hey, it seems to have worked!  How did you work that out?

    use AppleScript version "2.4" -- Yosemite (10.10) or later
    use scripting additions
    use framework "Foundation"

    property scriptTitle : "Group Project Album"
    -- You can edit this line to point to your starting Photos location so:
    -- property defaultPhotoLocation : alias "Data:Photos:"
    -- But the script will store your preferred starting location after the first run.
    property defaultPhotoLocation : missing value

    -- classes, constants, and enums used
    property NSArray : a reference to current application's NSArray
    property NSPredicate : a reference to current application's NSPredicate

    set doLoop to true
    repeat while doLoop is true
    set msg to "This script takes a folder hierarchy spanning at least three levels to create or maintain User Collections reflecting this hierarchy as:" & linefeed & linefeed & "Group ➤ Project ➤ Album." & linefeed & linefeed & "Example folder structure:" & linefeed & "Camera Model ➤ Year ➤ Month [ ➤ Day ] ➤ Photos" & linefeed & linefeed & "Resulting User Collections:" & linefeed & "Camera Model (Group) ➤ Year (Project) ➤ Month (Album)" & linefeed & linefeed & "Variants from all folders under the Month would be combined in this case into the one album for that month." & linefeed & linefeed & "It prompts for the folder to become your Project; does not create duplicates on repeated execution."

    tell application "Capture One 20" to display dialog msg with title scriptTitle buttons {"Photo Location…", "Cancel", "Run"} default button "Run" with icon 1
    set br to button returned of the result
    if (br is "Photo Location…") or defaultPhotoLocation is missing value then
    set defaultPhotoLocation to my getDefaultPhotoLocation()
    end if
    if br is "Run" then
    set doLoop to false
    end if
    end repeat

    try
    set parentFolder to choose folder with prompt "Select the folder you want as your Project. It will be created, if it doesn't exist, inside a Group collection named from its parent folder." & linefeed & "Its immediate subfolders will be represented by Albums inside the Project containing their entire contents." default location defaultPhotoLocation
    on error errMsg number errNum
    if errNum is -128 then
    --don't proceed as for a 'User Cancelled' error as then any change of script property (default photo folder) won't register
    return
    end if
    end try

    delay 0.1

    set saveTID to AppleScript's text item delimiters
    set AppleScript's text item delimiters to {":"}
    set pathComponents to text items of (parentFolder as text)

    -- Last path item will provide the Project name; 1st-level enclosed folders will become Albums beneath
    set projectName to text item -2 of pathComponents

    -- Second-last path item will provide the Group name, maybe a camera model, etc.
    set groupName to text item -3 of pathComponents

    set AppleScript's text item delimiters to saveTID


    set matchingFolders to {}
    tell application "Capture One 20"
    -- Get folders (locations) for every listed folder
    set theFolders to folder of every collection of document 1 whose kind is catalog folder

    -- convert this to a text list for filtering with NSPredicate
    repeat with i from 1 to count theFolders
    set item i of theFolders to item i of theFolders as text
    end repeat

    (*
    --The slo-ow way
    repeat with f in theFolders
    set textFolder to (folder of f) as text
    if textFolder starts with (parentFolder as text) then
    log textFolder
    copy textFolder to end of matchingFolders
    end if
    end repeat
    *)

    end tell

    -- Refine list of folders to only those beneath our parent folder.
    -- Leverage ASObjC for speed but note need with Mojave and later to keep
    -- Cocoa variables inside a handler and pass AS list back out.
    -- This is just so our persistent property for default photo location works. See:
    -- https://forum.latenightsw.com/t/mojave-and-applescript-applets/1563/2
    set filteredFolders to my filterFolders(theFolders, parentFolder as text)


    if (count of filteredFolders) is 0 then
    -- No folders matching this project in CO (only in Finder)
    display dialog "Folder '" & projectName & "' of '" & groupName & "' has not been imported into Capture One." buttons {"Quit"} default button "Quit" with title scriptTitle with icon stop
    return
    end if

    tell application "Capture One 20"

    -- Get/make the var groupName to the enclosing folder. This is the enclosing Group for each year's Project. Maybe relates to camera model.

    try
    set theGroup to some collection of document 1 whose name is groupName and kind is group
    on error errMsg number errNum
    --log "Error " & errNum & ": " & errMsg
    if errNum is -1730 then -- Container specified was an empty list
    -- new top-level group
    tell document 1 to set theGroup to (make new collection with properties {name:groupName, kind:group})
    else
    display dialog "Error " & errNum & ": " & errMsg buttons {"Quit"} default button "Quit" --cancel button "Quit"
    end if
    end try

    -- Get/make project. Maybe for Year.
    try
    set theProject to some collection of theGroup whose name is projectName and kind is project
    on error errMsg number errNum
    if errNum is -1730 then -- Container specified was an empty list
    -- new project for the year
    tell theGroup to set theProject to make collection with properties {kind:project, name:projectName}
    else
    display dialog "Error " & errNum & ": " & errMsg buttons {"Quit"} default button "Quit" --cancel button "Quit"
    end if
    end try

    end tell

    tell application "System Events"
    set subFolders to name of folders of parentFolder
    end tell

    -- Make an album for each direct subfolder
    repeat with subFolder in subFolders

    set pathToAlbum to (parentFolder as text) & subFolder & ":"

    set albumFolders to my filterFolders(filteredFolders, pathToAlbum)

    set albumVariants to {}

    tell application "Capture One 20"

    repeat with a in albumFolders
    set dFolder to (some collection of document 1 whose folder is file a)
    -- add these variants to those for the whole ablum
    set albumVariants to albumVariants & variants of dFolder
    end repeat

    if (count of albumVariants) ≠ 0 then
    -- check destination album
    try
    set theAlbum to (some collection of theProject whose name is subFolder and kind is album)
    on error errMsg number errNum
    if errNum is -1730 then -- Container specified was an empty list
    tell theProject to set theAlbum to make collection with properties {kind:album, name:subFolder}
    else
    display dialog "Error " & errNum & ": " & errMsg buttons {"Quit"} default button "Quit" --cancel button "Quit"
    end if
    end try

    add inside theAlbum variants albumVariants

    end if

    end tell

    end repeat




    -- Separate handler required to keep Cocoa variables out of top level of script
    on filterFolders(theFolders, parentFolderText)
    set nsFolders to NSArray's arrayWithArray:theFolders
    set thePredicate to NSPredicate's predicateWithFormat_("SELF BEGINSWITH %@", parentFolderText)
    set nsFilteredFolders to (nsFolders's filteredArrayUsingPredicate:thePredicate)
    return nsFilteredFolders as list
    end filterFolders


    on getDefaultPhotoLocation()
    if defaultPhotoLocation is missing value then
    set dpl to path to pictures folder from user domain
    else
    set dpl to defaultPhotoLocation
    end if
    tell application "Capture One 20" to choose folder with prompt "Select the folder you'd like as your default photo location." & linefeed & "This is where the Folder-picker window will default to each time you run the script." default location dpl
    return result
    end getDefaultPhotoLocation
    0
  • Eric Valk

    Hi Quentin

    I am aware of the idiosyncracies of the Group type collection

    There is a native Capture One feature that may acheive your objectives, perhaps even better than the method you are trying, or perhaps in combination with it.

    In Capture One select the "All Images" folder (but you can select other folders to narrow down the search)

    On the Filter Tool, (by default on the Library tool tab), click on the three dot symbol on the top right, then on the drop down click on the item Show/Hide Filters. This brings up a the Show/Hide Metadata Filters floating window. In this window, enable the Date filter, then you may close that window.

    Now back to the Filter tool. You should see that the Filter tool now has hierarchical filters for every year and every month, as well as individual dates. This should give the zooming view that you desire.

    0
  • Quentin Black

    That's a very powerful and granular filter. Definitely interesting, thanks!

    0

Post is closed for comments.