You are not logged in.
Here is the script I wrote to display icalendar events in conky using calcurse.
I wrote this after finding that this script no longer worked correctly.
After looking into making recurring appointments work I found that this was not possible using calcurse.
I switched to using the icalendar python module to directly parse icalendar files instead of having calcurse do it for me.
The new script does everything the other scripts did and is less buggy.
The script now supports DAILY, WEEKLY, and YEARLY recurring appointment types.
The MONTHLY recurring appointment type is more complicated to handle due to months having different numbers of days and is not supported yet.
The script should inform you of any types of recurring appointments I have not discovered yet so I can add functions to handle them.
You will need to install v3.0 or higher of the icalendar Python module.
If your OS has a package for pip you can install the icalendar module with
pip install icalendaras root.
Otherwise follow the install instructions from wherever you get it from.
Someone left a debugging print statement in the current version (v3.0.1b2) of the icalendar module so you will need to open
/usr/local/lib/python2.7/dist-packages/icalendar/cal.pyas root and change line 384 from
print vals.to_ical()to
#print vals.to_ical()or it will print a bunch of unecessary stuff before the appointments and calendar are printed by the script.
I have been told this has already been fixed for the next version of the icalendar module.
Here is the new script it outputs both the appointments and calendar by default.
That can be changed if you don't want both.
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
"""
Name: conky_icalendar_2.py
Author: arclance
Date_Created:2012-01-10
Date_Updated:2012-05-11
Reads the evolution calendar(or another ical calendar) using calcurse and format the output for dispaly in conky.
Does not work with recurring appointments yet (need to write appointment sorting function first).
Requires
icalendar python package v3.0 or higher | http://pypi.python.org/pypi/icalendar/3.0.1b2#downloads
time
subprocess
Changelog
v2.5.1 2012-05-11
fix for displaying non-ascii characters in conky (worked in terminal before this makes it work in conky)
v2.5 2012-05-10
Add support for DAILY, WEEKLY, and YEARLY recurring events
v2.0 2012-05-09
replace calcurse with icalendar python module
rewrite appointment display
fixed to12Hour (12 PM was showed as 12 AM | 12 AM would have been displayed as 00 AM)
- 2012-05-10 -
rewrite calendar display
fixed entry duplication bug in appointmentDates
"""
import time
from subprocess import Popen, PIPE
from icalendar.cal import Calendar, Event
from icalendar.prop import vDatetime, vDDDTypes, vDDDLists
#### user defined variables ####
daysToDisplay = 3 # number of days to display appointments for
icalendarPath = '~/.local/share/evolution/calendar/system/calendar.ics' # location of ics format calendar file, default is the loctaion for evolution but files from other programs should work but are untested
calendarFont = "DejaVu Sans Mono:size=10"
defaultColor = "${color}"
color0 = "${color0}"
usingShading = False # Set to True if using draw_shades yes
defaultShadeColor = "${shadecolor 8B0000}"
secondaryShadeColor = "${shadecolor 000000}"
#### end user defined variables ####
def to12Hour(inputTime):
Hour = int(inputTime.split(":")[0])
Minute = int(inputTime.split(":")[1])
if Hour >= 12: # check for 24 hour format
if Hour > 12:
Hour = (Hour - 12) # make 12 hour format
#endif
_12HourTime = str(Hour).rjust(2, "0") + ':' + str(Minute).rjust(2, "0") + ' PM' # make sunset time string
else:
if Hour == 0:
Hour = 12
#endif
_12HourTime = str(Hour).rjust(2, "0") + ':' + str(Minute).rjust(2, "0") + ' AM' # make sunset time string
#endif
return _12HourTime
#enddef
def timeUntil(inputTime, dayHappens):
Hour = int(inputTime.split(":")[0])
Minute = int(inputTime.split(":")[1])
secondsFromTimeZero = (60*60*Hour) + (60*Minute) # calculate seconds from start of day of event to the event
currentHour = int(time.strftime('%H', time.localtime(time.time()))) # get current hour
currentMinute = int(time.strftime('%M', time.localtime(time.time()))) # get current minute
secondsSinceTimeZero = (60*60*currentHour) + (60*currentMinute) # calculate seconds since the start of today
if dayHappens == 0:
if secondsSinceTimeZero > secondsFromTimeZero: # event has already ocurred
secondsLeft = - secondsFromTimeZero + secondsSinceTimeZero # calculate seconds until the event
hoursLeft = secondsLeft / 3600 # get hours left
minutesLeft = (secondsLeft % 3600) / 60 # get minutes left
timeLeft = "-" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
else:
secondsLeft = secondsFromTimeZero - secondsSinceTimeZero # calculate seconds until the event
hoursLeft = secondsLeft / 3600 # get hours left
minutesLeft = (secondsLeft % 3600) / 60 # get minutes left
if secondsLeft <= (3600*0.5):
if usingShading == True:
timeLeft = " " + secondaryShadeColor + "${color EE0000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") + defaultShadeColor # make timeLeft string
else:
timeLeft = " ${color EE0000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
elif secondsLeft <= (3600*1.5):
timeLeft = " ${color FF8000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
elif secondsLeft <= (3600*2.5):
timeLeft = " ${color EEEE00}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
elif secondsLeft <= (3600*4):
if usingShading == True:
timeLeft = " " + secondaryShadeColor + "${color 006400}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") + defaultShadeColor # make timeLeft string
else:
timeLeft = " ${color 006400}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
else:
timeLeft = " " + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
#endif
else:
timeLeftInToday = (60*60*24) - (60*60*currentHour) - (60*currentMinute) # calcuate seconds until the end of the current day
secondsLeft = timeLeftInToday + (3600*24*(dayHappens -1)) + secondsFromTimeZero # calcualate seconds until event
hoursLeft = secondsLeft / 3600 # get hours left
minutesLeft = (secondsLeft % 3600) / 60 # get minutes left
if secondsLeft <= (3600*0.5):
if usingShading == True:
timeLeft = " " + secondaryShadeColor + "${color EE0000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") + defaultShadeColor # make timeLeft string
else:
timeLeft = " ${color EE0000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
elif secondsLeft <= (3600*1.5):
timeLeft = " ${color FF8000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
elif secondsLeft <= (3600*2.5):
timeLeft = " ${color EEEE00}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
elif secondsLeft <= (3600*4):
if usingShading == True:
timeLeft = " " + secondaryShadeColor + "${color 006400}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") + defaultShadeColor # make timeLeft string
else:
timeLeft = " ${color 006400}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
else:
timeLeft = " " + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
#endif
return timeLeft
#enddef
##############################
class eventList:
def __init__(self):
self._listOfEvents = []
self._daysToDisplay = daysToDisplay
self._currentTime = time.time()
self._currentDate = time.strftime('%Y-%m-%d' ,time.localtime(float(self._currentTime)))
self._currentDateSplit = self._currentDate.split("-")
self._currentWeekday = time.strftime('%a' ,time.localtime(float(self._currentTime)))
self._checkDates = [self._currentDate]
for i in xrange(self._daysToDisplay - 1):
self._checkDates.append(time.strftime('%Y-%m-%d' ,time.localtime(float(self._currentTime + float((i + 1)*3600*24)))))
#endfor
#### Appointments ####
self._hrOffset = "${voffset -8}"
self._dayHeaderOffset = "${voffset -5}"
self._eventOffset = "${voffset -2}"
#### Calendar ####
self._tophrOffset = "${voffset -6}"
self._monthYearAlignment = "${alignc}${voffset -6}"
self._bodyAlignment = "${alignc}${voffset -2}"
#enddef
def appendSingleEvent(self, newEvent):
self._listOfEvents.append(newEvent)
#enddef
def appendReccuringEvent_Weekly(self, startDate, startTime, endDate, endTime, recurDays, recurEndDate, recurCount, typeWeekly, summary): # eventList.appendReccuringEvent_Weekly(eventStartDate, eventStartTime, eventEndDate, eventEndTime, eventRecurDays, eventRecurEndDate, eventSummary)
# UNTIL=20120518;BYDAY=SA,SU,MO,TU,WE,TH,FR
#print str(recurEndDate)
#print type(recurDays[0])
for i in xrange(len(recurDays)):
recurDays[i] = str(recurDays[i]).strip().replace("SA","Sat").replace("SU","Sun").replace("MO","Mon").replace("TU","Tue").replace("WE","Wed").replace("TH","Thu").replace("FR","Fri")
#endfor
#print str(recurDays)
if typeWeekly == 1:
#print len(str(recurEndDate))
if len(str(recurEndDate)) < 19:
recurEndDate_Seconds = time.mktime(time.strptime(str(recurEndDate), "%Y-%m-%d"))
else:
recurEndDate_Seconds = time.mktime(time.strptime(str(recurEndDate), "%Y-%m-%d %H:%M:%S"))
#endif
if recurEndDate_Seconds > self._currentTime: # only calculate recurring events if the reccurance has not ended yet
#print str(recurEndDate_Seconds)
numDays = 0
timeStartSeconds = dateInSeconds(startDate, startTime)
timeEndSeconds = dateInSeconds(endDate, endTime)
checkDateSeconds = float(timeStartSeconds + float(numDays*3600*24))
dayOfWeek = time.strftime('%a' ,time.localtime(checkDateSeconds))
while checkDateSeconds < recurEndDate_Seconds:
#break
#print dayOfWeek
if dayOfWeek in recurDays:
checkStartDate = time.strftime('%Y-%m-%d',time.localtime(checkDateSeconds))
checkEndDate = time.strftime('%Y-%m-%d',time.localtime(float(timeEndSeconds + float(numDays*3600*24))))
self._listOfEvents.append([checkDateSeconds, checkStartDate, startTime, checkEndDate, endTime, summary, "WEEKLY"])
#endif
numDays = numDays + 1
checkDateSeconds = float(timeStartSeconds + float(numDays*3600*24))
dayOfWeek = time.strftime('%a' ,time.localtime(checkDateSeconds))
#endwhile
#pass
#endif
elif typeWeekly == 2:
#print recurCount[0]
numOccurances = 0
numDays = 0
timeStartSeconds = dateInSeconds(startDate, startTime)
timeEndSeconds = dateInSeconds(endDate, endTime)
while numOccurances < recurCount[0]:
#break
checkDateSeconds = float(timeStartSeconds + float(numDays*3600*24))
dayOfWeek = time.strftime('%a' ,time.localtime(checkDateSeconds))
#print dayOfWeek
if dayOfWeek in recurDays:
checkStartDate = time.strftime('%Y-%m-%d',time.localtime(checkDateSeconds))
checkEndDate = time.strftime('%Y-%m-%d',time.localtime(float(timeEndSeconds + float(numDays*3600*24))))
self._listOfEvents.append([checkDateSeconds, checkStartDate, startTime, checkEndDate, endTime, summary, "WEEKLY"])
numOccurances = numOccurances + 1
#endif
numDays = numDays + 1
#endwhile
#endif
#pass # for now
#enddef
def appendReccuringEvent_Daily(self, startDate, startTime, endDate, endTime, recurEndDate, recurCount, recurInterval, typeDaily, summary):
if typeDaily == 1:
#break
timeStartSeconds = dateInSeconds(startDate, startTime)
timeEndSeconds = dateInSeconds(endDate, endTime)
#print (recurCount[0]*recurInterval[0])
for i in xrange(0, int(recurCount[0]*recurInterval[0]), recurInterval[0]):
#break
#print i
checkDateSeconds = float(timeStartSeconds + float(i*3600*24))
checkStartDate = time.strftime('%Y-%m-%d',time.localtime(checkDateSeconds))
#print checkStartDate
checkEndDate = time.strftime('%Y-%m-%d',time.localtime(float(timeEndSeconds + float(i*3600*24))))
self._listOfEvents.append([checkDateSeconds, checkStartDate, startTime, checkEndDate, endTime, summary, "DAILY"])
#endfor
elif typeDaily == 2:
#break
timeStartSeconds = dateInSeconds(startDate, startTime)
timeEndSeconds = dateInSeconds(endDate, endTime)
for i in xrange(recurCount[0]):
#break
checkDateSeconds = float(timeStartSeconds + float(i*3600*24))
checkStartDate = time.strftime('%Y-%m-%d',time.localtime(checkDateSeconds))
checkEndDate = time.strftime('%Y-%m-%d',time.localtime(float(timeEndSeconds + float(i*3600*24))))
self._listOfEvents.append([checkDateSeconds, checkStartDate, startTime, checkEndDate, endTime, summary, "DAILY"])
#endfor
#endif
#enddef
def appendReccuringEvent_Monthly(self):
pass
#enddef
def appendReccuringEvent_Yearly(self, startDate, startTime, endDate, endTime, recurCount, typeYearly, summary):
if typeYearly == 1:
timeStartSeconds = dateInSeconds(startDate, startTime)
timeEndSeconds = dateInSeconds(endDate, endTime)
for i in xrange(recurCount[0]):
#break
checkDateSeconds = float(timeStartSeconds + float(i*3600*24*365))
checkStartDate = time.strftime('%Y-%m-%d',time.localtime(checkDateSeconds))
checkEndDate = time.strftime('%Y-%m-%d',time.localtime(float(timeEndSeconds + float(i*3600*24*365))))
self._listOfEvents.append([checkDateSeconds, checkStartDate, startTime, checkEndDate, endTime, summary, "YEARLY"])
#endfor
#endif
#enddef
def sortList(self):
self._sortedList = sorted(self._listOfEvents, key=lambda epoch: int(epoch[0]))
#enddef
def returnList(self):
return self._listOfEvents
#enddef
def returnSortedList(self):
return self._sortedList
#enddef
def conkyApts(self):
previousDate = ""
outputString = "" # set outputString to empty String
##print "conkyApts Test"
for l in xrange(len(self._sortedList)):
for i in xrange(len(self._checkDates)):
checkDateString = self._checkDates[i]
if (str(self._sortedList[l][1]).strip() == checkDateString):
##print "date match"
if i == 0: # today
if previousDate != self._sortedList[l][1]:
dayName = time.strftime('%A' ,time.localtime(float(self._currentTime + float(3600*24*i)))) # get the weekday name
outputString = outputString + self._hrOffset + color0 + "${hr}\n" + self._dayHeaderOffset + defaultColor + "Today (" + dayName + ") " + color0 + "- " + defaultColor + "" + checkDateString #
previousDate = checkDateString
#endif
startTime = self._sortedList[l][2]
endTime = self._sortedList[l][4]
eventName = self._sortedList[l][5]
outputString = outputString + "\n" + self._eventOffset + "" + color0 + "" + to12Hour(startTime) + " " + defaultColor + "-> " + color0 + "" + to12Hour(endTime) + " |" + defaultColor + "" + timeUntil(startTime, i) + " " + color0 + "| " + defaultColor + "" + eventName.replace("$","$$") #
elif i == 1: # tommorow
if previousDate != self._sortedList[l][1]:
dayName = time.strftime('%A' ,time.localtime(float(self._currentTime + float(3600*24*i)))) # get the weekday name
outputString = outputString + "\n" + self._hrOffset + color0 + "${hr}\n" + self._dayHeaderOffset + defaultColor + "Tommorow (" + dayName + ") " + color0 + "- " + defaultColor + "" + checkDateString#
previousDate = checkDateString
#endif
startTime = self._sortedList[l][2]
endTime = self._sortedList[l][4]
eventName = self._sortedList[l][5]
outputString = outputString + "\n" + self._eventOffset + "" + color0 + "" + to12Hour(startTime) + " " + defaultColor + "-> " + color0 + "" + to12Hour(endTime) + " |" + defaultColor + "" + timeUntil(startTime, i) + " " + color0 + "| " + defaultColor + "" + eventName.replace("$","$$") #
else:
if previousDate != self._sortedList[l][1]:
dayName = time.strftime('%A' ,time.localtime(float(self._currentTime + float(3600*24*i)))) # get the weekday name
outputString = outputString + "\n" +self._hrOffset + color0 + "${hr}\n" + self._dayHeaderOffset + defaultColor + "" + dayName + " " + color0 + "- " + defaultColor + "" + checkDateString #
previousDate = checkDateString
#endif
startTime = self._sortedList[l][2]
endTime = self._sortedList[l][4]
eventName = self._sortedList[l][5]
outputString = outputString + "\n" + self._eventOffset + "" + color0 + "" + to12Hour(startTime) + " " + defaultColor + "-> " + color0 + "" + to12Hour(endTime) + " |" + defaultColor + "" + timeUntil(startTime, i) + " " + color0 + "| " + defaultColor + "" + eventName.replace("$","$$") #
#endif
#endif
#endfor
#endfor
if outputString != "":
return outputString.strip()
else:
return self._hrOffset + color0 + "${hr}\n" + self._dayHeaderOffset + defaultColor + "No Events"
#endif
#enddef
def conkyCalendar(self):
(stdout, stderr) = Popen(["cal"], stdout=PIPE, stderr=PIPE).communicate()
if stderr != "":
print "cal error = " + stderr
#endif
rawcalendar = stdout.strip().split("\n")
lastDateMonth = rawcalendar[len(rawcalendar) - 1].strip().split(" ")
#print lastDateMonth
lastDateMonth = lastDateMonth[len(lastDateMonth) - 1].replace("_\x08","")
"""
currentYear = self._currentDateSplit[0]
currentMonth = self._currentDateSplit[1]
currentDay = self._currentDateSplit[2]
"""
#print self._currentDateSplit[2]
appointmentDates = []
for l in xrange(len(self._sortedList)):
for i in xrange(1, (int(lastDateMonth) + 1)):
checkDateString = self._currentDateSplit[0] + "-" + self._currentDateSplit[1] + "-" + str(i).rjust(2, "0")
if self._sortedList[l][1] == checkDateString and (str(i) not in appointmentDates):
appointmentDates.append(str(i))
#endif
#endfor
#endfor
#print str(appointmentDates)
finalcalendar = self._tophrOffset + color0 + "${hr}\n"
for m in xrange(len(rawcalendar)):
if m == 0:
finalcalendar = finalcalendar + self._monthYearAlignment + color0 + rawcalendar[m].strip() + "\n"
elif m == 1:
finalcalendar = finalcalendar + self._bodyAlignment + color0 + rawcalendar[m].strip() + "\n"
elif len(rawcalendar[m].strip()) != 0:
#print "len test"
rawcalendar[m] = rawcalendar[m] + " "
rawLength = len(rawcalendar[m])
for k in xrange(len(appointmentDates)):
if appointmentDates[k] == str(self._currentDateSplit[2]):
if usingShading == True:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(appointmentDates[k].rjust(2," ").ljust(3," "), ("${font " + calendarFont + ":style=bold}" + secondaryShadeColor + "${color EE0000}" + appointmentDates[k].rjust(2," ").ljust(3," ") + "${font}" + defaultShadeColor + defaultColor)) # make today bold and red if it has an appointment
else:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(appointmentDates[k].rjust(2," ").ljust(3," "), ("${font " + calendarFont + ":style=bold}${color EE0000}" + appointmentDates[k].rjust(2," ").ljust(3," ") + "${font}" + defaultColor)) # make today bold and red if it has an appointment
#endif
else:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(appointmentDates[k].rjust(2," ").ljust(3," "), (color0 + appointmentDates[k].rjust(2," ").ljust(3," ") + defaultColor)) # make other day a different color if they have appointments
#endif
#endfor
if str(self._currentDateSplit[2]) not in appointmentDates:
if usingShading == True:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(str(currentDate).rjust(2," ").ljust(3," "), ("${font " + calendarFont + ":style=bold}" + secondaryShadeColor + "${color 006400}" + str(currentDate).rjust(2," ").ljust(3," ") + "${font}" + defaultShadeColor + defaultColor)) # make today bold and green if it does not have an appointment
else:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(str(currentDate).rjust(2," ").ljust(3," "), ("${font " + calendarFont + ":style=bold}${color 006400}" + str(currentDate).rjust(2," ").ljust(3," ") + "${font}" + defaultColor)) # make today bold and green if it does not have an appointment
#endif
#endif
if i == 2:
finalcalendar = finalcalendar + self._bodyAlignment + defaultColor + (" " * (21 - rawLength)) + rawcalendar[m] + "\n"
else:
finalcalendar = finalcalendar + self._bodyAlignment + defaultColor + rawcalendar[m] + (" " * (21 - rawLength)) + "\n"
#endif
#endif
#endfor
return str(finalcalendar).strip("\n")
#enddef
#endclass
def dateInSeconds(startDate, startTime):
timeStruct = time.strptime((startDate + " " + startTime), "%Y-%m-%d %H:%M:%S")
return time.mktime(timeStruct)
#enddef
def parseTest():
rawCalendar = open(icalendarPath, "rb") # open calendar for reading
evoCalendar = rawCalendar.read()
rawCalendar.close()
####
#print "importing"
parsCalendar = Calendar.from_ical(evoCalendar)
#print "walking"
eventHolder = eventList()
for component in parsCalendar.walk('VEVENT'):
#print component
#print component.canonical_order
#print component.name
eventSummary = component['SUMMARY']
#print str(compSummary)
compDTStart = component['DTSTART'].to_ical()
#print compDTStart
if compDTStart.find("T") != (-1):
[eventStartDate, eventStartTime] = str(vDatetime.from_ical(compDTStart)).split(" ")
else:
#print "no start time"
#print str(compDTStart)
eventStartDate = compDTStart[0:4] + "-" + compDTStart[4:6] + "-" + compDTStart[6:8]
eventStartTime = "00:00:00"
#endif
eventStartSeconds = dateInSeconds(eventStartDate, eventStartTime)
#print str(eventStartSeconds)
compDTEnd = component['DTEND'].to_ical()
if compDTEnd.find("T") != (-1):
[eventEndDate, eventEndTime] = str(vDatetime.from_ical(compDTEnd)).split(" ")
else:
#print "no end time"
#print str(compDTEnd)
eventEndDate = compDTEnd[0:4] + "-" + compDTEnd[4:6] + "-" + compDTEnd[6:8]
eventEndTime = "23:59:59"
#endif
try:
compRRule = component['RRULE']
#print eventSummary
#print str(compRRule)
eventRecurFreq = compRRule['FREQ']
#print str(eventRecurFreq)
except Exception, e:
#print "RRule Error = " + str(e)
compRRule = "N/A"
#endtry
weeklyType = 0
dailyType = 0
yearlyType = 0
if compRRule == "N/A": # Single appointments
eventHolder.appendSingleEvent([eventStartSeconds, eventStartDate, eventStartTime, eventEndDate, eventEndTime, eventSummary, compRRule])
elif eventRecurFreq[0] == "WEEKLY": # Weekly reccuring appointments ## RRULE:FREQ=WEEKLY;UNTIL=20111209T040000;BYDAY=MO,WE,FR;COUNT=4
#print str(eventRecurFreq[0])
try:
eventRecurDays = compRRule['BYDAY']
except Exception, e:
print "Error Unknown WEEKLY Recurring Appointment Type: " + str(e)
break
#endtry
try: # check for WEEKLY events defined by enddate
eventRecurEndDate = compRRule['UNTIL'][0]
weeklyType = 1
eventRecurCount = "N/A"
except Exception, e:
pass
#endtry
try: # check for WEEKLY events defined by number of occurances
eventRecurCount = compRRule['COUNT']
weeklyType = 2
eventRecurEndDate = "N/A"
except Exception, e:
pass
#endtry
if weeklyType != 0:
eventHolder.appendReccuringEvent_Weekly(eventStartDate, eventStartTime, eventEndDate, eventEndTime, eventRecurDays, eventRecurEndDate, eventRecurCount, weeklyType, eventSummary)
#endif
elif eventRecurFreq[0] == 'DAILY': # Daily reccruing appointments ## RRULE;X-EVOLUTION-ENDDATE=20120525T233000Z:FREQ=DAILY;COUNT=8;INTERVAL=2;
#print eventSummary
#print str(compRRule)
try: # check for DAILY events that occur at a interval of every other day or greater
eventRecurInterval = compRRule['INTERVAL']
eventRecurCount = compRRule['COUNT']
eventRecurEndDate = "N/A"
dailyType = 1
except Exception, e:
#print str(e)
pass
#endtry
if dailyType != 1:
try: # check for DAILY
eventRecurCount = compRRule['COUNT']
dailyType = 2
eventRecurEndDate = "N/A"
eventRecurInterval = 1
except Exception, e:
print "Error Unknown DAILY Recurring Appointment Type: " + str(e)
#pass
#endtry
#endif
if dailyType != 0:
eventHolder.appendReccuringEvent_Daily(eventStartDate, eventStartTime, eventEndDate, eventEndTime, eventRecurEndDate, eventRecurCount, eventRecurInterval, dailyType, eventSummary)
#endif
pass # for now
elif eventRecurFreq[0] == 'MONTHLY':
pass # this is the most complicated type and I don't use it, it can wait till later
elif eventRecurFreq[0] == 'YEARLY': #RRULE;X-EVOLUTION-ENDDATE=20140511T000000Z:FREQ=YEARLY;COUNT=3;WKST=SA
try: # check for YEARLY
eventRecurCount = compRRule['COUNT']
yearlyType = 1
except Exception, e:
#print str(e)
print "Error Unknown YEARLY Recurring Appointment Type: " + str(e)
#pass
#endtry
if yearlyType != 0:
eventHolder.appendReccuringEvent_Yearly(eventStartDate, eventStartTime, eventEndDate, eventEndTime, eventRecurCount, yearlyType, eventSummary)
#endif
else:
print "Error Unknown Recurring Appointment Type: " + str(eventRecurFreq)
#pass
#endif
#endfor
"""
unsortedList = eventHolder.returnList()
for i in xrange(len(unsortedList)):
# print str(unsortedList[i])
#endfor
"""
eventHolder.sortList()
#sortedList = eventHolder.returnSortedList()
#print ""
#for i in xrange(len(sortedList)):
# print str(sortedList[i])
#endfor
print (eventHolder.conkyApts()).encode('utf-8')
print eventHolder.conkyCalendar().encode('utf-8')
#enddef
#########
#timeStart = time.time()
parseTest()
#print "time end = " + str(time.time() - timeStart) + "s"Features
The scripts are written in Python and use the icalendar module to process the icalendar file into a simpler format.
The script reads the Evolution calendar by default but it should work with icalendar formated files produced by other programs.
Support for DAILY, WEEKLY, and YEARLY recurring appointment types.
Appointments
The remaing time until an event starts will change colors as it gets closer to starting.
Events that have already started show the time since they started as a negative value.
Calendar
The calendar is centered in the conky window.
Days without events are displayed in conkys configured default_color.
Days with events are displayed in conkys configured color0
The current day is displayed in green if there are no events today.
The current day is displayed in red if there are events today.
Limitations
MONTHLY reccuring appointments are not supported for now.
How To Use
The scripts should be run from conky using ${execp} or ${execpi}.
If you don't want the appointemnts to be output change line 529 to
#print eventHolder.conkyApts()If you don't want the calendar to be output change line 530 to
#print eventHolder.conkyCalendar()Configuraton
Make sure
calendarLocation = '~/.local/share/evolution/calendar/system/calendar.ics' # location of ics format calendar file, default is the loctaion for evolution but files from other programs should work but are untestedis the path to your icalendar file.
Set
daysToDisplay = 3 # number of days to display appointments forto the number of days you want to display events for.
Set
calendarFont = "DejaVu Sans Mono:size=10"to your conkys default font.
If you have draw_shades yes in your .conkyrc change
usingShading = False # Set to True if using draw_shades yesto
usingShading = True # Set to True if using draw_shades yesand configure
defaultShadeColor = "${shadecolor 8B0000}"to match your .conkyrc to improve the appearance of the countdown text.
Changelog
v2.5.1 2012-05-11
fix for displaying non-ascii characters in conky
v2.5 2012-05-10
Add support for DAILY, WEEKLY, and YEARLY recurring events
v2.0 2012-05-09
replace calcurse with icalendar python module
rewrite appointment display
fixed to12Hour (12 PM was showed as 12 AM | 12 AM would have been displayed as 00 AM)
- 2012-05-10 -
rewrite calendar display
fixed entry duplication bug in appointmentDates
Last edited by arclance (2012-05-11 19:23:20)
Offline
When you say icalender, are you refereing to iCal on mac?
If so i will be giving this a try for sure!
Offline
When you say icalender, are you refereing to iCal on mac?
If so i will be giving this a try for sure!
Yes according to wikipedia iCal uses the icalendar format to store it's calendar so it should work.
Just change Script 1 so it uses the calendar file from iCal instead of the defalult settings.
I have only tested the script on icalendar files produced by Evolution so I can't be absolutely sure it will work.
Offline
ok, so i tried this script. But something occured.
On my conky on desktop i get:
remove notes error = [Errno 2] No such file or directory: '/home/kerel/.calcurse/notes'
calcurse import error = utils.c: 859: temporary file "/home/kerel/.calcurse/notes/gJNng3"
io.c: 2349: Warning: could not create new note file to store description. Aborting...
" + color0 + "_________________________________________________________________
" + defaultColor + "No EventsThats all... I setuped everything, from my .conkyrc file i use ${execp python ~/evolutionconky.py} command to get script. Do you know what is the problem ?
Thanks for response.... 
Last edited by ZlyChleba (2012-05-10 17:06:23)
Offline
ok, so i tried this script. But something occured.
On my conky on desktop i get:remove notes error = [Errno 2] No such file or directory: '/home/kerel/.calcurse/notes'
That is normal the first time you run the script the errors happen because calcurse has not written any files yet.
calcurse import error = utils.c: 859: temporary file "/home/kerel/.calcurse/notes/gJNng3" io.c: 2349: Warning: could not create new note file to store description. Aborting...
That comes from calcurse indicating it was unable to write one of its output files.
You don't need that file so as long as the ones you do need were written first it should not be a problem (other than it appearing on your conky).
Is the partion your /home is on full?
/home/kerel/.calcurse is not read only is it?
" + color0 + "_________________________________________________________________ " + defaultColor + "No EventsThats all... I setuped everything, from my .conkyrc file i use ${execp python ~/evolutionconky.py} command to get script. Do you know what is the problem ?
Thanks for response....
That was caused by a typo left from when I moved the color configuration to the top so it would be easy to find.
I updated the first post with a fixed version.
I looked into making recurring appointments work yesterday and found that calcurse does not import them correctely.
I am currently rewriting the script to use the python icalendar package to directly parse the icalendar file without using calcurse.
I have the appoinments section (Script 1) completely rewritten and working.
The script is collecting the data needed to get reccuring appointments working, I just need to write functions to handle the different types of recurring appointments.
I am going to redo the calendar (Script 2) first though.
If you don't need the calendar on the bottom you could try that since it looks like calcurse may be having problems with your icalendar file.
If you don't want to try the new script please run the fixed Script 1 in a terminal and post the output here.
Also post the configuration section of the script so I can make sure you have everything set up correctly.
Offline
Thanks for your reply.
I tried fixed script you posted and the think with
" + color0 + "_________________________________________________________________
" + defaultColor + "No Eventswas soluted.
but, I still get the other errors.
Configuration section :
daysToDisplay = 3 # number of days to display appointments for
homePath = '/home/kerel/' # full path to your home folder
calendarLocation = '.evolution/calendar/local/system/calendar.ics' # location of ics format calendar file, default is the loctaion for evolution but files from other programs should work but are untested
defaultColor = "${color}"
color0 = "${color0}"
usingShading = True # Set to True if using draw_shades yes
defaultShadeColor = "${shadecolor 8B0000}"
secondaryShadeColor = "${shadecolor 000000}"I run the script.py in terminal with command "python script.py" and i got:
remove notes error = [Errno 2] No such file or directory: '/home/kerel/.calcurse/notes'
calcurse import error = utils.c: 859: temporary file "/home/kerel/.calcurse/notes/QvBnV4" could not be created
io.c: 2349: Warning: could not create new note file to store description. Aborting...
${voffset -8}${color0}${hr}
${voffset -5}${color}No EventsOffline
Thanks for your reply.
I tried fixed script you posted and the think with" + color0 + "_________________________________________________________________ " + defaultColor + "No Eventswas soluted.
but, I still get the other errors.
Configuration section :
daysToDisplay = 3 # number of days to display appointments for homePath = '/home/kerel/' # full path to your home folder calendarLocation = '.evolution/calendar/local/system/calendar.ics' # location of ics format calendar file, default is the loctaion for evolution but files from other programs should work but are untested defaultColor = "${color}" color0 = "${color0}" usingShading = True # Set to True if using draw_shades yes defaultShadeColor = "${shadecolor 8B0000}" secondaryShadeColor = "${shadecolor 000000}"I run the script.py in terminal with command "python script.py" and i got:
remove notes error = [Errno 2] No such file or directory: '/home/kerel/.calcurse/notes' calcurse import error = utils.c: 859: temporary file "/home/kerel/.calcurse/notes/QvBnV4" could not be created io.c: 2349: Warning: could not create new note file to store description. Aborting... ${voffset -8}${color0}${hr} ${voffset -5}${color}No Events
Is there a /home/kerel/.calcurse/notes directory?
Maybe it was not created when you installed calcurse?
If not try making one and then running the script again.
Offline
Well, i tried to make folder notes in .calcurse and run the script. But the script deletes the folder and keep printing errors...
Offline
Well, i tried to make folder notes in .calcurse and run the script. But the script deletes the folder and keep printing errors...
I don't know then the script deletes the folder to prevent calcurse from making millions of temporary files so it has to delete the folder.
It is working here the folder is deleted and recreated every time the script runs.
I should have all the features of the current scripts recreated in the new version that does not depend on calcurse in about an hour.
Since you seem to be having problems with calcurse on your system do you want to wait for me to finish that?
Offline
Yes, I would like to wait, with calcurse are only problems... I really appreciate your work
thanks for everything.
Offline
Yes, I would like to wait, with calcurse are only problems... I really appreciate your work
thanks for everything.
Okay here it is.
It does everything the other scripts did and is less buggy.
I have not written the functions for handling recuring appointments yet so they will not be displayed at all.
The script should inform you of any types of recurring appointments I have not discovered yet so I can add functions to handle them.
You will need to install v3.0 or higher of the icalendar Python module.
This python module replaces calcurse which would not have worked with reccuring appointments.
If your OS has a package for pip you can install the icalendar module with
pip install icalendaras root.
Someone left a debugging print statement in the current version of the icalendar module so you will need to open
/usr/local/lib/python2.7/dist-packages/icalendar/cal.pyas root and change line 384 from
print vals.to_ical()to
#print vals.to_ical()or it will print a buch of unecessary stuff before the appointments and calendar are printed by the script.
Here is the new script it outputs both the appointments and calendar by default.
That can be changed if you don't want both.
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
"""
Name:conky_calendar2.py
Author: arclance
Date_Created:2012-01-10
Date_Updated:2012-05-09
Reads the evolution calendar(or another ical calendar) using icalendar and format the output for display in conky.
Does not work with recurring appointments yet (need to write appointment handling function first).
Requires
icalendar python package v3.0 or higher | http://pypi.python.org/pypi/icalendar/3.0.1b2#downloads
time
subprocess
Changelog
v2.0 2012-05-09
replace calcurse with icalendar python module
rewrite appointment display
fixed to12Hour (12 PM was showed as 12 AM | 12 AM would have been displayed as 00 AM)
- 2012-05-10 -
rewrite calendar display
fixed entry duplication bug in appointmentDates
"""
import time
from subprocess import Popen, PIPE
from icalendar.cal import Calendar, Event
from icalendar.prop import vDatetime, vDDDTypes, vDDDLists
#### user defined variables ####
daysToDisplay = 3 # number of days to display appointments for
icalendarPath = '~/.local/share/evolution/calendar/system/calendar.ics' # location of ics format calendar file, default is the loctaion for evolution but files from other programs should work but are untested
calendarFont = "DejaVu Sans Mono:size=10"
defaultColor = "${color}"
color0 = "${color0}"
usingShading = False # Set to True if using draw_shades yes
defaultShadeColor = "${shadecolor 8B0000}"
secondaryShadeColor = "${shadecolor 000000}"
#### end user defined variables ####
def to12Hour(inputTime):
Hour = int(inputTime.split(":")[0])
Minute = int(inputTime.split(":")[1])
if Hour >= 12: # check for 24 hour format
if Hour > 12:
Hour = (Hour - 12) # make 12 hour format
#endif
_12HourTime = str(Hour).rjust(2, "0") + ':' + str(Minute).rjust(2, "0") + ' PM' # make sunset time string
else:
if Hour == 0:
Hour = 12
#endif
_12HourTime = str(Hour).rjust(2, "0") + ':' + str(Minute).rjust(2, "0") + ' AM' # make sunset time string
#endif
return _12HourTime
#enddef
def timeUntil(inputTime, dayHappens):
Hour = int(inputTime.split(":")[0])
Minute = int(inputTime.split(":")[1])
secondsFromTimeZero = (60*60*Hour) + (60*Minute) # calculate seconds from start of day of event to the event
currentHour = int(time.strftime('%H', time.localtime(time.time()))) # get current hour
currentMinute = int(time.strftime('%M', time.localtime(time.time()))) # get current minute
secondsSinceTimeZero = (60*60*currentHour) + (60*currentMinute) # calculate seconds since the start of today
if dayHappens == 0:
if secondsSinceTimeZero > secondsFromTimeZero: # event has already ocurred
secondsLeft = - secondsFromTimeZero + secondsSinceTimeZero # calculate seconds until the event
hoursLeft = secondsLeft / 3600 # get hours left
minutesLeft = (secondsLeft % 3600) / 60 # get minutes left
timeLeft = "-" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
else:
secondsLeft = secondsFromTimeZero - secondsSinceTimeZero # calculate seconds until the event
hoursLeft = secondsLeft / 3600 # get hours left
minutesLeft = (secondsLeft % 3600) / 60 # get minutes left
if secondsLeft <= (3600*0.5):
if usingShading == True:
timeLeft = " " + secondaryShadeColor + "${color EE0000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") + defaultShadeColor # make timeLeft string
else:
timeLeft = " ${color EE0000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
elif secondsLeft <= (3600*1.5):
timeLeft = " ${color FF8000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
elif secondsLeft <= (3600*2.5):
timeLeft = " ${color EEEE00}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
elif secondsLeft <= (3600*4):
if usingShading == True:
timeLeft = " " + secondaryShadeColor + "${color 006400}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") + defaultShadeColor # make timeLeft string
else:
timeLeft = " ${color 006400}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
else:
timeLeft = " " + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
#endif
else:
timeLeftInToday = (60*60*24) - (60*60*currentHour) - (60*currentMinute) # calcuate seconds until the end of the current day
secondsLeft = timeLeftInToday + (3600*24*(dayHappens -1)) + secondsFromTimeZero # calcualate seconds until event
hoursLeft = secondsLeft / 3600 # get hours left
minutesLeft = (secondsLeft % 3600) / 60 # get minutes left
if secondsLeft <= (3600*0.5):
if usingShading == True:
timeLeft = " " + secondaryShadeColor + "${color EE0000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") + defaultShadeColor # make timeLeft string
else:
timeLeft = " ${color EE0000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
elif secondsLeft <= (3600*1.5):
timeLeft = " ${color FF8000}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
elif secondsLeft <= (3600*2.5):
timeLeft = " ${color EEEE00}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
elif secondsLeft <= (3600*4):
if usingShading == True:
timeLeft = " " + secondaryShadeColor + "${color 006400}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") + defaultShadeColor # make timeLeft string
else:
timeLeft = " ${color 006400}" + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
else:
timeLeft = " " + str(hoursLeft).rjust(2, "0") + ":" + str(minutesLeft).rjust(2, "0") # make timeLeft string
#endif
#endif
return timeLeft
#enddef
##############################
class eventList:
def __init__(self):
self._listOfEvents = []
self._daysToDisplay = daysToDisplay
self._currentTime = time.time()
self._currentDate = time.strftime('%Y-%m-%d' ,time.localtime(float(self._currentTime)))
self._currentDateSplit = self._currentDate.split("-")
self._currentWeekday = time.strftime('%a' ,time.localtime(float(self._currentTime))).upper()
self._checkDates = [self._currentDate]
for i in xrange(self._daysToDisplay - 1):
self._checkDates.append(time.strftime('%Y-%m-%d' ,time.localtime(float(self._currentTime + float((i + 1)*3600*24)))))
#endfor
#### Appointments ####
self._hrOffset = "${voffset -8}"
self._dayHeaderOffset = "${voffset -5}"
self._eventOffset = "${voffset -2}"
#### Calendar ####
self._tophrOffset = "${voffset -6}"
self._monthYearAlignment = "${alignc}${voffset -6}"
self._bodyAlignment = "${alignc}${voffset -2}"
#enddef
def appendSingleEvent(self, newEvent):
self._listOfEvents.append(newEvent)
#enddef
def appendReccuringEvent_Weekly(self, newEvent, recurDays, startDate, endDate): # eventList.appendReccuringEvent_Weekly(formatedEvent, eventRecurDays, eventStartDate, eventRecurEndDate)
pass # for now
#enddef
def appendReccuringEvent_Daily(self):
pass # for now
#enddef
def sortList(self):
self._sortedList = sorted(self._listOfEvents, key=lambda epoch: int(epoch[0]))
#enddef
def returnList(self):
return self._listOfEvents
#enddef
def returnSortedList(self):
return self._sortedList
#enddef
def conkyApts(self):
previousDate = ""
outputString = "" # set outputString to empty String
##print "conkyApts Test"
for l in xrange(len(self._sortedList)):
for i in xrange(len(self._checkDates)):
checkDateString = self._checkDates[i]
if (str(self._sortedList[l][1]).strip() == checkDateString):
##print "date match"
if i == 0: # today
if previousDate != self._sortedList[l][1]:
dayName = time.strftime('%A' ,time.localtime(float(self._currentTime + float(3600*24*i)))) # get the weekday name
outputString = outputString + self._hrOffset + color0 + "${hr}\n" + self._dayHeaderOffset + defaultColor + "Today (" + dayName + ") " + color0 + "- " + defaultColor + "" + checkDateString #
previousDate = checkDateString
#endif
startTime = self._sortedList[l][2]
endTime = self._sortedList[l][4]
eventName = self._sortedList[l][5]
outputString = outputString + "\n" + self._eventOffset + "" + color0 + "" + to12Hour(startTime) + " " + defaultColor + "-> " + color0 + "" + to12Hour(endTime) + " |" + defaultColor + "" + timeUntil(startTime, i) + " " + color0 + "| " + defaultColor + "" + eventName.replace("$","$$") #
elif i == 1: # tommorow
if previousDate != self._sortedList[l][1]:
dayName = time.strftime('%A' ,time.localtime(float(self._currentTime + float(3600*24*i)))) # get the weekday name
outputString = outputString + "\n" + self._hrOffset + color0 + "${hr}\n" + self._dayHeaderOffset + defaultColor + "Tommorow (" + dayName + ") " + color0 + "- " + defaultColor + "" + checkDateString#
previousDate = checkDateString
#endif
startTime = self._sortedList[l][2]
endTime = self._sortedList[l][4]
eventName = self._sortedList[l][5]
outputString = outputString + "\n" + self._eventOffset + "" + color0 + "" + to12Hour(startTime) + " " + defaultColor + "-> " + color0 + "" + to12Hour(endTime) + " |" + defaultColor + "" + timeUntil(startTime, i) + " " + color0 + "| " + defaultColor + "" + eventName.replace("$","$$") #
else:
if previousDate != self._sortedList[l][1]:
dayName = time.strftime('%A' ,time.localtime(float(self._currentTime + float(3600*24*i)))) # get the weekday name
outputString = outputString + "\n" +self._hrOffset + color0 + "${hr}\n" + self._dayHeaderOffset + defaultColor + "" + dayName + " " + color0 + "- " + defaultColor + "" + checkDateString #
previousDate = checkDateString
#endif
startTime = self._sortedList[l][2]
endTime = self._sortedList[l][4]
eventName = self._sortedList[l][5]
outputString = outputString + "\n" + self._eventOffset + "" + color0 + "" + to12Hour(startTime) + " " + defaultColor + "-> " + color0 + "" + to12Hour(endTime) + " |" + defaultColor + "" + timeUntil(startTime, i) + " " + color0 + "| " + defaultColor + "" + eventName.replace("$","$$") #
#endif
#endif
#endfor
#endfor
if outputString != "":
return outputString.strip()
else:
return self._hrOffset + color0 + "${hr}\n" + self._dayHeaderOffset + defaultColor + "No Events"
#endif
#enddef
def conkyCalendar(self):
(stdout, stderr) = Popen(["cal"], stdout=PIPE, stderr=PIPE).communicate()
if stderr != "":
print "cal error = " + stderr
#endif
rawcalendar = stdout.strip().split("\n")
lastDateMonth = rawcalendar[len(rawcalendar) - 1].strip().split(" ")
#print lastDateMonth
lastDateMonth = lastDateMonth[len(lastDateMonth) - 1].replace("_\x08","")
"""
currentYear = self._currentDateSplit[0]
currentMonth = self._currentDateSplit[1]
currentDay = self._currentDateSplit[2]
"""
#print self._currentDateSplit[2]
appointmentDates = []
for l in xrange(len(self._sortedList)):
for i in xrange(1, (int(lastDateMonth) + 1)):
checkDateString = self._currentDateSplit[0] + "-" + self._currentDateSplit[1] + "-" + str(i).rjust(2, "0")
if self._sortedList[l][1] == checkDateString and (str(i) not in appointmentDates):
appointmentDates.append(str(i))
#endif
#endfor
#endfor
#print str(appointmentDates)
finalcalendar = self._tophrOffset + color0 + "${hr}\n"
for m in xrange(len(rawcalendar)):
if m == 0:
finalcalendar = finalcalendar + self._monthYearAlignment + color0 + rawcalendar[m].strip() + "\n"
elif m == 1:
finalcalendar = finalcalendar + self._bodyAlignment + color0 + rawcalendar[m].strip() + "\n"
elif len(rawcalendar[m].strip()) != 0:
#print "len test"
rawcalendar[m] = rawcalendar[m] + " "
rawLength = len(rawcalendar[m])
for k in xrange(len(appointmentDates)):
if appointmentDates[k] == str(self._currentDateSplit[2]):
if usingShading == True:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(appointmentDates[k].rjust(3," ").ljust(3," "), ("${font " + calendarFont + ":style=bold}" + secondaryShadeColor + "${color EE0000}" + appointmentDates[k].rjust(3," ").ljust(3," ") + "${font}" + defaultShadeColor + defaultColor)) # make today bold and red if it has an appointment
else:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(appointmentDates[k].rjust(3," ").ljust(3," "), ("${font " + calendarFont + ":style=bold}${color EE0000}" + appointmentDates[k].rjust(3," ").ljust(3," ") + "${font}" + defaultColor)) # make today bold and red if it has an appointment
#endif
else:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(appointmentDates[k].rjust(3," ").ljust(3," "), (color0 + appointmentDates[k].rjust(3," ").ljust(3," ") + defaultColor)) # make other day a different color if they have appointments
#endif
#endfor
if str(self._currentDateSplit[2]) not in appointmentDates:
if usingShading == True:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(str(currentDate).rjust(3," ").ljust(3," "), ("${font " + calendarFont + ":style=bold}" + secondaryShadeColor + "${color 006400}" + str(currentDate).rjust(3," ").ljust(3," ") + "${font}" + defaultShadeColor + defaultColor)) # make today bold and green if it does not have an appointment
else:
rawcalendar[m] = rawcalendar[m].replace("_\x08","").replace(str(currentDate).rjust(3," ").ljust(3," "), ("${font " + calendarFont + ":style=bold}${color 006400}" + str(currentDate).rjust(3," ").ljust(3," ") + "${font}" + defaultColor)) # make today bold and green if it does not have an appointment
#endif
#endif
if i == 2:
finalcalendar = finalcalendar + self._bodyAlignment + defaultColor + (" " * (21 - rawLength)) + rawcalendar[m] + "\n"
else:
finalcalendar = finalcalendar + self._bodyAlignment + defaultColor + rawcalendar[m] + (" " * (21 - rawLength)) + "\n"
#endif
#endif
#endfor
return str(finalcalendar).strip("\n")
#pass # for now
#enddef
#endclass
def dateInSeconds(startDate, startTime):
timeStruct = time.strptime((startDate + " " + startTime), "%Y-%m-%d %H:%M:%S")
return time.mktime(timeStruct)
#enddef
def parseTest():
rawCalendar = open(icalendarPath, "rb") # open calendar for reading
evoCalendar = rawCalendar.read()
rawCalendar.close()
####
#print "importing"
parsCalendar = Calendar.from_ical(evoCalendar)
#print "walking"
eventHolder = eventList()
for component in parsCalendar.walk('VEVENT'):
#print component
#print component.canonical_order
#print component.name
eventSummary = component['SUMMARY']
#print str(compSummary)
compDTStart = component['DTSTART'].to_ical()
#print compDTStart
if compDTStart.find("T") != (-1):
[eventStartDate, eventStartTime] = str(vDatetime.from_ical(compDTStart)).split(" ")
else:
#print "no start time"
#print str(compDTStart)
eventStartDate = compDTStart[0:4] + "-" + compDTStart[4:6] + "-" + compDTStart[6:8]
eventStartTime = "00:00:00"
#endif
eventStartSeconds = dateInSeconds(eventStartDate, eventStartTime)
#print str(eventStartSeconds)
compDTEnd = component['DTEND'].to_ical()
if compDTEnd.find("T") != (-1):
[eventEndDate, eventEndTime] = str(vDatetime.from_ical(compDTEnd)).split(" ")
else:
#print "no end time"
#print str(compDTEnd)
eventEndDate = compDTEnd[0:4] + "-" + compDTEnd[4:6] + "-" + compDTEnd[6:8]
eventEndTime = "24:00:00"
#endif
try:
compRRule = component['RRULE']
eventRecurFreq = compRRule['FREQ']
if eventRecurFreq[0] == 'WEEKLY':
eventRecurDays = compRRule['BYDAY']
eventRecurEndDate = compRRule['UNTIL'][0]
elif eventRecurFreq[0] == 'DAILY':
eventRecurCount = compRRule['COUNT']
#print str(eventRecurCount)
#endif
#print str(eventRecurFreq)
except Exception, e:
#print "RRule Error = " + str(e)
compRRule = "N/A"
#endtry
if compRRule == "N/A": # Single appointments
eventHolder.appendSingleEvent([eventStartSeconds, eventStartDate, eventStartTime, eventEndDate, eventEndTime, eventSummary, compRRule])
elif eventRecurFreq[0] == "WEEKLY": # Weekly reccuring appointments ## RRULE:FREQ=WEEKLY;UNTIL=20111209T040000;BYDAY=MO,WE,FR
#print str(eventRecurFreq[0])
pass # for now
elif eventRecurFreq[0] == 'DAILY': # Daily reccruing appointments ## RRULE;X-EVOLUTION-ENDDATE=20120511T190000Z:FREQ=DAILY;COUNT=2;WKST=SA
pass # for now
else:
#print "Error Unknown Reccuring Appointment Type: " + str(eventRecurFreq)
pass
#endif
#endfor
"""
unsortedList = eventHolder.returnList()
for i in xrange(len(unsortedList)):
# print str(unsortedList[i])
#endfor
"""
eventHolder.sortList()
sortedList = eventHolder.returnSortedList()
#print ""
#for i in xrange(len(sortedList)):
# print str(sortedList[i])
#endfor
print eventHolder.conkyApts()
print eventHolder.conkyCalendar()
#enddef
#########
#timeStart = time.time()
parseTest()
#print "time end = " + str(time.time() - timeStart) + "s"Last edited by arclance (2012-05-11 15:41:36)
Offline
Update v2.5
Added support for DAILY, WEEKLY, and YEARLY recurring appointment types.
MONTHLY recurring appointments are not supported yet.
Offline
I tried to run it in terminal and it is ok :
kerel@kerel:~$ python evolutionconky.py
${voffset -8}${color0}${hr}
${voffset -5}${color}Today (Friday) ${color0}- ${color}2012-05-11
${voffset -2}${color0}12:30 PM ${color}-> ${color0}01:00 PM |${color}-01:04 ${color0}| ${color}něco
${voffset -6}${color0}${hr}
${alignc}${voffset -6}${color0}Květen 2012
${alignc}${voffset -2}${color0}Po Út St Čt Pá So Ne
${alignc}${voffset -2}${color} 1 2 3 4 5 6
${alignc}${voffset -2}${color} 7 8 9 10${font DejaVu Sans Mono:size=10:style=bold}${color EE0000} 11${font}${color} 12 13
${alignc}${voffset -2}${color}14 15 16 17 18 19 20
${alignc}${voffset -2}${color}21 22 23 24 25 26 27
${alignc}${voffset -2}${color}28 29 30 31 But it is not appearing on my desktop when I launch conky...
Here is my conky file:
background no
use_xft yes
xftfont Bitstream Vera Sans Mono:size=9
xftalpha 0.8
update_interval 1.0
total_run_times 0
own_window no
double_buffer yes
minimum_size 400 0
maximum_width 800
draw_shades yes
draw_outline no
draw_borders no
draw_graph_borders yes
stippled_borders 8
border_margin 4
border_width 1
default_color white
default_shade_color black
default_outline_color white
own_window yes
own_window_transparent yes
own_window_type override
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager
alignment top_right
gap_x 10
gap_y 35
no_buffers yes
uppercase no
cpu_avg_samples 2
net_avg_samples 2
override_utf8_locale yes
use_spacer right
color1 white
color2 A7D33A
text_buffer_size 2048
TEXT
${offset 175}${voffset 10}${color2}${font Ubuntu-B:size=35}${time %a %d %b}${font}
${offset 175}${color2}${font openlogos:size=45}u${font}${color1}${offset 10}${voffset -45}${font Ubuntu-B:size=35}${time %H:%M}${font}
${offset 175}${color2}${font Ubuntu-B:size=35}Rhythmbox${font}
${offset 175}${voffset 20} ${color1}${exec conkyRhythmbox --datatype=TI}
${offset 175} ${color1}${exec conkyRhythmbox --datatype=AR}
${offset 175} ${color1}${exec conkyRhythmbox --datatype=PT}/${exec conkyRhythmbox --datatype=LE}
${offset 175}${color2}${font Ubuntu-B:size=35}Co dělat${font}
${offset 185}${voffset 20}${color1}${head /home/kerel/codelat.txt 30 20}
${execp python ~/evolutionconky.py}I tried to copy output from terminal of script.py to conkyrc and it worked... So the problem isn't in ${color0} and ${color}. It is displaying fine... I think it is in that last line when its calling the script ${execp python ~/evolutionconky.py} . But in scripts before it worked fine, i don't see the problem.
Last edited by ZlyChleba (2012-05-11 11:48:38)
Offline
I tried to run it in terminal and it is ok :
kerel@kerel:~$ python evolutionconky.py ${voffset -8}${color0}${hr} ${voffset -5}${color}Today (Friday) ${color0}- ${color}2012-05-11 ${voffset -2}${color0}12:30 PM ${color}-> ${color0}01:00 PM |${color}-01:04 ${color0}| ${color}něco ${voffset -6}${color0}${hr} ${alignc}${voffset -6}${color0}Květen 2012 ${alignc}${voffset -2}${color0}Po Út St Čt Pá So Ne ${alignc}${voffset -2}${color} 1 2 3 4 5 6 ${alignc}${voffset -2}${color} 7 8 9 10${font DejaVu Sans Mono:size=10:style=bold}${color EE0000} 11${font}${color} 12 13 ${alignc}${voffset -2}${color}14 15 16 17 18 19 20 ${alignc}${voffset -2}${color}21 22 23 24 25 26 27 ${alignc}${voffset -2}${color}28 29 30 31But it is not appearing on my desktop when I launch conky...
Here is my conky file:...
I tried to copy output from terminal of script.py to conkyrc and it worked... So the problem isn't in ${color0} and ${color}. It is displaying fine... I think it is in that last line when its calling the script ${execp python ~/evolutionconky.py} . But in scripts before it worked fine, i don't see the problem.
Good it is at least parsing your calendar correctly now.
I am not sure why it is not working in conky but there are a few things you can try.
First make your text_buffer_size larger just to be safe.
Something in the range of 5000 - 10000 should cover just about any script.
You don't have a color0 defined that should not matter, conky will use a default value but execp may not work without one defined.
To be safe add a color0 to your .conkyrc or edit the script to use color1 instead of color0 (color0 = "${color1}").
The last thing is to use the full path to the script instead of ~/evolutionconky.py to remove another variable that could cause the problem.
Looking at the rest of your .conkyrc it would be ${execp python /home/kerel/evolutionconky.py}.
Last a suggestion, you can use ${execpi 30 python /home/kerel/evolutionconky.py} to reduce cpu use since you are not making changes to your calendar every second.
Kill and restart your conky after you make these changes to be sure they are applied correctly.
Offline
Still nothing... Could it be that I have Python2.6 and your script is in Python2.7 ?
Offline
Still nothing... Could it be that I have Python2.6 and your script is in Python2.7 ?
No if it works in a termial that would not be the case.
Maybe conky is not properly resizing the window for the lines produced by ${execp} objects.
Try increaseing the minimum window height (the second number in minimum_size) to something like 1000 to test this.
Offline
Still nothing... And what about if something happened with icalendar installation.. could it have some effect to this ? In terminal it worked properly, so i think that no.
Offline
Still nothing... And what about if something happened with icalendar installation.. could it have some effect to this ? In terminal it worked properly, so i think that no.
No it is definately something to do with conky.
What version of conky are you using?
Post the output of conky -v to check that.
${execp} is broken in v1.8.1 but it should still produce some output.
Last edited by arclance (2012-05-11 15:36:01)
Offline
Conky 1.8.0 compiled Fri Apr 23 10:38:37 UTC 2010 for Linux 2.6.24-27-server (i686)
Compiled in features:
System config file: /etc/conky/conky.conf
Package library path: /usr/lib/conky
X11:
* Xdamage extension
* XDBE (double buffer extension)
* Xft
* ARGB visual
Music detection:
* MPD
* MOC
General:
* math
* hddtemp
* portmon
* Curl
* RSS
* Weather (METAR)
* Weather (XOAP)
* wireless
* support for IBM/Lenovo notebooks
* nvidia
* eve-online
* config-output
* Imlib2
* ALSA mixer support
* apcupsd
* iostats
* ncurses
* Lua
Lua bindings:
* Cairo
* Imlib2Offline
conky v1.8.0 should work fine, I used the old version of the script with it and the output is identical.
What OS and version are you using?
Are there any error messages in the terminal where you started the conky?
Try running the script with ${exec} to see if conky produces any output when it is not trying to parse the scripts output.
You can try changing line 38
calendarFont = "DejaVu Sans Mono:size=10"to
calendarFont = "Bitstream Vera Sans Mono:size=9"in the script so the calendar is using the same font as the rest of your conky when it bolds the current day on the calendar.
That might cause a problem and it will screw up the alignement of the calendar if you don't.
Try adding
max_specials 1000to your .conkyrc above TEXT.
This will increase the limit of the number of conky objects (things like ${color}) that are allowed.
I don't think this is the problem as conky should crash if you use more specials than the max_specials allowed but we have not tried it yet.
Last edited by arclance (2012-05-11 16:59:31)
Offline
I am using Ubuntu 10.04. When I start conky i get:
Conky: /home/kerel/.conkyrc: 16: no such configuration: 'border_margin'
Conky: desktop window (1a000a7) is subwindow of root window (99)
Conky: window type - override
Conky: drawing to created window (0x3c00001)
Conky: drawing to double buffer
Traceback (most recent call last):
File "/home/kerel/evolutionconky.py", line 379, in <module>
parseTest()
File "/home/kerel/evolutionconky.py", line 372, in parseTest
print eventHolder.conkyApts()
UnicodeEncodeError: 'ascii' codec can't encode character u'\u011b' in position 190: ordinal not in range(128)Which is weird, that don't happen before.
Offline
I am using Ubuntu 10.04. When I start conky i get:
Conky: /home/kerel/.conkyrc: 16: no such configuration: 'border_margin' Conky: desktop window (1a000a7) is subwindow of root window (99) Conky: window type - override Conky: drawing to created window (0x3c00001) Conky: drawing to double buffer Traceback (most recent call last): File "/home/kerel/evolutionconky.py", line 379, in <module> parseTest() File "/home/kerel/evolutionconky.py", line 372, in parseTest print eventHolder.conkyApts() UnicodeEncodeError: 'ascii' codec can't encode character u'\u011b' in position 190: ordinal not in range(128)Which is weird, that don't happen before.
Okay now I know what is going on!
Python by default tries to decode strings assuming they are encoded in ascii.
The accented characters you are getting are not in the ascii encoding, it is most likely utf-8.
I have run into this problem with other scripts so I know how to fix it.
Try changing lines 529-530 from
print eventHolder.conkyApts()
print eventHolder.conkyCalendar()to
print eventHolder.conkyApts().encode('utf-8')
print eventHolder.conkyCalendar().encode('utf-8')If that does not work could you PM me your calendar file so I can use it to fix the script to support non-ascii encodings?
Since the script works in a terminal for you this is most likely caused by
override_utf8_locale yesin the your .conkyrc but you most likely don't want to change that setting.
Last edited by arclance (2012-05-11 17:26:41)
Offline
Finally working!!!
thank you for your long support, means lot for me 
Offline
Update v2.5.1 - 2012-05-11
fix for displaying non-ascii characters in conky
The script crashed when trying to ouput non-ascii characters when run from conky but not when run from a terminal.
The script now encodes it's output in utf-8 to fix this.
Finally working!!!
thank you for your long support, means lot for me
Good that is an annoying error to fix sometimes I'm glad that is all it took.
Could you post a screenshot now that it is working?
Offline
Offline
Copyright © 2012 CrunchBang Linux.
Proudly powered by Debian. Hosted by Linode.
Debian is a registered trademark of Software in the Public Interest, Inc.