11 Replies Latest reply: Jul 31, 2006 7:16 PM by macintosh_tech
macintosh_tech Level 1 Level 1 (30 points)
Hi There,

Here is my issue. I have a script inside of an Xcode project that is used when a file is dropped onto the selected object. What this script does is get the path information from the file (where its located), (With single or multiple files) and uses it in the script to copy them to a temp folder for use by another script at a later time. The script works, however its SLOW. when an item is dropped it takes about 10 seconds for it to finish doing whatever it needs to do or is doing. The files being dropped are usually PDF's, or EPS's Does anyone know of a better way to maybe speed it up? Thanks for your help and time!

-Nate

--------------------------
Here Is The Script:

on drop theObject drag info dragInfo
set dataTypes to types of pasteboard of dragInfo
set doclist1 to {}
display dialog "What Is The Ad Number Of The Item To Be Spooled?" default answer "Enter Ad Number Here..." buttons {"Cancel", "Enter"} default button 2
set theadNumber to text returned of result
set contents of text field "adnumber" of window "SafeLaunch" to theadNumber
set preferred type of pasteboard of dragInfo to "file names"
set doclist1 to contents of pasteboard of dragInfo
set dropped to doclist1 is not {}
set items_dropped to doclist1 is not {}
return true
end drop

on conclude drop theObject drag info dragInfo
set mycount to (count of every item of doclist1)
tell progress indicator "progressbar" of window "SafeLaunch"
start
end tell
tell progress indicator "progressbar" of window "SafeLaunch" to increment by 10
set contents of text field "statusfield" of window "SafeLaunch" to "Adding Artwork To List..."
tell progress indicator "progressbar" of window "SafeLaunch" to increment by 30
tell progress indicator "progressbar" of window "SafeLaunch"
start
end tell
tell progress indicator "progressbar" of window "SafeLaunch" to increment by 10
set contents of text field "statusfield" of window "SafeLaunch" to "Adding Artwork To List..."
repeat with repeatVar from 1 to (mycount)
set doclist to item repeatVar of doclist1
set item_reference to (doclist as POSIX file) as alias
set doclist to doclist as POSIX file as alias
set pathTospool to "/private/var/tmp/slspooler/"
do shell script "mkdir -p " & pathTospool & theadNumber
tell progress indicator "progressbar" of window "SafeLaunch" to increment by 40
do shell script "chmod 777 " & pathTospool & theadNumber
tell progress indicator "progressbar" of window "SafeLaunch" to increment by 50
try
set tmpMacPathAd to (path to startup disk as string) & "private:var:tmp:slspooler:" & theadNumber & ":"
tell application "Finder"
duplicate file doclist to alias tmpMacPathAd without replacing
end tell
on error errorMsg number errorNum
tell progress indicator "progressbar" of window "SafeLaunch"
stop
end tell
set theSoundERROR to load sound "WARNING"
play theSoundERROR
tell progress indicator "progressbar" of window "SafeLaunch" to increment by 100
tell progress indicator "progressbar" of window "SafeLaunch" to increment by -100
set contents of text field "statusfield" of window "SafeLaunch" to "idle... (However A List Error Occured)"
delete every image of image view "drop" of window "SafeLaunch"
display dialog "Safe Launch Error #: " & errorMsg
end try
end repeat
tell progress indicator "progressbar" of window "SafeLaunch" to increment by 100
set theSound1 to load sound "adaccepted"
play theSound1
delay 1
say "Art Added" using "Bruce"
set contents of text field "statusfield" of window "SafeLaunch" to "One Art Element Waiting..."
set {visible of button "box" of window "SafeLaunch"} to {true}
if mycount is greater than 1 then
set {visible of button "box2" of window "SafeLaunch"} to {true}
set contents of text field "statusfield" of window "SafeLaunch" to "Multiple Art Elements Waiting..."
end if
set enabled of button "spoolbutton" of window "SafeLaunch" to true
tell progress indicator "progressbar" of window "SafeLaunch"
stop
end tell
tell progress indicator "progressbar" of window "SafeLaunch" to increment by -100
set contents of text field "statusfield" of window "SafeLaunch" to "idle..."
delete every image of image view "drop" of window "SafeLaunch"
end conclude drop


PowerMac G5, iBook G4, Intel MacMini, PowerMac G3 B&W, iMac DV, iBook Tangerine   Mac OS X (10.4.7)  

PowerMac G5, iBook G4, Intel MacMini, PowerMac G3 B&W, iMac DV Blueberry   Mac OS X (10.4.6)  
  • kel Level 3 Level 3 (850 points)
    Hi macintosh_tech,

    It takes a long time because the Finder is talking to your app, I think. What you can do is set a flag with data and conclude the drop handler. Then, when the idle handler sees the flag as true it does somehting. Here's an example in plain AppleScript. You save it as stay open application. When you drop an item on it, the idle handler does its thing.

    property do_something : false
    property the_something : "hello"
    --
    on idle
    if do_something then
    activate
    display dialog the_something
    set do_something to false
    end if
    return 1
    end idle
    --
    on open these_files
    set n to name of (info for (item 1 of these_files))
    set the_something to n
    set do_something to true
    end open

    gl,
  • macintosh_tech Level 1 Level 1 (30 points)
    Thanks for the response.

    I had thought about putting it in the idle handler, but for the odd work flow we have it wouldn't necessarily help, im kinda saving it as a last ditch effort.

    Is there a better way to get the separate paths of the files dropped and nothing else so they could be used elsewhere later in a repeat command? Im new to the drag and drop in Xcode and not sure what the most efficient way is.

    Thanks again
  • Cyclosaurus Level 6 Level 6 (12,915 points)
    You can use plist file to store you info. plist file can be accessed with defaults, see defaults man pages for details.

    But looking at your code, you have theadNumber associates with file paths.
    That makes it a little bit more complicate, because defaults doesn't handle plist's complex keys structure very well.
    The simple thing to do is keep plist's keys flat and use pointer method, here is an example:

    spool_count = 2

    theadNumber_1 = 1234
    theadNumber_2 = 5678

    1234_count = 4

    1234_1 = "59878F4A-FF01-4748-A8D3-21EC1ECCF850"
    1234_2 = "A12ACDDC-8530-4C0E-B6C9-D0BB494820D3"
    1234_3 = "FCF13386-B0A0-4DA7-8E76-AD92EDFAB605"
    1234_4 = "EEB0DC34-86C5-4398-AC8C-0E5BE0104F3E"

    5678_count = 2

    5678_1 = "25E930C8-848B-4CCB-B1A6-FE107588E440"
    5678_2 = "6F9C346B-E141-4C33-B45C-0C92A76899D5"

    So you see, it starts with one pointer, points to two keys, and from those: one points to four and one points to two other keys.

    The other option is to play with System Events' Property List Suite, it can handle complex key structure, but not very friendly to use.
  • Jon Lopiano Level 1 Level 1 (35 points)
    Im attempting something simular
    I was curious why is it taking so long to drag and drop.
    People say "its talking to the finder" by what does that mean, what is it actaully doing.
  • macintosh_tech Level 1 Level 1 (30 points)
    Hey kel,

    it looks like maybe the idle may work, now the "First Responder" is the only part of the Xcode environment that allows the "on idle" (as far as I know) so if I linked the drop script and the first responder's on idle in the same script that should work in the background not tying up the application making users wait. All I need is on the sucessful drop set do_something to true and when the idle goes by looking and sees a true it will perform the operation. Right? Thanks again for your help!!!

    PowerMac G5, iBook G4, Intel MacMini, PowerMac G3 B&W, iMac DV Blueberry   Mac OS X (10.4.6)  
  • Cyclosaurus Level 6 Level 6 (12,915 points)
    If you look at the OP's codes, you see that he is doing a lot of things in on conclude drop theObject drag info dragInfo, including tell Finder to duplicate and delete files, that probably take the most time.

    What he should had done is to write the info to a plist file, set an idle flag, then have the idle handler process the info in the background.
  • kel Level 3 Level 3 (850 points)
    Hi Cylcl,

    Isn't that what I said to do or are you talking about something I don't know about. Are you talking about running something in the background behind (or above) the idle handler? If this can be done then It sounds very good. Like you'll call something and it runs in the background. How do you do this?

    gl,
  • Cyclosaurus Level 6 Level 6 (12,915 points)
    kel,

    It's the same thing, but AppleScript Studio app is little bit tricky to setup, because only Application object can run idle handler.

    Also, because there may be large piece of info to process (reading back from plist) you don't want to waste time reading null data.

    so the OP should:

    1) link Application or File's Owner in IB to idle handler
    2) declare a global or property idle_run, in the script contains idle handler.
    3) in on drop theObject drag info dragInfo handler, must do:

    a. update the plist to change spool_count, threadNumber index, etc...
    b. set idle_run to true

    4) in idle handler

    on idle
    if idle_run then
    -- process the data
    end if
    end idle

    that is basically it, however, there is potential problem:
    what if the user drop new file path while idle is processing the data?
  • macintosh_tech Level 1 Level 1 (30 points)
    Well guys i figured it out....here is what fixes the script and makes it lightning fast...

    OLD
    on drop theObject drag info dragInfo
    set dataTypes to types of pasteboard of dragInfo
    set doclist1 to {}
    display dialog "What Is The Ad Number Of The Item To Be Spooled?" default answer "Enter Ad Number Here..." buttons {"Cancel", "Enter"} default button 2
    set theadNumber to text returned of result
    set contents of text field "adnumber" of window "SafeLaunch" to theadNumber
    set preferred type of pasteboard of dragInfo to "file names"
    set doclist1 to contents of pasteboard of dragInfo
    set dropped to doclist1 is not {}
    set items_dropped to doclist1 is not {}
    return true
    end drop

    NEW
    on drop theObject drag info dragInfo
    delay .01
    set dataTypes to types of pasteboard of dragInfo
    delay .01
    set doclist1 to {}
    delay .01
    display dialog "What Is The Ad Number Of The Item To Be Spooled?" default answer "Enter Ad Number Here..." buttons {"Cancel", "Enter"} default button 2
    set theadNumber to text returned of result
    set contents of text field "adnumber" of window "SafeLaunch" to theadNumber
    set preferred type of pasteboard of dragInfo to "file names"
    delay .01
    set doclist1 to contents of pasteboard of dragInfo
    delay .01
    set dropped to doclist1 is not {}
    delay .01
    set items_dropped to doclist1 is not {}
    delay .01
    return true
    end drop

    It seems adding thoes delays makes it run insantanious and without takes up to 30 second.

    This was a last ditch effort after the idle command had the same problem....so make a note people! Thanks again everyone for your assistance
  • Cyclosaurus Level 6 Level 6 (12,915 points)
    OK, that's weird. But I'll keep that in mind, just in case I'll see that in the future.

    Thank for sharing.
  • macintosh_tech Level 1 Level 1 (30 points)
    Well, the wierd part was when I decided to put in "beep 1" in between all the lines to see where it was getting hung up and when I went "Build & Go" it ran at the speed of light, switched out a few with delays and worked like a charm....my theory is it frees up the finder and or the app somehow by making it do something else....but who knows...it is wierd though. :\