diff options
Diffstat (limited to 'src/com/android/calendar/EventInfoFragment.java')
-rw-r--r-- | src/com/android/calendar/EventInfoFragment.java | 251 |
1 files changed, 155 insertions, 96 deletions
diff --git a/src/com/android/calendar/EventInfoFragment.java b/src/com/android/calendar/EventInfoFragment.java index 4374226e..dd4d17a6 100644 --- a/src/com/android/calendar/EventInfoFragment.java +++ b/src/com/android/calendar/EventInfoFragment.java @@ -427,6 +427,10 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange private QueryHandler mHandler; + // used to signal the completion of querying calendar event data + // note: runnable is executed on the ui thread + private Runnable mQueryCompleteRunnable; + private final Runnable mTZUpdater = new Runnable() { @Override public void run() { @@ -463,6 +467,8 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange private CalendarController mController; + private boolean mInNonUiMode; + private class QueryHandler extends AsyncQueryService { public QueryHandler(Context context) { super(context); @@ -471,7 +477,7 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { // if the activity is finishing, then close the cursor and return - final Activity activity = getActivity(); + final Activity activity = (mActivity != null) ? mActivity : getActivity(); if (activity == null || activity.isFinishing()) { if (cursor != null) { cursor.close(); @@ -517,9 +523,10 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange case TOKEN_QUERY_CALENDARS: mCalendarsCursor = Utils.matrixCursorFromCursor(cursor); updateCalendar(mView); - // FRAG_TODO fragments shouldn't set the title anymore - updateTitle(); - + if (!mInNonUiMode) { + // FRAG_TODO fragments shouldn't set the title anymore + updateTitle(); + } args = new String[] { mCalendarsCursor.getString(CALENDARS_INDEX_ACCOUNT_NAME), mCalendarsCursor.getString(CALENDARS_INDEX_ACCOUNT_TYPE) }; @@ -535,7 +542,7 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange startQuery(TOKEN_QUERY_ATTENDEES, null, uri, ATTENDEES_PROJECTION, ATTENDEES_WHERE, args, ATTENDEES_SORT_ORDER); } else { - sendAccessibilityEventIfQueryDone(TOKEN_QUERY_ATTENDEES); + assessQueryCompletion(TOKEN_QUERY_ATTENDEES); } if (mHasAlarm) { // start reminders query @@ -544,10 +551,11 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange startQuery(TOKEN_QUERY_REMINDERS, null, uri, REMINDERS_PROJECTION, REMINDERS_WHERE, args, null); } else { - sendAccessibilityEventIfQueryDone(TOKEN_QUERY_REMINDERS); + assessQueryCompletion(TOKEN_QUERY_REMINDERS); } break; case TOKEN_QUERY_COLORS: + if (mInNonUiMode) break; ArrayList<Integer> colors = new ArrayList<Integer>(); if (cursor.moveToFirst()) { do @@ -584,11 +592,11 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange case TOKEN_QUERY_ATTENDEES: mAttendeesCursor = Utils.matrixCursorFromCursor(cursor); initAttendeesCursor(mView); - updateResponse(mView); + if (!mInNonUiMode) updateResponse(mView); break; case TOKEN_QUERY_REMINDERS: mRemindersCursor = Utils.matrixCursorFromCursor(cursor); - initReminders(mView, mRemindersCursor); + if (!mInNonUiMode) initReminders(mView, mRemindersCursor); break; case TOKEN_QUERY_VISIBLE_CALENDARS: if (cursor.getCount() > 1) { @@ -601,34 +609,38 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange } else { // Don't need to display the calendar owner when there is only a single // calendar. Skip the duplicate calendars query. - setVisibilityCommon(mView, R.id.calendar_container, View.GONE); + if (!mInNonUiMode) { + setVisibilityCommon(mView, R.id.calendar_container, View.GONE); + } mCurrentQuery |= TOKEN_QUERY_DUPLICATE_CALENDARS; } break; case TOKEN_QUERY_DUPLICATE_CALENDARS: - SpannableStringBuilder sb = new SpannableStringBuilder(); - - // Calendar display name - String calendarName = mCalendarsCursor.getString(CALENDARS_INDEX_DISPLAY_NAME); - sb.append(calendarName); - - // Show email account if display name is not unique and - // display name != email - String email = mCalendarsCursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT); - if (cursor.getCount() > 1 && !calendarName.equalsIgnoreCase(email) && - Utils.isValidEmail(email)) { - sb.append(" (").append(email).append(")"); - } + if (!mInNonUiMode) { + SpannableStringBuilder sb = new SpannableStringBuilder(); + + // Calendar display name + String calendarName = mCalendarsCursor.getString(CALENDARS_INDEX_DISPLAY_NAME); + sb.append(calendarName); + + // Show email account if display name is not unique and + // display name != email + String email = mCalendarsCursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT); + if (cursor.getCount() > 1 && !calendarName.equalsIgnoreCase(email) && + Utils.isValidEmail(email)) { + sb.append(" (").append(email).append(")"); + } - setVisibilityCommon(mView, R.id.calendar_container, View.VISIBLE); - setTextCommon(mView, R.id.calendar_name, sb); + setVisibilityCommon(mView, R.id.calendar_container, View.VISIBLE); + setTextCommon(mView, R.id.calendar_name, sb); + } break; } cursor.close(); - sendAccessibilityEventIfQueryDone(token); + assessQueryCompletion(token); // All queries are done, show the view. - if (mCurrentQuery == TOKEN_QUERY_ALL) { + if (mCurrentQuery == TOKEN_QUERY_ALL && !mInNonUiMode) { if (mLoadingMsgView.getAlpha() == 1) { // Loading message is showing, let it stay a bit more (to prevent // flashing) by adding a start delay to the event animation @@ -648,10 +660,18 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange } } - private void sendAccessibilityEventIfQueryDone(int token) { + private void assessQueryCompletion(int token) { mCurrentQuery |= token; if (mCurrentQuery == TOKEN_QUERY_ALL) { - sendAccessibilityEvent(); + + // signal query completion + if (mQueryCompleteRunnable != null) { + mActivity.runOnUiThread(mQueryCompleteRunnable); + } + if (!mInNonUiMode) { + sendAccessibilityEvent(); + } + } } @@ -699,6 +719,10 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange mEventId = eventId; } + public void launchInNonUiMode() { + mInNonUiMode = true; + } + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -739,6 +763,10 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange } } + public void setQueryCompleteRunnable(Runnable runnable) { + mQueryCompleteRunnable = runnable; + } + private void applyDialogParams() { Dialog dialog = getDialog(); dialog.setCanceledOnTouchOutside(true); @@ -870,6 +898,21 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange } } + /** + * Initiate the querying of the calendar event data. + * For when this component is started in a non-ui mode + */ + public void startQueryingData(Context context) { + mContext = context; + if (context instanceof Activity) { + mActivity = (Activity) context; + } + + mHandler = new QueryHandler(context); + mHandler.startQuery(TOKEN_QUERY_EVENT, null, mUri, EVENT_PROJECTION, + null, null, null); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -1112,7 +1155,7 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange // Overwrites the one from Event table if available if (!TextUtils.isEmpty(name)) { mEventOrganizerDisplayName = name; - if (!mIsOrganizer) { + if (!mIsOrganizer && view != null) { setVisibilityCommon(view, R.id.organizer_container, View.VISIBLE); setTextCommon(view, R.id.organizer, mEventOrganizerDisplayName); } @@ -1160,7 +1203,7 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange } while (mAttendeesCursor.moveToNext()); mAttendeesCursor.moveToFirst(); - updateAttendees(view); + if (view != null) updateAttendees(view); } } } @@ -1278,64 +1321,13 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange * Generates an .ics formatted file with the event info and launches intent chooser to * share said file */ - private void shareEvent(ShareType type) { - // Create the respective ICalendar objects from the event info - VCalendar calendar = new VCalendar(); - calendar.addProperty(VCalendar.VERSION, "2.0"); - calendar.addProperty(VCalendar.PRODID, VCalendar.PRODUCT_IDENTIFIER); - calendar.addProperty(VCalendar.CALSCALE, "GREGORIAN"); - calendar.addProperty(VCalendar.METHOD, "REQUEST"); - - VEvent event = new VEvent(); - mEventCursor.moveToFirst(); - // add event start and end datetime - if (!mAllDay) { - String eventTimeZone = mEventCursor.getString(EVENT_INDEX_EVENT_TIMEZONE); - event.addEventStart(mStartMillis, eventTimeZone); - event.addEventEnd(mEndMillis, eventTimeZone); - } else { - // All-day events' start and end time are stored as UTC. - // Treat the event start and end time as being in the local time zone and convert them - // to the corresponding UTC datetime. If the UTC time is used as is, the ical recipients - // will report the wrong start and end time (+/- 1 day) for the event as they will - // convert the UTC time to their respective local time-zones - String localTimeZone = Utils.getTimeZone(mActivity, mTZUpdater); - long eventStart = IcalendarUtils.convertTimeToUtc(mStartMillis, localTimeZone); - long eventEnd = IcalendarUtils.convertTimeToUtc(mEndMillis, localTimeZone); - event.addEventStart(eventStart, "UTC"); - event.addEventEnd(eventEnd, "UTC"); - } - - event.addProperty(VEvent.LOCATION, mEventCursor.getString(EVENT_INDEX_EVENT_LOCATION)); - event.addProperty(VEvent.DESCRIPTION, mEventCursor.getString(EVENT_INDEX_DESCRIPTION)); - event.addProperty(VEvent.SUMMARY, mEventCursor.getString(EVENT_INDEX_TITLE)); - event.addOrganizer(new Organizer(mEventOrganizerDisplayName, mEventOrganizerEmail)); - - // Add Attendees to event - for (Attendee attendee : mAcceptedAttendees) { - IcalendarUtils.addAttendeeToEvent(attendee, event); - } - - for (Attendee attendee : mDeclinedAttendees) { - IcalendarUtils.addAttendeeToEvent(attendee, event); - } - - for (Attendee attendee : mTentativeAttendees) { - IcalendarUtils.addAttendeeToEvent(attendee, event); - } - - for (Attendee attendee : mNoResponseAttendees) { - IcalendarUtils.addAttendeeToEvent(attendee, event); - } - - // compose all of the ICalendar objects - calendar.addEvent(event); - + public void shareEvent(ShareType type) { + VCalendar calendar = generateVCalendar(); // create and share ics file boolean isShareSuccessful = false; try { // event title serves as the file name prefix - String filePrefix = event.getProperty(VEvent.SUMMARY); + String filePrefix = calendar.getFirstEvent().getProperty(VEvent.SUMMARY); if (filePrefix == null || filePrefix.length() < 3) { // default to a generic filename if event title doesn't qualify // prefix length constraint is imposed by File#createTempFile @@ -1358,8 +1350,7 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange dir = mActivity.getExternalCacheDir(); } - File inviteFile = IcalendarUtils.createTempFile(filePrefix, ".ics", - dir); + File inviteFile = IcalendarUtils.createTempFile(filePrefix, ".ics", dir); if (IcalendarUtils.writeCalendarToFile(calendar, inviteFile)) { if (type == ShareType.INTENT) { @@ -1393,9 +1384,11 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange } startActivity(chooserIntent); } else { - String msg = getString(R.string.cal_export_succ_msg); - Toast.makeText(mActivity, String.format(msg, inviteFile), - Toast.LENGTH_SHORT).show(); + if (! mInNonUiMode) { + String msg = getString(R.string.cal_export_succ_msg); + Toast.makeText(mActivity, String.format(msg, inviteFile), + Toast.LENGTH_SHORT).show(); + } } isShareSuccessful = true; @@ -1414,6 +1407,66 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange } } + /** + * Creates a calendar object (VCalendar) that adheres to the ICalendar specification + */ + public VCalendar generateVCalendar() { + + // Create the respective ICalendar objects from the event info + VCalendar calendar = new VCalendar(); + calendar.addProperty(VCalendar.VERSION, "2.0"); + calendar.addProperty(VCalendar.PRODID, VCalendar.PRODUCT_IDENTIFIER); + calendar.addProperty(VCalendar.CALSCALE, "GREGORIAN"); + calendar.addProperty(VCalendar.METHOD, "REQUEST"); + + VEvent event = new VEvent(); + mEventCursor.moveToFirst(); + // add event start and end datetime + if (!mAllDay) { + String eventTimeZone = mEventCursor.getString(EVENT_INDEX_EVENT_TIMEZONE); + event.addEventStart(mStartMillis, eventTimeZone); + event.addEventEnd(mEndMillis, eventTimeZone); + } else { + // All-day events' start and end time are stored as UTC. + // Treat the event start and end time as being in the local time zone and convert them + // to the corresponding UTC datetime. If the UTC time is used as is, the ical recipients + // will report the wrong start and end time (+/- 1 day) for the event as they will + // convert the UTC time to their respective local time-zones + String localTimeZone = Utils.getTimeZone(mActivity, mTZUpdater); + long eventStart = IcalendarUtils.convertTimeToUtc(mStartMillis, localTimeZone); + long eventEnd = IcalendarUtils.convertTimeToUtc(mEndMillis, localTimeZone); + event.addEventStart(eventStart, "UTC"); + event.addEventEnd(eventEnd, "UTC"); + } + + event.addProperty(VEvent.LOCATION, mEventCursor.getString(EVENT_INDEX_EVENT_LOCATION)); + event.addProperty(VEvent.DESCRIPTION, mEventCursor.getString(EVENT_INDEX_DESCRIPTION)); + event.addProperty(VEvent.SUMMARY, mEventCursor.getString(EVENT_INDEX_TITLE)); + event.addOrganizer(new Organizer(mEventOrganizerDisplayName, mEventOrganizerEmail)); + + // Add Attendees to event + for (Attendee attendee : mAcceptedAttendees) { + IcalendarUtils.addAttendeeToEvent(attendee, event); + } + + for (Attendee attendee : mDeclinedAttendees) { + IcalendarUtils.addAttendeeToEvent(attendee, event); + } + + for (Attendee attendee : mTentativeAttendees) { + IcalendarUtils.addAttendeeToEvent(attendee, event); + } + + for (Attendee attendee : mNoResponseAttendees) { + IcalendarUtils.addAttendeeToEvent(attendee, event); + } + + // compose all of the ICalendar objects + calendar.addEvent(event); + + return calendar; + } + private void showEventColorPickerDialog() { if (mColorPickerDialog == null) { mColorPickerDialog = EventColorPickerDialog.newInstance(mColors, mCurrentColor, @@ -1925,12 +1978,15 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange mEventOrganizerDisplayName = mEventOrganizerEmail; } - if (!mIsOrganizer && !TextUtils.isEmpty(mEventOrganizerDisplayName)) { - setTextCommon(view, R.id.organizer, mEventOrganizerDisplayName); - setVisibilityCommon(view, R.id.organizer_container, View.VISIBLE); - } else { - setVisibilityCommon(view, R.id.organizer_container, View.GONE); + if (!mInNonUiMode) { + if (!mIsOrganizer && !TextUtils.isEmpty(mEventOrganizerDisplayName)) { + setTextCommon(view, R.id.organizer, mEventOrganizerDisplayName); + setVisibilityCommon(view, R.id.organizer_container, View.VISIBLE); + } else { + setVisibilityCommon(view, R.id.organizer_container, View.GONE); + } } + mHasAttendeeData = mEventCursor.getInt(EVENT_INDEX_HAS_ATTENDEE_DATA) != 0; mCanModifyCalendar = mEventCursor.getInt(EVENT_INDEX_ACCESS_LEVEL) >= Calendars.CAL_ACCESS_CONTRIBUTOR; @@ -1939,6 +1995,9 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange mIsBusyFreeCalendar = mEventCursor.getInt(EVENT_INDEX_ACCESS_LEVEL) == Calendars.CAL_ACCESS_FREEBUSY; + // no more work to be done if launched in non-ui mode + if (mInNonUiMode) return; + if (!mIsBusyFreeCalendar) { View b = mView.findViewById(R.id.edit); @@ -1978,8 +2037,8 @@ public class EventInfoFragment extends DialogFragment implements OnCheckedChange mActivity.invalidateOptionsMenu(); } } else { - setVisibilityCommon(view, R.id.calendar, View.GONE); - sendAccessibilityEventIfQueryDone(TOKEN_QUERY_DUPLICATE_CALENDARS); + if (!mInNonUiMode) setVisibilityCommon(view, R.id.calendar, View.GONE); + assessQueryCompletion(TOKEN_QUERY_DUPLICATE_CALENDARS); } } |