display (growl) number of incomplete ical "to dos"

Hello, I’ve tried getting this work work for a while and seem to be stuck. I’ll spare you my ridiculous code errors and provide the chunks that actually work.

I was able to find this snippet on the web which displays all iCal “to dos” that don’t have a completion date, but it pops up each “to do” item as an individual growl notification.

set applicationName to "GrowlTodo"
set allNotifications to {"Todos"}
set defaultNotifications to allNotifications
tell application "GrowlHelperApp" to ¬
	register as application applicationName ¬
		all notifications allNotifications ¬
		default notifications defaultNotifications ¬
		icon of application "iCal"
tell application "iCal"
	repeat with thisCalendar in calendars
		repeat with thisTodo in (every todo of thisCalendar)
			if (not (completion date of thisTodo exists)) then
				tell thisTodo
					set todoSummary to (summary)
				end tell
				tell application "GrowlHelperApp" to ¬
					notify with name ¬
						"Todos" title "Todo" description todoSummary ¬
						application name applicationName
			end if
		end repeat
	end repeat
end tell

That’s pretty cool, but I would like to consolidate to one growl notification to just display the number of incomplete “to dos”. So I would get a notification such as “you have 5 incomplete tasks”.

Using this method:

tell application "iCal"
	display dialog (count every todo of every calendar) buttons "OK" default button "OK"
end tell

I can show the total number of “to dos”, but it also shows the completed ones, since it does not look for a completion date. After a few tries, I can not figure out how to integrate “count” into the first script above to

  1. Look at all calendars
  2. Look at all to dos
  3. Ignore to dos with completed date present
  4. Count all to-dos (except those with completion date)
  5. Output the number of uncompleted to dos to a growl notification

Another important thing to mention is that if there are no uncompleted “to dos” the first script does not generate any growl notifications and I’d like to keep it that way as I intend to add this to my crontab to run every x minutes.
Can anyone please give me some pointers?

This works for me. You have to build a string of todos to be displayed inside your loop but the actual call to GrowlHelperApp should only happen once, so has to be outside your loop.

set applicationName to "GrowlTodo"
set allNotifications to {"Todos"}
set defaultNotifications to allNotifications
tell application "GrowlHelperApp" to ¬
	register as application applicationName ¬
		all notifications allNotifications ¬
		default notifications defaultNotifications ¬
		icon of application "iCal"
set TodosNotDone to "" -- this is the string to hold the paragraphs of todos we find that will be displayed by Growl.
tell application "iCal"
	repeat with thisCalendar in calendars
		repeat with thisTodo in (every todo of thisCalendar)
			if (not (completion date of thisTodo exists)) then tell thisTodo to set TodosNotDone to TodosNotDone & summary & return
		end repeat
	end repeat
	tell application "GrowlHelperApp" to ¬
		notify with name ¬
			"Todos" title "Todo" description TodosNotDone ¬
			application name applicationName
end tell

Thank you so much Adam! This does exactly what I need. This was my first try at applescript and I’m really amazed at all the possibilities it has.

You’re welcome, Steve. I’ve modified mine a bit to show how many todos are not done in the title.

set applicationName to "GrowlTodos"
set allNotifications to {"Todos"}
set defaultNotifications to allNotifications
tell application "GrowlHelperApp" to ¬
	register as application applicationName ¬
		all notifications allNotifications ¬
		default notifications defaultNotifications ¬
		icon of application "iCal"
set TodosNotDone to ""
tell application "iCal"
	repeat with thisCalendar in calendars
		repeat with thisTodo in (every todo of thisCalendar)
			if (not (completion date of thisTodo exists)) then tell thisTodo to set TodosNotDone to TodosNotDone & summary & return
		end repeat
	end repeat
	set P to ((count paragraphs of TodosNotDone) - 1) as string -- last one is a return left over from string building.
	tell application "GrowlHelperApp" to ¬
		notify with name ¬
			"Todos" title P & " ToDos Not Done" description TodosNotDone ¬
			application name applicationName
end tell

Hi Adam, that is awesome!

That change really puts a nice touch on it. The only thing that can be improved I think, is the original script would not generate a growl if there are no incomplete items in the to do list. So you’re only “nagged” if you have something to do. But with the much improved version we get a growl pop-up with an empty description, or with the latest version it displays “-1 Todos not done” with an empty description.

Hi.

Nothing to do the Growl problem, but just out of interest: a variation on the above code which works with iCals 2.0.5 and 1.5.5 (and I assume with iCal 3.0):

-- Growl stuff.

set TodosNotDone to ""
tell application "iCal" to set {summaryLists, completionDateLists} to {summary, completion date} of todos of calendars
repeat with i from 1 to (count completionDateLists)
	repeat with j from 1 to (count item i of completionDateLists)
		if (item j of item i of completionDateLists is missing value) then set TodosNotDone to TodosNotDone & item j of item i of summaryLists & return
	end repeat
end repeat

-- Growl stuff.

‘summaryLists’ is a list of lists (corresponding to the calendars) of the todo summaries; ‘completionDates’ is a matching list of lists of their completion dates. Where a todo doesn’t have a completion date, its place in the ‘completionDates’ hierarchy is held with a ‘missing value’.

Getting all the data with one iCal command and then processing them with vanilla AppleScript is faster than having the script itself loop through the individual calendars and todos in iCal. This might make a difference if you have a large number of calendars and/or todos to check.

Thanks Nigel! I really appreciate the tips as I am an absolute beginner.

I haven’t tried this yet as I’m traveling with a different computer :frowning:

But I’ll give it a go as soon as I get a chance. Also on my “todo” list it trying to figure out how to not have the growl pop up at all when there’s no uncompleted “todos” in iCal. I noticed that gets annoying fast when you have it in your launchd every 15 minutes :slight_smile:

I have to thank you guys again for the help!

I’ve made some changes to the script to use the more efficient calendar lookup method above, and I think I’ve got the kinks worked out. It should no longer display a “-1” if there are 0 uncompleted “todos”, in fact it will no longer generate a growl pop-up at all, unless there is at least 1 uncompleted “todo”. So now I can run this using osascript every x minutes (I used lingon.app) and it will remind me to stop procrastinating :slight_smile:

I’m not sure if I used the best method to do this, but it’s working fine for me so far (on osx 10.5.6/iCal 3.0.6).


set applicationName to "GrowlTodos"
set allNotifications to {"Todos"}
set defaultNotifications to allNotifications
tell application "GrowlHelperApp" to ¬
	register as application applicationName ¬
		all notifications allNotifications ¬
		default notifications defaultNotifications ¬
		icon of application "iCal"
set TodosNotDone to ""
tell application "iCal" to set {summaryLists, completionDateLists} to {summary, completion date} of todos of calendars
repeat with i from 1 to (count completionDateLists)
	repeat with j from 1 to (count item i of completionDateLists)
		if (item j of item i of completionDateLists is missing value) then set TodosNotDone to TodosNotDone & item j of item i of summaryLists & return
	end repeat
end repeat
set P to ((count paragraphs of TodosNotDone)) as string -- last one is a return left over from string building.
set N to 0
if P > 0 then set N to (P - 1) as string
if N is not equal to 0 then tell application "GrowlHelperApp" to ¬
	notify with name ¬
		"Todos" title N & " Uncompleted Tasks" description TodosNotDone ¬
		application name applicationName