[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[mhc:01669] Re: MHC on Zaurus
乃村です.
On Fri, 27 Sep 2002 13:45:35 JST,
knok@xxxxxxxxxxxxx (NOKUBI Takatsugu) said:
> 野首です。こちらでは初めまして。
どうも.はじめまして.某所では,お世話になっています.
# 機会があれば,一度お目にかかりたいです.
> 私も昨日ちょっと Zaurus の datebook.xml を生成させてみようといろいろ
> やってました。結局成功していませんが...
一応,途中まで作ったものを下に付けておきます.
繰り返しじゃない普通のスケジュールなら,このまま使えると思います.
ujis で吐くので,
this-script | iconv -f EUC-JP -t UTF-8 > datebook.xml
してあげて下さい.
繰り返しの処理は,mhc-schedule.rb 中の to_palm をから作れば
いけそうな気がします.でも,ここまで来てexception の扱いが
できない事に気付いて萎えたんです..
> >> 情報公開されていないタグ (rinfo とか) があって,
> >> その部分のソースコードもない.
>
> この辺りの情報は DateBookDB というクラスで操作するようなのですが、が
> んばって Ruby binding を作ればなんとかならないかなあ、などと考えていま
> す。
オープンソース版の DateBookDB には,rinfo というフィールドが存在
しないんですよ.なので,この方法でもあんまり嬉しくない気がしています.
どちらかっていうと,DateBookDB を libmhc.a とかにまるごと
すげかえて GUI 部分だけ datebook から貰うというのが
面白いのかもしれません.
> Datebook を捨てて KOrganizer Embedded を使うという方法もあるようです。
KO/E って,繰り返しの予定が入れられなかった記憶があるのですが,
既に昔の話でしょうか.
--
nom
#!/usr/local/bin/ruby
require 'mhc-kconv'
require 'mhc-date'
require 'mhc-schedule'
################################################################
## ZDatebookDB class
class ZDatebookDB
def initialize()
@last_uid = -1 * Time .now .to_i
@last_rid = 0
@records = []
end
def new_record()
rec = ZDatebookRecord .new(self, new_uid(), new_rid())
@records << rec
return rec
end
def new_uid()
return @last_uid -= 1
end
def new_rid()
return @last_rid += 1
end
def each_record()
@records .each{|rec|
yield(rec)
}
end
def dump()
ret = '<?xml version="1.0" encoding="UTF-8"?>'
ret += '<!DOCTYPE DATEBOOK ><DATEBOOK>'
ret += "<RIDMAX>#{@last_rid}</RIDMAX>"
ret += "<events>\n"
@records .each{|rec|
ret += rec .dump + "\n"
}
ret += "</events>\n"
ret += "</DATEBOOK>\n"
end
end
################################################################
## ZDatebookRecord class
class ZDatebookRecord
def initialize(zdb = nil, uid = nil, rid = nil)
set_zdb(zdb)
set_uid(uid)
set_rid(rid)
set_rinfo(1) ## XXX
end
################
## uid is not always unique. In cases where rinfo=0|2 uid seems to
## be 0 or positive (mostly 0). In the case that rinfo=1|3 it is
## always negative and seems to look like a date field.
## Maybe rinfo keeps some sync information...
## XXX: usually, you don't have to set these vars by hand.
def set_uid(uid);
@uid = uid
return self
end
def set_rid(rid)
@rid = rid
return self
end
def set_rinfo(rinfo) ## myterious field... (inside of QtopiaDesktop?)
@rinfo = rinfo
return self
end
def set_zdb(db)
@zdb = db
return self
end
################
## set common fields
def set_description(string)
@description = string
return self
end
def set_location(string)
@location = string
return self
end
def set_note(string)
@note = string
return self
end
def set_categories(cat_list)
@categories = cat_list ## array of category string.
return self
end
def set_time(s, e, allday)
## start and endtime are suposed to be Time.
if @allday = allday
@start = Time .local(s .year, s .mon, s .mday)
@endtime = Time .local(e .year, e .mon, e .mday, 23, 59, 0)
else
@start = s
@endtime = e
end
return self
end
def set_alarm(minute)
@alarm = minute
return self
end
################
## set repeat fields
def set_repeat_daily(enddt, freq)
# rtype = "Daily"
set_repeat(enddt, freq)
@rtype = 'Daily'
return self
end
def set_repeat_weekdays(enddt, freq, rweekdays)
# rtype = "Weekly" rweekdays = "127"
# 127 is bitfield. bit7 (MSB) = Sun, bit1 = Mon
set_repeat(enddt, freq)
@rtype = 'Weekly'
@rweekdays = rweekdays
end
def set_repeat_monthlydate(enddt, freq)
# rtype = "MonthlyDate" rposition = "4"
# 4 is for 4th week.
set_repeat(enddt, freq)
@rtype = 'MonthlyDate'
return self
end
def set_repeat_monthlyday(enddt, freq)
# rtype = "MonthlyDay" rposition = "4" -- 4th Tue every month
set_repeat(enddt, freq)
@rtype = 'MonthlyDay'
return self
end
def set_repeat_yearly(enddt, freq)
# rtype="Yearly"
@rtype = 'Yearly'
set_repeat(enddt, freq)
return self
end
################
## predicates.
def allday?()
return true if @allday
return false
end
def has_alarm?()
return true if @alarm && !allday?
return false
end
def repeat?()
return true if @rtype
return false
end
def repeat_weekly?()
return true if @rtype && @rtype == 'Weekly'
return false
end
def repeat_monthly?()
return true if @rtype && @rtype =~ /^Monthly/
return false
end
################
# print/dump fields
def dump
return '<event ' +
fld_description() +
fld_location() +
fld_categories() +
fld_uid() +
fld_rid() +
fld_rinfo() +
fld_type() +
fld_alarm() +
fld_repeat() +
fld_start() +
fld_end() +
fld_note() +
' />'
end
def fld_description()
return make_field_string('description', @description)
end
def fld_location()
return make_field_string('location', @location)
end
def fld_categories()
return '' ## XXX
end
def fld_uid()
return make_field_string('uid', @uid)
end
def fld_rid()
return make_field_string('rid', @rid)
end
def fld_rinfo()
return make_field_string('rinfo', @rinfo)
end
def fld_type()
return make_field_string('type', 'AllDay') if allday?
return ''
end
def fld_alarm()
return '' if !has_alarm? || allday?
return make_field_string('alarm', @alarm) + # in minute
make_field_string('sound', 'loud')
end
def fld_repeat()
return '' if !repeat?
return make_field_string('rtype', @rtype) +
make_field_string('rweekdays', @rweekdays) +
make_field_string('rposition', @rposition) +
make_field_string('rfreq', @rfreq) +
make_field_string('rhasenddate', @enddt, true) +
make_field_string('enddt', @enddt) +
make_field_string('created', @created)
end
def fld_start()
return make_field_string('start', @start)
return ''
end
def fld_end()
return make_field_string('end', @endtime)
return ''
end
def fld_note()
return make_field_string('note', @note)
return ''
end
################################################################
private
def set_repeat(enddt, freq)
raise ('set time first') if !@start
@enddt = Time .local(enddt .year, enddt .mon, enddt .mday)
@freq = freq
@rposition = (@start .mday - 1) / 7 + 1
return self
end
def make_field_string(name, val, val_is_bool = false)
val = (val ? 1 : 0) if val_is_bool
val = val .to_i if val .is_a?(Time)
val = val .to_s
return '' if val == ''
val = Kconv::toeuc(val)
val = val .gsub('&', '&')
val = val .gsub('<', '<')
val = val .gsub('>', '>')
val = val .gsub('"', '"')
val = val .gsub("'", ''')
return name + '="' + val + '" '
end
end
################################################################
## add methods to MhcScheduleItem.
class MhcScheduleItem
def to_zaurus(zdb)
ret = []
day_cp = day .dup
rec = zdb .new_record
rec .set_description(subject)
rec .set_location(location)
# rec .set_note(description)
rec .set_categories(category)
rec .set_alarm(alarm / 60) if alarm
################
if day && day .length > 0
if time_b && time_e
rec .set_time(day[0] .to_t(time_b), day[0] .to_t(time_e), !time_b)
else
rec .set_time(day[0] .to_t, day[0] .to_t, !time_b)
end
return rec
else
return nil
end
### for repeat
beg, fin = occur_min, occur_max
fin = nil if fin == DURATION_MAX
## First, treat X-SC-Day: field.
while day_cp .length > 0
if day_cp .length > 1 && day_cp .length == day_cp .max - day_cp .min + 1
## repeat in a series of days -- make up as a daily.
ret << mk_palm_skel .set_daily(day_cp .min, day_cp .max, 1)
day_cp = []
else
ret << mk_palm_skel .set_nonrepeat_date(day_cp .shift)
end
end
## Second, treat X-SC-Cond: field.
if cond .length == cond_wek .length && cond_wek .length > 0
## weekly
weeks = []
for w in 0 .. 6
weeks << cond_wek .include?(MhcDate::W_LABEL[w]) ? true : false
end
ret << mk_palm_skel .set_weekly(beg, fin, 1, weeks)
elsif cond_ord .length >= 1 &&
!cond_ord .include?('5th') &&
cond_wek .length >= 1 &&
cond_num .length == 0 &&
cond_mon .length == 0
## monthly by day
cond_ord .each{|ord_str|
cond_wek .each{|wek_str|
ord = MhcDate::O_LABEL .index(ord_str)
wek = MhcDate::W_LABEL .index(wek_str)
sch2 = MhcScheduleItem .new .add_cond(ord_str) .add_cond(wek_str)
beg2 = beg .dup
while !sch2 .occur_on?(beg2) ## XXX: unnecessary?
beg2 .succ!
end
ret << mk_palm_skel .set_monthly_by_day(beg2, fin, 1, ord, wek)
}
}
elsif cond_num .length == 1 &&
cond_num .length == cond .length
## monthly by date
while !occur_on?(beg) ## XXX: maybe necessary?
beg .succ!
end
ret << mk_palm_skel .set_monthly_by_date(beg, fin, 1)
elsif cond_num .length == 1 &&
cond_mon .length == 1 &&
cond_wek .length == 0 &&
cond_ord .length == 0
## yearly by date
y = beg .y
m = MhcDate::M_LABEL .index(cond_mon[0]) + 1
d = cond_num[0] .to_i
date = MhcDate .new(y, m, d)
if date < beg
date .y_succ!
end
## 2/29 はどうする?
ret << mk_palm_skel .set_yearly(date, fin, 1)
elsif cond_ord .length == 1 &&
cond_ord[0] != '5th' &&
cond_wek .length == 1 &&
cond_num .length == 0 &&
cond_mon .length == 1
## yearly by day
ord = MhcDate::O_LABEL .index(cond_ord[0])
wek = MhcDate::W_LABEL .index(cond_wek[0])
m = MhcDate::M_LABEL .index(cond_mon[0]) + 1
date = MhcDate .new(beg .y, m, 1)
if date .m < beg .m
date .y_succ!
end
while !occur_on?(date)
date .succ!
end
ret << mk_palm_skel .set_monthly_by_day(date, fin, 12, ord, wek)
elsif cond .empty?
## do nothing
else
## conversion failed.
ret = []
end
if ret .empty?
# STDERR .print "#{occur_min .to_js} : #{subject} unsupported. ignored..\n"
return nil
else
return ret
end
end
end
################################################################
## main
$DEBUG = false
STDOUT .sync= true
STDERR .sync= true
def usage
print '
usage: mhc2z [-r dir] [YYYYMMDD-yyyymmdd]
mhc2z -- make datebook.xml
-r dir : Set repository directory of the mhc.
~/Mail/schedule
YYYYMMDD-yyyymmdd : set a start and end date of scanning mhc.
if omitted, scan from 3 months ago to
3 months after.
'
exit 1
end
##
## option check.
##
$flag_from, $flag_to = nil, nil
$flag_dir = File .expand_path("~/Mail/schedule")
while ARGV .length > 0
case ARGV[0]
when '-r'
ARGV .shift
$flag_dir = ARGV[0]
when /^(\d{8})-(\d{8})$/
$flag_from, $flag_to = MhcDate .new($1), MhcDate .new($2)
else
usage()
end
ARGV .shift
end
$flag_from = MhcDate .new .m_succ!(-3) if !$flag_from
$flag_to = MhcDate .new .m_succ!(+3) if !$flag_to
##
## Open mhc & convert to z.
##
converted, count = 0, 0
mdb = MhcScheduleDB .new($flag_dir)
zdb = ZDatebookDB .new
mdb .each_sch($flag_from, $flag_to){|sch|
count += 1
if sch .to_zaurus(zdb)
converted += 1
else
STDERR .print "failed to convert."
STDERR .print MhcKconv::todisp(" subject: #{sch .subject}\n")
STDERR .print " first occured: #{sch .occur_min}\n"
STDERR .print " path: #{sch .path}\n"
end
}
print zdb .dump
STDERR .print "#{converted}/#{count} successfully converted.\n"
exit 0