Simple progress bar example

SouthernAtHeart

macrumors newbie
Original poster
Nov 6, 2011
28
0
I am dabbling in AppleScript and would like to try adding a progress bar to my script so I downloaded Xcode 4. I found a couple examples That seem real easy to follow, but they must be an old version of Xcode because i can't get anywhere in my Xcode 4. Here's one tutorial that seems real easy to follow:
http://macscripter.net/viewtopic.php?id=24760

Is there something like this for the new Xcode? Or should I download an older version of Xcode
Thanks
 

Red Menace

macrumors 6502
May 29, 2011
380
45
Littleton, Colorado, USA
If all you are familiar with is AppleScript Studio (or just regular AppleScript), there isn't a whole lot out there that demonstrates the new AppleScript Objective-C framework - mostly it is a matter of converting from the existing Objective-C documentation.

There is an example project in Shane Stanley's AppleScriptObjC Explored ebook, which is pretty much the handbook for ASObjC. Lion's AppleScript Editor has the ability to create applications using ASObj-C, so if you are just wanting to put a progress indicator into a regular AppleScript, there are also some Cocoa-AppleScript examples.
 

SouthernAtHeart

macrumors newbie
Original poster
Nov 6, 2011
28
0
If all you are familiar with is AppleScript Studio (or just regular AppleScript), there isn't a whole lot out there that demonstrates the new AppleScript Objective-C framework - mostly it is a matter of converting from the existing Objective-C documentation.

There is an example project in Shane Stanley's AppleScriptObjC Explored ebook, which is pretty much the handbook for ASObjC. Lion's AppleScript Editor has the ability to create applications using ASObj-C, so if you are just wanting to put a progress indicator into a regular AppleScript, there are also some Cocoa-AppleScript examples.
I'm looking at these links you mentioned. I think it's a bit over my head though. I have scripts that do things like organize contacts and other things with contacts in the address book, and sometimes it takes it awhile (30 seconds)so I thought a progress bar would let the user know my script didn't crash on them, but it looks loke it's pretty complex to just add a progress bar. Its too bad, because that example of a progressbar in the old Xcode looked sumer enough to follow.
Thanks for the input
 

Red Menace

macrumors 6502
May 29, 2011
380
45
Littleton, Colorado, USA
The Cocoa-AppleScript template isn't too complicated (I have a version that uses a controller script similar to the old BP Progress bar), although you need to be able to break the task up into enough pieces to make the progress bar meaningful. Maybe you could just put up an indeterminate progress indicator (a spinner or barber pole).
 

SouthernAtHeart

macrumors newbie
Original poster
Nov 6, 2011
28
0
The Cocoa-AppleScript template isn't too complicated (I have a version that uses a controller script similar to the old BP Progress bar), although you need to be able to break the task up into enough pieces to make the progress bar meaningful. Maybe you could just put up an indeterminate progress indicator (a spinner or barber pole).
...that would be great. Can you do that will plain old AppleScript? I'll do some research...
 

SouthernAtHeart

macrumors newbie
Original poster
Nov 6, 2011
28
0
Here's one of my scripts that can take long enough that a user might think its not doing anything.

Is there just a few lines to add that would show some kind of barberpole? I searched for AppleScript barberpole but didn't come up with any examples.

Code:
set BadList to {"(", ")", " "}
    set Changes to "Person--Phone--OldNo--NewNo" & return
    tell application "Address Book"
        repeat with Acontact in people in the group named theirGroup
            repeat with APhone in phones of Acontact
                set newtarget to ""
                set Target to value of APhone
                repeat with achar in characters of Target
                    if achar is not in BadList then set newtarget to newtarget & achar
                    if achar is in {" "} then
                        if (count of newtarget) < 12 then set newtarget to newtarget & "-"
                    end if
                end repeat
                if not (Target = newtarget) then
                    set theChange to (name of Acontact) & "  --  " & (label of APhone)
                    set theChange to theChange & "  --  " & Target & "  --  " & newtarget
                    set Changes to Changes & theChange & return
                    set value of APhone to newtarget
                    save
                end if
            end repeat
        end repeat
        
    end tell
    Changes
 

Red Menace

macrumors 6502
May 29, 2011
380
45
Littleton, Colorado, USA
You wouldn't need to break anything up to use the barberpole. Your script repeats through the people in a group though, so you could count the total, and increment the progress indicator each time through the loop.

My template is set up right now to process files, but it can be changed easily enough. The Changes/log variable would need to be put in a dialog or something, since the Cocoa-AppleScript can only be run as an application. Is that the compete script? I'm noticing that the theirGroup variable is not set.
 

SouthernAtHeart

macrumors newbie
Original poster
Nov 6, 2011
28
0
You wouldn't need to break anything up to use the barberpole. Your script repeats through the people in a group though, so you could count the total, and increment the progress indicator each time through the loop.

My template is set up right now to process files, but it can be changed easily enough. The Changes/log variable would need to be put in a dialog or something, since the Cocoa-AppleScript can only be run as an application. Is that the compete script? I'm noticing that the theirGroup variable is not set.
...sorry I copied this out of a series of steps, so theirgroup was set at the beginning. But basically each step is like this, running through the contacts making a change like this. You mentioned you template? Did you post an example you made, I'm not seeing it I guess...
I tried looking at the example script folder under help in the Appllescript editor, but didn't see anything there that helped.
If you have an example similar to what I'm trying to do, I'd like to see it.
Thanks,
 
Last edited:

Red Menace

macrumors 6502
May 29, 2011
380
45
Littleton, Colorado, USA
I didn't post the template, it is an application bundle that I have on my AppleScriptObjectiveC home page - the direct link is here.

As I mentioned earlier, the template is set up as an example using a progress bar for some files (it doesn't actually do anything with them, though), so the main script would need to be reworked to use the Address Book script. If the script works as posted, you should be able to replace the main script in the template with yours, adding the commands to the progress bar (see the ProgressBarController.scpt in the application bundle). It is getting late here, but I will post a modified script later.
 

SouthernAtHeart

macrumors newbie
Original poster
Nov 6, 2011
28
0
I didn't post the template, it is an application bundle that I have on my AppleScriptObjectiveC home page - the direct link is here.

As I mentioned earlier, the template is set up as an example using a progress bar for some files (it doesn't actually do anything with them, though), so the main script would need to be reworked to use the Address Book script. If the script works as posted, you should be able to replace the main script in the template with yours, adding the commands to the progress bar (see the ProgressBarController.scpt in the application bundle). It is getting late here, but I will post a modified script later.
Thanks. I bought that book you mentioned, will give it a reading over the next few days. It may be over my head.
I've made custom forms with VBA in MS Access. I see in Xcode 4 there are button, text boxes, even a progress bar. It would be great if I could made little AppleScript utilities and turn them into professional looking apps with this stuff. I'm hoping this book is for beginners.
Getting late here, too
 

Red Menace

macrumors 6502
May 29, 2011
380
45
Littleton, Colorado, USA
Give this a try. Using my progress bar template, make a new application and replace the main script with:

Code:
property myProgressController : missing value -- the controller script instance

on run
	set myProgressController to current application's ProgressBarController's alloc's init() -- create instance
	try
		doStuff()
	on error errmess number errnum
		display alert "error number " & errnum message errmess
	end try
	tell me to quit
end run

on doStuff()
	set theirGroup to "test" -- fill in the blank
	set badList to {"(", ")", " "} -- a list of characters to clean
	set changes to {"Person -- Phone -- Old# -- New#"} -- this will be a list of changes
	
	tell application "Address Book"
		set theContacts to (people in group theirGroup)
		
		set theCount to (count theContacts) -- get a maximum count for the progress bar
		tell myProgressController -- set up and show the progress bar
			createProgressWindow()
			setBarberPole_(false)
			setupProgressWithTopText_bottomText_maxValue_("Fixing phone numbers...", "", theCount)
			delay 1
		end tell
		
		repeat with this from 1 to theCount
			set aContact to item this of theContacts
			
			set theName to name of aContact
			tell myProgressController -- increment the progress bar
				updateProgressByAmount_topText_bottomText_(1, "Processing item " & this & " of " & theCount, theName)
				doEventFetch() -- keep event queue cleared
				-- delay 0.25
			end tell
			
			repeat with aPhone in phones of aContact
				set newTarget to ""
				set target to (value of aPhone)
				repeat with aChar in (characters of target)
					if aChar is not in badList then set newTarget to newTarget & aChar
					if aChar is in {" "} then
						if (count of newTarget) < 12 then set newTarget to newTarget & "-"
					end if
				end repeat
				if not (target = newTarget) then
					set theChange to (name of aContact) & "  --  " & (label of aPhone)
					set theChange to theChange & "  --  " & target & "  --  " & newTarget
					set the end of changes to theChange
					set value of aPhone to (newTarget as text)
					save
				end if
			end repeat
		end repeat
		delay 0.5
	end tell
	
	if (count changes) is greater than 1 then (choose from list changes with empty selection allowed) -- show any changes
end doStuff
 

SouthernAtHeart

macrumors newbie
Original poster
Nov 6, 2011
28
0
Thanks!

I'll definitely look into this. I've started reading this ebook you mentioned. It's VERY helpful.


Give this a try. Using my progress bar template, make a new application and replace the main script with:

Code:
property myProgressController : missing value -- the controller script instance

on run
	set myProgressController to current application's ProgressBarController's alloc's init() -- create instance
	try
		doStuff()
	on error errmess number errnum
		display alert "error number " & errnum message errmess
	end try
	tell me to quit
end run

on doStuff()
	set theirGroup to "test" -- fill in the blank
	set badList to {"(", ")", " "} -- a list of characters to clean
	set changes to {"Person -- Phone -- Old# -- New#"} -- this will be a list of changes
	
	tell application "Address Book"
		set theContacts to (people in group theirGroup)
		
		set theCount to (count theContacts) -- get a maximum count for the progress bar
		tell myProgressController -- set up and show the progress bar
			createProgressWindow()
			setBarberPole_(false)
			setupProgressWithTopText_bottomText_maxValue_("Fixing phone numbers...", "", theCount)
			delay 1
		end tell
		
		repeat with this from 1 to theCount
			set aContact to item this of theContacts
			
			set theName to name of aContact
			tell myProgressController -- increment the progress bar
				updateProgressByAmount_topText_bottomText_(1, "Processing item " & this & " of " & theCount, theName)
				doEventFetch() -- keep event queue cleared
				-- delay 0.25
			end tell
			
			repeat with aPhone in phones of aContact
				set newTarget to ""
				set target to (value of aPhone)
				repeat with aChar in (characters of target)
					if aChar is not in badList then set newTarget to newTarget & aChar
					if aChar is in {" "} then
						if (count of newTarget) < 12 then set newTarget to newTarget & "-"
					end if
				end repeat
				if not (target = newTarget) then
					set theChange to (name of aContact) & "  --  " & (label of aPhone)
					set theChange to theChange & "  --  " & target & "  --  " & newTarget
					set the end of changes to theChange
					set value of aPhone to (newTarget as text)
					save
				end if
			end repeat
		end repeat
		delay 0.5
	end tell
	
	if (count changes) is greater than 1 then (choose from list changes with empty selection allowed) -- show any changes
end doStuff
 

kildjean

macrumors 6502
Apr 16, 2005
258
33
Useless, TX
Here goes nothing...

Disclosure: I am aware that thing to resuscitate this thread might be fruitless but just in case...

I made this script to make a backup of a user profile. The script on its own works very well. It asks which profile you want to backup into a filename.dmg and stores it on the desktop... you can run it again to restore said filename.dmg into the profile it goes into.

Code:
property theTitle : "User Migration Tool for Mac v0.01"

set theDialogResults to display dialog "Do you want to BACKUP or RESTORE a user's profile?" with title theTitle buttons {"Backup", "Restore", "Cancel"}
if button returned of theDialogResults is "Backup" then
	backup()
else
	restore()
end if

on backup()
	--	get the path to the user folder to backup 
	set theSource to choose folder with prompt "Select a user folder to backup to a disk image." default location path to users folder
	
	--	get file name and path where image will be saved
	set theFile to choose file name with prompt "Select the name and location where you want to save the image file." default name "MyBackup.dmg" default location path to desktop
	
	--	warning
	display dialog "Be patient. The backup may take considerable time. You will be notified upon completion." with title theTitle buttons {"Ok"} default button "Ok" giving up after 5 with icon caution

	--	make disk image
	set theResult to do shell script ("/usr/bin/hdiutil create -fs HFS+ -srcFolder " & POSIX path of theSource & " " & POSIX path of theFile) with administrator privileges
	log theResult
			
	if theResult contains "created:" then
		display dialog "The backup is complete." with title theTitle buttons {"Ok"} default button "Ok" giving up after 5
		say "Backup is complete"
	end if
end backup


on restore()
	--	get disk image to mount
	set theFile to choose file of type "devi" with prompt "Select a disk image file that contains a copy of a user's profile to restore." default location path to desktop
	
	--	mount disk image 
	set theMountPath to do shell script ("/usr/bin/hdiutil mount " & POSIX path of theFile & "| grep '/Volumes' | awk '{ print $3 }'")
	log theMountPath
	
	--	get folder where user's profile will be copied
	set theDestination to choose folder with prompt "Select the user's home folder where the profile will be retored." default location path to users folder
	
	--	warning
	display dialog "Be patient. The restore may take considerable time. You will be notified upon completion." with title theTitle buttons {"Ok"} default button "Ok" giving up after 5 with icon caution
	
	--	copy data to user's folder
	set theResult to do shell script ("/usr/bin/ditto " & theMountPath & " " & POSIX path of theDestination) with administrator privileges
	log theResult
	
	--	unmount disk image
	do shell script ("/usr/bin/hdiutil eject " & theMountPath)
	
	if theResult is "" then
		display dialog "The restore is complete." with title theTitle buttons {"Ok"} default button "Ok" giving up after 5
		say "Restore is complete"
	end if
end restore
The problem I am having is that during the Backup or the Restore there is not "Progress Bar" Indicator of how far into the backup or the restore it is on... there is no time estimation of when it will complete.

I wanted some help in adding a barber pole that spins until the backup or the restore is done. The line that tells the script when the backup is done is: if theResult contains "created:" then and for the restore it would be:

Code:
if theResult is "" then
		display dialog "The restore is complete."
Any help or direction would be great. I have tried just about everything I can think off... short of building an app in Xcode which I don't have the time to learn for this particular project... don't know what to do.

Thanks!

K
 

kildjean

macrumors 6502
Apr 16, 2005
258
33
Useless, TX
What OS are you running? Yosemite added some properties to AppleScript for indicating progress (see the 10.10 release notes), otherwise you will need to use some AppleScriptObjC from either a Cocoa-AppleScript applet or Xcode.
I am running Yosemite / Mavericks. ASObjC Runner is deprecated in Yosemite and only works in Mavericks. I took a look at the new configs you mentioned earlier but they don't offer me a way to add a progress bar to the script...

A determinate progress bar would be nice but the main purpose of the script is to backup a user profile and store it on a .dmg file, a process which I think probably has an unguessable / indeterminable duration.


Most if the options on the Yosemite Updates for progress automation, include step counter in order to show progress, but there is no way to that I have found, to add just a barber pole that spins until the script is done doing the backup or the restore.

I have been told I should probably go the Xcode way since it has widgets I can use, but I tried to build my script in Xcode and I got lost.