sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    How to get the saved file path

    Scheduled Pinned Locked Moved Developers' Forum
    13 Posts 5 Posters 2.3k Views 5 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • N Offline
      Nick60
      last edited by

      SketchUp version: 8.0.4811
      Operating system: windows 7

      As I need to save an XML file with the same name of the sketchup file and in the same directory from a ruby script,
      I've tried to use the model observer's OnPostSaveModel event, but the model.path is not updated.

      Let me explain with an example.

      Let's say that I create a MyModelObserver class:

      class MyModelObserver < Sketchup::ModelObserver
      def onPostSaveModel(model)
      UI.messagebox("Path = '#{model.path}' ")
      end
      end

      and that I attach an istance of this class to the model:

      Sketchup.active_model.add_observer(MyModelObserver.new)

      Now, if I create a new file from SketchUp and then save it on my desktop as, i.e., "Try1.skp", the message box shows: Path = ''

      But after this, opening the console and writing: puts Sketchup.active_model.path
      shows the correct info.

      Conclusion: it seems to me that this is a bug, and I've already filled the bug form, but meanwhile anybody knows a workaround?

      1 Reply Last reply Reply Quote 0
      • TIGT Offline
        TIG Moderator
        last edited by

        You need to have an AppObserver AS WELL - see here -
        http://code.google.com/apis/sketchup/docs/ourdoc/appobserver.html
        This will spot when Sketchup opens a new SKP or just other model, you then attach your observer to the current SKP to get its path...

        BUT... why do you need to go to the convolution of observers etc if all you want is a way to get the folder the SKP is in and its name to create a matching xml file ?
        This does it without complications...
        model=Sketchup.active_model path=model.path if not path or path=="" UI.messagebox("Save the model before making the XML file!") return nil end xmlpath=File.join(File.dirname(path), model.title+".xml")
        Then do your stuff writing the xml file etc...
        This code always returns the current path/name of the model if it's been saved...
        πŸ€“

        TIG

        1 Reply Last reply Reply Quote 0
        • TIGT Offline
          TIG Moderator
          last edited by

          The Dir.pwd will return the current working directory this might be 'Plugins' and not the SKP's folder.

          1. With a new [unsaved] SKP you don't know where to save your file - I showed this in my example...
          2. The onSaveModel observer should then return the current 'model.path' ?
            ??

          TIG

          1 Reply Last reply Reply Quote 0
          • N Offline
            Nick60
            last edited by

            Hi TIG,
            I don't think I need the AppObserver, I only need to save the xml file whenever the user save the sketchup file, without disturb him.
            Lets see two example where the AppObserver doesn't help.

            1Β° Scenario: The user create a new file:
            The "Sketchup.active_model.path" is an empty string, until is saved. So is useless during the AppObserver "onNewModel" event firing.

            2Β° scenario: Lets say the user has saved the file, or opened one, so that the "Sketchup.active_model.path" contain his path. But then, if the user decide to use the "Save as" command to save the file to a new location, then I need to save the xml file to the new location, and in this case only the ModelObserver events ("onPreSaveModel", "onSaveModel" and "onPostSaveModel") are fired, not the AppObserver ones.

            And if you use the "Sketchup.active_model.path" in the "onPostSaveModel" event, it's not nil nor empty, it contains the old folder and name info!

            Note that the word "post" should state that everything involved with the saving action is done, but something still appen after the firing of the event, because when you check again the value of "Sketchup.active_model.path" from the console, it the right one!

            So this is definitely a bug, and I hope they will fix it as soon as possible.

            I do think that SketchUp is an incredible powerfull program (that I use from version 1.0 !) but IMHO they should revise the full set of observers, and give us (working) pre and post events for all the events. Observers are great, easy to use and a very neat way to extend and personalize SKU, but without pre and post events, many of those are useless at best, and a sure way to crash the program at worst.

            The second scenario is also a good answer for your question, i.e. "why do I need to bother with observers": I need to observe the user and take an action (build the xml file and save it with the same name of the SKU file, in the same directory) whenever he save the SKU file.

            Meanwhile, I've found that when the user save the file I can find the directory using the standard ruby "Dir" class, with "Dir.pwd" (program working directory) but alas this doesn't help me on regard of the filename that the user has chosen for the SKU file.

            1 Reply Last reply Reply Quote 0
            • N Offline
              Nick60
              last edited by

              Hi TIG,
              second first: I'm talking about the onPostSaveModel. I don't pretend to save the xml file before or during the saving of the SKU file (where obviously the model.path and model.title cannot contain any data) but after the user has saved it. That's why I use the onPostSaveModel.

              You know you can create a class that is a descendant of the Sketchup::ModelObserver class and override the desired methods, like this one:

              class MyModelObserver < Sketchup;;ModelObserver
                def onPostSaveModel(model)
                  msg = "OnPostSaveModel; \n" +
                          "- Path = '#{model.path}' \n" +
                          "- Title = '#{model.title}' \n" +
                          "- Dir.pwd = '#{Dir.pwd}'"
                  UI.messagebox(msg)
                end
              end
              

              When you attach an istance of the MyModelObserver to the model, with:

              Sketchup.active_model.add_observer(MyModelObserver.new)

              Everytime the SKU file is saved, the onPostSaveModel method is executed.

              Here for debugging I'm just checking the model.path value showing it with the messagebox, but in real code I do all the things needed to create the xml data and save it using the model.path (if only it would contain the correct data!)

              For the Dir.pwd check for yourself if you dont trust me πŸ˜„
              Inside the onPostSaveModel method it return the folder where the model has been saved.
              But Model.path and Model.title don't. πŸ˜•

              Thanks for all the patience and effort you are putting on helping me.

              1 Reply Last reply Reply Quote 0
              • TIGT Offline
                TIG Moderator
                last edited by

                Unfortunately the onPostSaveModel method returns the model.path and model.title as it was BEFORE the save !
                It is no different from the onPreSave... and onSave... methods πŸ˜•

                This recoded way ensures that your code waits for half a second before kicking in - at that point the recently saved model path and title ARE accessible

                class MyModelObserver < Sketchup;;ModelObserver
                  def onPostSaveModel(model)
                    tid=UI.start_timer(0.5,false){
                      puts("OnPostSaveModel;\n- Path = '#{Sketchup.active_model.path}'\n- Title = '#{Sketchup.active_model.title}'\n- Dir.pwd = '#{Dir.pwd}'")
                      UI.stop_timer(tid)
                    }
                  end
                end
                

                Note that I used a puts in the test as a UI.messagebox will make multiple instances of the dialog until you OK it! A puts just does the one report in the Ruby Console.
                Your code [or a mthod invoking it] needs to go into the {} of the start_timer.
                I think you can get away with the stop_timer line...

                Also you CANNOT rely on the Dir.pwd to give you the correct path.
                If you do a 'save' on a SKP that has never been saved before or a 'save_as' then Dir.pwd does return the folder where the SKP now resides, BUT if you do a 'save' on a previously saved SKP that just been reopened then Dir.pwd will return the path to the Plugins folder πŸ˜’
                However, with the timer fix you can now get the correct path/title anyway.

                Note that the model-observer is only attached to the model that is active when you launch Sketchup and subsequent new/existing SKPs opened from the menu will not get the observer. As explained earlier an AppObserver can watch for Sketchup doing this and then it can attach your onPostSave observer to the newly opened SKP too.

                TIG

                1 Reply Last reply Reply Quote 0
                • N Offline
                  Nick60
                  last edited by

                  Hi TIG,
                  thanks a lot, your workaround is great, and you really saved my life! πŸ˜„
                  Thank you also for the detailed explanation of the unreliability of the Dir.pwd.
                  About the AppObserver, I already use it to attach the model observer to the model, as you wrote, so non problems with that 😎.

                  As I said, the whole observer set should be revised. Look at some oddities:

                  1. We have the onNewModel and onOpenModel, but where is the onCloseModel?
                  2. The onQuit is useless, because when fired the active_model is already gone with the wind...
                  3. The Model observer has onBeforeComponentSaveAs and onAfterComponentSaveAs, but also onPreSaveModel, onSaveModel and onPostSaveModel: they used the words "Before" and "After" but also "Pre" and "Post". This is non consistent and show that there isn't a coherent and organic view of the complete set.

                  I do hope that version 9 will do a complete redesign of events and observers.

                  We need more control on what the user do, also to prevent him on doing some things. I'm developing a program where I need to prevent the user to edit some component definitions and there is no simple way of doing that. But this is another story... πŸ˜‰

                  Anyway, thanks again for your precious help.

                  1 Reply Last reply Reply Quote 0
                  • N Offline
                    Nick60
                    last edited by

                    After some experiments, I'd like to add two things:

                    1. The Timer seems to ignore the no-repeat flag, so if the code (a delegate, tech speaking πŸ˜‰ ) use more time than the timer interval, the timer start a new execution of the code. That's why the UI.messagebox create such a mess...

                    2. The solution is to move the stop.timer execution at the very begin of the code:

                    
                    class MyModelObserver < Sketchup;;ModelObserver
                      def onPostSaveModel(model)
                        timer_id = UI.start_timer(0.5,false) do
                          UI.stop_timer(timer_id)
                          msg = "OnPostSaveModel; \n" +
                                "- Path = '#{model.path}' \n" +
                                "- Title = '#{model.title}' \n" +
                                "- Dir.pwd = '#{Dir.pwd}'"
                          UI.messagebox(msg)
                          # Generate and save xml report
                          # ...
                        end
                      end
                    end
                    
                    

                    Thanks again.

                    1 Reply Last reply Reply Quote 0
                    • thomthomT Offline
                      thomthom
                      last edited by

                      @tig said:

                      Unfortunately the onPostSaveModel method returns the model.path and model.title as it was BEFORE the save !
                      It is no different from the onPreSave... and onSave... methods πŸ˜•

                      Observer bug?

                      Thomas Thomassen β€” SketchUp Monkey & Coding addict
                      List of my plugins and link to the CookieWare fund

                      1 Reply Last reply Reply Quote 0
                      • N Offline
                        Nick60
                        last edited by

                        @thomthom said:

                        Observer bug?

                        Hi thomthom, can you please remove the question mark? πŸ˜‰

                        I've spent (lost...) two days to find a solution, and wrote a lot about it. Thanks god TIG helped me finding a workaround.

                        But now we can surely say that is a bug.

                        And I've already filled the form you pinned for it. It's a pity that we can't track the bug, nor vote for it, otherwise I'd begged you for a vote! πŸ˜„

                        (Ok, this reply was only an excuse to thank TIG one more time!)

                        and... ops! also the timer seems to have a bug because it doesn't stop even if the repeat flag is false

                        1 Reply Last reply Reply Quote 0
                        • TIGT Offline
                          TIG Moderator
                          last edited by

                          The timer should [will] stop when given a 'false' repeat argument, if the process only involves a 'puts' or other non-interruptive code.
                          BUT if it involves a UI.messagebox it keeps firing repeatedly until the dialog is closed - probably another bug πŸ˜’

                          TIG

                          1 Reply Last reply Reply Quote 0
                          • S Offline
                            shri
                            last edited by

                            πŸ˜• πŸ˜• πŸ˜•

                            1 Reply Last reply Reply Quote 0
                            • OricAtmosO Offline
                              OricAtmos
                              last edited by

                              Hey,

                              I ran into the same problem as Nick60 today and was glad I found this thread with an nice solution.
                              However there's still one use case with a problem:
                              when the user saves the model with "Save copy as..." the side-car file will be saved under the wrong name.
                              Any suggestions how this could be fixed?

                              1 Reply Last reply Reply Quote 0
                              • 1 / 1
                              • First post
                                Last post
                              Buy SketchPlus
                              Buy SUbD
                              Buy WrapR
                              Buy eBook
                              Buy Modelur
                              Buy Vertex Tools
                              Buy SketchCuisine
                              Buy FormFonts

                              Advertisement