bool GoogleCalHandler::startElement( const QString & namespaceURI, const QString & localName, const QString & qName, const QXmlAttributes & atts ) { Q_UNUSED(namespaceURI); Q_UNUSED(localName); // if we are in a tree we dont' recognize, ignore the lot of it. if (ignoreDepth) { ignoreDepth++; return true; } Element t = token(qName); switch(t) { case Entry: state = EntryState; break; case Feed: state = FeedState; break; case Category: if (atts.value("scheme").endsWith("#kind") && atts.value("term").endsWith("#event")) state = EventState; // TODO other kinds of categories? break; case Status: // this is how deleted events are detected if (atts.value("value").endsWith("#event.canceled")) { removeCurrentAppointment = true; } break; case Reminder: if (!atts.value("minutes").isEmpty()) { lastAppointment.setAlarm(atts.value("minutes").toInt(), QAppointment::Visible); } else if (!atts.value("hours").isEmpty()) { lastAppointment.setAlarm(atts.value("minutes").toInt()*60, QAppointment::Visible); } // TODO doesn't handle days or absolute time. break; case When: { QString st = atts.value("startTime"); QString et = atts.value("endTime"); if (st.isEmpty() || et.isEmpty()) { ignoreDepth++; } else { QTimeZone tz = parseTimeZone(st); QDateTime start = parseDateTime(st, tz); QDateTime end = parseDateTime(et, tz); if (st.length() < 19) lastAppointment.setAllDay(true); lastAppointment.setTimeZone(tz); lastAppointment.setStart(start); lastAppointment.setEnd(end); } } break; case Where: lastAppointment.setLocation(atts.value("valueString")); break; case Title: case Content: if (atts.value("type") != "text") { ignoreDepth++; } break; case Recurrence: case Id: case Published: case Updated: if (state != EntryState && state != EventState) { ignoreDepth++; break; } break; case Unrecognized: ignoreDepth++; } return true; }
bool GoogleCalHandler::endElement( const QString & namespaceURI, const QString & localName, const QString & qName ) { Q_UNUSED(namespaceURI); Q_UNUSED(localName); if (ignoreDepth) { ignoreDepth--; Q_ASSERT(ignoreDepth >= 0); return true; } Element t = token(qName); switch(t) { case Entry: if (removeCurrentAppointment) { mRemoved.append(lastAppointment.uid()); removeCurrentAppointment = false; } else { mAppointments.append(lastAppointment); } lastAppointment = QAppointment(); state = FeedState; break; case Feed: state = StartState; case Title: if (state == FeedState) mName = lastText; else lastAppointment.setDescription(lastText); break; case Content: lastAppointment.setNotes(lastText); break; case Recurrence: { // this is the MAIN TODO, seeing as once this works, /* iCal format, is not compatible with vcard parsing. however it may be similar enough that we can still use existing vcard parser. NOTE: RRULE format is different in iCal to vCard */ /* Example RRULE text from recurrence section. can be given instead of when e.g. DTSTART;TZID=Australia/Brisbane:20060615T113000 DURATION:PT1800S RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TH BEGIN:VTIMEZONE TZID:Australia/Brisbane X-LIC-LOCATION:Australia/Brisbane BEGIN:STANDARD TZOFFSETFROM:+1000 TZOFFSETTO:+1000 TZNAME:EST DTSTART:19700101T000000 END:STANDARD END:VTIMEZONE */ // pad out data to make it look like a vcal and get through our parser // qappointment also has some special ical handling in it. QByteArray data = "BEGIN:VCALENDAR\r\nVERSION:1.0\r\nBEGIN:VEVENT\r\n" + lastText.toUtf8() + "END:VEVENT\r\nEND:VCALENDAR\r\n"; QList<QAppointment> result = QAppointment::readVCalendarData(data.constData(), data.length()); if (result.count() > 0) { QAppointment a = result[0]; lastAppointment.setStart(a.start()); lastAppointment.setEnd(a.end()); lastAppointment.setRepeatRule(a.repeatRule()); lastAppointment.setFrequency(a.frequency()); lastAppointment.setRepeatUntil(a.repeatUntil()); lastAppointment.setWeekFlags(a.weekFlags()); } } break; case Id: { QUniqueId u = parseId(lastText + mIdContext); lastAppointment.setUid(u); // a lot more redundency in a google id. lastAppointment.setCustomField("GoogleId", lastText); } break; case Published: { // TODO should support published/updated fields natively in PimRecords? QDateTime dt = parseDateTime(lastText, QTimeZone::utc()); lastAppointment.setCustomField("GooglePublished", dt.toString(Qt::ISODate)); } break; case Updated: { QDateTime dt = parseDateTime(lastText, QTimeZone::utc()); lastAppointment.setCustomField("GoogleUpdated", dt.toString(Qt::ISODate)); } break; case Category: case Reminder: case When: case Where: case Status: break; case Unrecognized: break; } return true; }