13 Replies Latest reply on Jan 12, 2011 8:53 AM by marktomaras

    How to use LrCatalog.createCollectionSet

    JohnK UK

      Can anyone tell me why the following code fails, please?

       

      local LrFunctionContext = import 'LrFunctionContext'
      local LrLogger = import 'LrLogger'
      local LrApplication = import 'LrApplication'
      local LrTasks = import 'LrTasks'

       

      Foo = {}

       

      function Foo.foo()
        local log = LrLogger("foo")
        log:enable("logfile")

       

        LrTasks.startAsyncTask(function()
          local result = LrFunctionContext.callWithContext("showCustomDialog", function (context)
            local cat = LrApplication.activeCatalog()
            cat:withWriteAccessDo("Foo", function()
              local existingCollectionSets = cat:getChildCollectionSets()   
              if not cat.hasWriteAccess then
                log:trace("Write access could not be obtained.")
              end
              for _, s in ipairs(existingCollectionSets) do
                if s:getName() == LOC "Smart Collections" then
                  log:trace("Found parent collection set: " .. s:getName())
                  set = cat:createCollectionSet("New smart collection set", s, false)
                  break
                end
              end
              if set == nil then
                log:trace("Unable to create new collection set.")
              else
                log:trace("Collection set '" .. set.getName() .. "' successfully created.")
              end
            end)  -- withWriteAccessDo
          end) -- startAsyncTask
        end) -- callWithContext
      end

       

      Foo.foo()

       

      The call to createColectionSet fails with an internal error of "assertion failed!".  The parent collection set is found.  The error occurs whether the third parameter is false, true or absent.  There is no smart collection set in "Smart Collections" with the name "New smart collection set".

       

      And, whilst I have your attention, a real newbie question:  I can search the forums for, say, "createCollectionSet" and I can see the forums in which the term has been mentioned, and the contributors have used the term.  I can see links to the forums and to the contributors' profiles, but I can't see a link to the specific posts in which the search term is used.  Am I missing something, or do I really have to scroll through the entire forum to try find the relevant post(s)?

       

      Thanks in advance for your help.

       

      J

        • 1. Re: How to use LrCatalog.createCollectionSet
          areohbee Level 5

          I cant see the problem with your code.

           

          Can you create the collection set if you pass nil instead of s for the second parameter? i.e. can you create the collection set in the top level?

           

          PS - I *think* it just shows you a multi-item forum page link if the search text is only found in the title, and shows you a link to an actual thread if the search text is found in the body of a post. Something like that.

           

          Good luck.

           

          Rob

          • 2. Re: How to use LrCatalog.createCollectionSet
            JohnK UK Level 1

            Rob,

             

            Thanks for your reply.  I thought I'd tried passing a nil second parameter without success before posting, but to be sure I re ran the code without the search through the existing collections and using a nil second parameter.  Same result.

             

            The fact that you can't see the problem is good news and bad news, I guess: if I'm not incompetent then it may be a bug.  I'll give it a day or two for more replies and then investigate how to post a bug report.

             

            Cheers,

             

            J

            • 3. Re: How to use LrCatalog.createCollectionSet
              areohbee Level 5

              This code works:

               

                  pcallStatus = RcUtils.withCatalogDo( 5, catalog.withWriteAccessDo, catalog, "DevConvert - Collections Creation", function()
                      local collectionSet = catalog:createCollectionSet( "DevConvert", nil, true )
                      fillCheckCollection = catalog:createCollection( "Fill Light Check", collectionSet, true )
                      vignetteCheckCollection = catalog:createCollection( "Lens Vignette Check", collectionSet, true )
                      caCheckCollection = catalog:createCollection( "Chromatic Aberration Check", collectionSet, true )
                      detailCheckCollection = catalog:createCollection( "Detail Check", collectionSet, true )
                      genCheckCollection = catalog:createCollection( "General Check", collectionSet, true )
                  end )

               

              rc-utils.with-catalog-do is a wrapper for the catalog access function with catalog contention arbitration and error handling.

               

              R

              • 4. Re: How to use LrCatalog.createCollectionSet
                JohnK UK Level 1

                I've not been able to get Rob's suggested solution to work for me.  In fact, as far as I can see, it's essentially the same as my original post.

                 

                Has anyone else had any success with this?  Could it be an OS-problem?  I'm running LR 3.3 on OSX 10.6.5.  I'd be grateful if people with other set ups could have a go and let me know how they get on.

                 

                Thanks in advance.

                • 5. Re: How to use LrCatalog.createCollectionSet
                  areohbee Level 5

                  The code above has worked on both Windows and Mac.

                   

                  If you think your system might be wonky, why not try DevConvert and see if it creates the collections. If it does, then you'll have something working to start from, and if not - it would benefit both of us to know about it...

                  1 person found this helpful
                  • 6. Re: How to use LrCatalog.createCollectionSet
                    JohnK UK Level 1

                    Rob's DevConvert code does work successfully on my system, so I need to dig deeper

                    and try to understand the differences between his approach and mine.  I'll report back when I have something constructive to say.

                     

                    Thanks for your help, Rob - agree about mutal benefit, by the way.

                    • 7. Re: How to use LrCatalog.createCollectionSet
                      areohbee Level 5

                      John,

                       

                      One thing maybe: I noticed the foo-foo function is being called as soon as the module is loaded.

                       

                      I dont know whats loading it, but consider calling it in response to a menu item or button push and see if it works.

                       

                      I mean, "assertion failed" means it either doesn't like the parameters, or the context in which it is executing - assuming your catalog isnt hosed...

                       

                      If it aint the former, its the latter...

                       

                      And maybe back down to a single call until it works:

                       

                           cat:createCollectionSet( {name}, nil, true ) -- parameters are recommended since thats what Ive used so far and has worked.

                       

                           and try a different name or even a fresh catalog in case there's something amiss like that.

                       

                      Also, see if you can create the collection set by hand and then delete it - as a sanity check.

                       

                      Rob

                      • 8. Re: How to use LrCatalog.createCollectionSet
                        JohnK UK Level 1

                        Solved.  And lessons learnt.....

                         

                        First off, to answer Rob's queries above:

                         

                        I am running the code in response to a menu item in a plugin.  I didn't post the Info.lua file simply for brevity.  I had also tried different collection names and running in a fresh catalog, all to no avail.

                         

                        A hack of Rob's DevConvert code to my context gives this:

                         

                        function Foo.hybrid_foo()
                          RcModuleLoader = dofile( LrPathUtils.child( LrPathUtils.parent( _PLUGIN.path ),
                                                   "RC_CommonModules/RcModuleLoader.lua" ) )
                          RcModuleLoader.init()
                          local RcUtils = RcModuleLoader.loadRcModule( 'RcUtils' )

                          LrTasks.startAsyncTask(function()
                            local pcallStatus, qual
                            pcallStatus, qual = RcUtils.withCatalogDo( 5, cat.withWriteAccessDo, cat, "_dev_collections", function()
                              local collectionSet = cat:createCollectionSet( "DevConvert", nil, true )
                              undefColl = cat:createCollection( "PV-Undefined", collectionSet, true )
                              toDoColl = cat:createCollection( "PV2003", collectionSet, true )
                              doneColl = cat:createCollection( "PV2010", collectionSet, true )
                            end )

                            if pcallStatus then
                            else
                              log:error( "Unable to access the catalog and create collections." )
                              log:error(qual)
                              return
                            end
                          end) -- startAsyncTask   
                        end

                         

                        This works.

                         

                        Replacing Rob's anonymous function

                         

                        function()
                          local collectionSet = cat:createCollectionSet( "DevConvert", nil, true )
                          undefColl = cat:createCollection( "PV-Undefined", collectionSet, true )
                          toDoColl = cat:createCollection( "PV2003", collectionSet, true )
                          doneColl = cat:createCollection( "PV2010", collectionSet, true )
                        end

                         

                        with my collection set creation code (slightly simplified from my original post)

                         

                        function()
                          if not cat.hasWriteAccess then
                            log:trace("Write access could not be obtained.")
                          end
                          local collectionSet = cat:createCollectionSet("Test", nil, true)
                          if collectionSet == nil then
                            log:trace("Unable to create new collection set.")
                          else
                            log:trace("Collection set '" .. collectionSet.getName() .. "' successfully created.")
                          end
                        end

                         

                        fails.  However, for the first time, I get a line number associated with the assertion failure.  The problem line is this one:

                         

                        log:trace("Collection set '" .. collectionSet.getName() .. "' successfully created.")

                         

                        Changing

                         

                        collectionSet.getName()

                         

                        to

                         

                        collectionSet:getName()

                         

                        gives a more useful error:

                         

                        Can't get collection information after creating collection inside the same withWriteAccessDo function

                         

                        Voila!

                         

                        To be fair, the SDK documentation does say (under withWriteAccessDo)

                         

                        'As of version 3.0, changes you make to the database within this call do not have immediate effect, but are written to the database upon successful completion of the callback function. This means, in general, that if you create a new item (for instance, by calling catalog:createCollection()), you cannot retrieve information about that item until the with___AccessDo has finished. There are some special cases where you can reference the newly-created item; for instance, after creating a collection set, you can create a collection within that set. These cases are noted in the API documentation.'

                         

                        and (under createCollectionSet)

                         

                        'Must be called from within one of the with__WriteAccessDo gates. The new collection set is not available for access until that function returns.'

                         

                        So the problem was simply my attempt to contain error checking and reporting within the creation function.

                         

                        The following code works, and does need not any reference to Rob's RcUtils.


                        function Foo.foo()
                          LrTasks.startAsyncTask(function()
                            cat:withWriteAccessDo("Foo", function ()
                              if not cat.hasWriteAccess then
                                log:trace("Write access could not be obtained.")
                              end
                              local set = cat:createCollectionSet("New smart collection set", nil, true)
                              if set == nil then
                                log:trace("Unable to create new collection set.")
                              end
                            end)  -- withWriteAccessDo
                          end) -- startAsyncTask
                        end

                         

                        I have to say, as a newcomer to Lua, I do find the subtle differences between the ":" and "." notations confusing....

                         

                        Thanks for your help, Rob.

                         

                        Message was edited by: JohnK UK to correct code formatting

                        • 9. Re: How to use LrCatalog.createCollectionSet
                          areohbee Level 5

                          JohnK UK wrote:

                           

                          I have to say, as a newcomer to Lua, I do find the subtle differences between the ":" and "." notations confusing....

                           

                          Notta one Lua programmer hasn't made that mistake before - its part of the price of admission: welcome to the club!

                           

                          In case you haven't got it exactly yet

                           

                          a:b() is syntactic sugar for a.b( self )

                           

                          i.e. the colon represents an object method call that hides the implicit self object parameter.

                          dot means just call as a regular function...

                           

                          Some Lr Api calls are object methods, and some are static function calls.

                           

                          As a general rule, if it starts out with a lower case letter (e.g. photo, catalog, ...), then call it with a colon. If it starts out with an upper case letter (e.g. Lr...), then call it with a dot.

                           

                          Note: non-function data members are always accessed using dot notation.

                           

                          Congrats.

                          • 10. Re: How to use LrCatalog.createCollectionSet
                            johnrellis Most Valuable Participant
                            Notta one Lua programmer hasn't made that mistake before - its part of the price of admission: welcome to the club!

                            What makes the "dot instead of colon" error so frustrating is that the error message, "assertion failed", is so uninformative.  Adobe could save its SDK customers countless hours of frustration simply by making the error message more informative.

                            • 11. Re: How to use LrCatalog.createCollectionSet
                              areohbee Level 5

                              Agreed.

                               

                              I filed a feature request for Adobe to go through all their assert( cond ) statements and add a second parameter.

                               

                              Cheers,

                              Rob

                              • 12. Re: How to use LrCatalog.createCollectionSet
                                JohnK UK Level 1

                                In case it's useful to anyone, the motivation behind my original post was the desire to automate the task of creating a collection set for all photographs taken within a calendar year and, within the collection set, a smart collection for each month.

                                 

                                You can download the plugin at http://www.tilebarn.com/lightroom/index.htm

                                • 13. Re: anyone able to develop lightroom plug-in??
                                  marktomaras

                                  Hello,

                                   

                                  We are looking for a developer who is familliar with developing a plugin for Lightroom 3.
                                  We know the SDK & API for Lightroom is a bit unique, and we want to work with someone who either has developed for Lightroom already, or someone very familiar with the process.

                                   

                                  We would like a plug in for Lightroom 3 that creates web photo galleries.  We are not looking for something too difficult!  In fact, many plugins already exist, but none do exactly what we need.  So, we need a custom one designed for us.

                                   

                                  The plug in should look like and work like the photo gallery plug ins already available for Lightroom, such as the standard HTML web galleries Lightroom 3 has standard, as well as the Airtight Simpleviewer plugin.  Both of these have their advantages and disadvantages.  But both are fairly flexible in what they offer, and the user can make galleries that look and behave in many ways.

                                   

                                  Our plug in needs to avoid flash all together.  We like J Query code such as this one:
                                  http://www.twospy.com/galleriffic/example-2.html

                                   

                                  The galleries should have a download option that lets the viewer download a low res, med res, or high res file.

                                   

                                  The galleries need a search field where users can search for key words or metadata.

                                   

                                  This is the basic idea.  We would like to develop this project right away.  Please contact us.

                                   

                                  Thank you,
                                  Mark Tomaras

                                   

                                  mark (at) luminositycreative (dot) com
                                  +1 305 775 3020

                                   

                                  shelby (at) luminositycreative (dot) com
                                  +1 561 441 2679