use of com.android.calendar.CalendarEventModel.Attendee in project Etar-Calendar by Etar-Group.
the class EditEventHelper method saveEvent.
/**
* Saves the event. Returns true if the event was successfully saved, false
* otherwise.
*
* @param model The event model to save
* @param originalModel A model of the original event if it exists
* @param modifyWhich For recurring events which type of series modification to use
* @return true if the event was successfully queued for saving
*/
public boolean saveEvent(CalendarEventModel model, CalendarEventModel originalModel, int modifyWhich) {
boolean forceSaveReminders = false;
if (DEBUG) {
Log.d(TAG, "Saving event model: " + model);
}
if (!mEventOk) {
if (DEBUG) {
Log.w(TAG, "Event no longer exists. Event was not saved.");
}
return false;
}
// modifying an existing event and we have the wrong original model
if (model == null) {
Log.e(TAG, "Attempted to save null model.");
return false;
}
if (!model.isValid()) {
Log.e(TAG, "Attempted to save invalid model.");
return false;
}
if (originalModel != null && !isSameEvent(model, originalModel)) {
Log.e(TAG, "Attempted to update existing event but models didn't refer to the same " + "event.");
return false;
}
if (originalModel != null && model.isUnchanged(originalModel)) {
return false;
}
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
int eventIdIndex = -1;
ContentValues values = getContentValuesFromModel(model);
if (model.mUri != null && originalModel == null) {
Log.e(TAG, "Existing event but no originalModel provided. Aborting save.");
return false;
}
Uri uri = null;
if (model.mUri != null) {
uri = Uri.parse(model.mUri);
}
// Update the "hasAlarm" field for the event
ArrayList<ReminderEntry> reminders = model.mReminders;
int len = reminders.size();
values.put(Events.HAS_ALARM, (len > 0) ? 1 : 0);
if (uri == null) {
// Add hasAttendeeData for a new event
values.put(Events.HAS_ATTENDEE_DATA, 1);
values.put(Events.STATUS, Events.STATUS_CONFIRMED);
eventIdIndex = ops.size();
ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(Events.CONTENT_URI).withValues(values);
ops.add(b.build());
forceSaveReminders = true;
} else if (TextUtils.isEmpty(model.mRrule) && TextUtils.isEmpty(originalModel.mRrule)) {
// Simple update to a non-recurring event
checkTimeDependentFields(originalModel, model, values, modifyWhich);
ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
} else if (TextUtils.isEmpty(originalModel.mRrule)) {
// This event was changed from a non-repeating event to a
// repeating event.
ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
} else if (modifyWhich == MODIFY_SELECTED) {
// Modify contents of the current instance of repeating event
// Create a recurrence exception
long begin = model.mOriginalStart;
values.put(Events.ORIGINAL_SYNC_ID, originalModel.mSyncId);
values.put(Events.ORIGINAL_INSTANCE_TIME, begin);
boolean allDay = originalModel.mAllDay;
values.put(Events.ORIGINAL_ALL_DAY, allDay ? 1 : 0);
values.put(Events.STATUS, originalModel.mEventStatus);
eventIdIndex = ops.size();
ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(Events.CONTENT_URI).withValues(values);
ops.add(b.build());
forceSaveReminders = true;
} else if (modifyWhich == MODIFY_ALL_FOLLOWING) {
if (TextUtils.isEmpty(model.mRrule)) {
// to end at the new start time.
if (isFirstEventInSeries(model, originalModel)) {
ops.add(ContentProviderOperation.newDelete(uri).build());
} else {
// Update the current repeating event to end at the new start time. We
// ignore the RRULE returned because the exception event doesn't want one.
updatePastEvents(ops, originalModel, model.mOriginalStart);
}
eventIdIndex = ops.size();
values.put(Events.STATUS, originalModel.mEventStatus);
ops.add(ContentProviderOperation.newInsert(Events.CONTENT_URI).withValues(values).build());
} else {
if (isFirstEventInSeries(model, originalModel)) {
checkTimeDependentFields(originalModel, model, values, modifyWhich);
ContentProviderOperation.Builder b = ContentProviderOperation.newUpdate(uri).withValues(values);
ops.add(b.build());
} else {
// We need to update the existing recurrence to end before the exception
// event starts. If the recurrence rule has a COUNT, we need to adjust
// that in the original and in the exception. This call rewrites the
// original event's recurrence rule (in "ops"), and returns a new rule
// for the exception. If the exception explicitly set a new rule, however,
// we don't want to overwrite it.
String newRrule = updatePastEvents(ops, originalModel, model.mOriginalStart);
if (model.mRrule.equals(originalModel.mRrule)) {
values.put(Events.RRULE, newRrule);
}
// Create a new event with the user-modified fields
eventIdIndex = ops.size();
values.put(Events.STATUS, originalModel.mEventStatus);
ops.add(ContentProviderOperation.newInsert(Events.CONTENT_URI).withValues(values).build());
}
}
forceSaveReminders = true;
} else if (modifyWhich == MODIFY_ALL) {
// Modify all instances of repeating event
if (TextUtils.isEmpty(model.mRrule)) {
// We've changed a recurring event to a non-recurring event.
// Delete the whole series and replace it with a new
// non-recurring event.
ops.add(ContentProviderOperation.newDelete(uri).build());
eventIdIndex = ops.size();
ops.add(ContentProviderOperation.newInsert(Events.CONTENT_URI).withValues(values).build());
forceSaveReminders = true;
} else {
checkTimeDependentFields(originalModel, model, values, modifyWhich);
ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
}
}
// New Event or New Exception to an existing event
boolean newEvent = (eventIdIndex != -1);
ArrayList<ReminderEntry> originalReminders;
if (originalModel != null) {
originalReminders = originalModel.mReminders;
} else {
originalReminders = new ArrayList<ReminderEntry>();
}
if (newEvent) {
saveRemindersWithBackRef(ops, eventIdIndex, reminders, originalReminders, forceSaveReminders);
} else if (uri != null) {
long eventId = ContentUris.parseId(uri);
saveReminders(ops, eventId, reminders, originalReminders, forceSaveReminders);
}
ContentProviderOperation.Builder b;
boolean hasAttendeeData = model.mHasAttendeeData;
if (hasAttendeeData && model.mOwnerAttendeeId == -1) {
// Organizer is not an attendee
String ownerEmail = model.mOwnerAccount;
if (model.mAttendeesList.size() != 0 && Utils.isValidEmail(ownerEmail)) {
// Add organizer as attendee since we got some attendees
values.clear();
values.put(Attendees.ATTENDEE_EMAIL, ownerEmail);
values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER);
values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_ACCEPTED);
if (newEvent) {
b = ContentProviderOperation.newInsert(Attendees.CONTENT_URI).withValues(values);
b.withValueBackReference(Attendees.EVENT_ID, eventIdIndex);
} else {
values.put(Attendees.EVENT_ID, model.mId);
b = ContentProviderOperation.newInsert(Attendees.CONTENT_URI).withValues(values);
}
ops.add(b.build());
}
} else if (hasAttendeeData && model.mSelfAttendeeStatus != originalModel.mSelfAttendeeStatus && model.mOwnerAttendeeId != -1) {
if (DEBUG) {
Log.d(TAG, "Setting attendee status to " + model.mSelfAttendeeStatus);
}
Uri attUri = ContentUris.withAppendedId(Attendees.CONTENT_URI, model.mOwnerAttendeeId);
values.clear();
values.put(Attendees.ATTENDEE_STATUS, model.mSelfAttendeeStatus);
values.put(Attendees.EVENT_ID, model.mId);
b = ContentProviderOperation.newUpdate(attUri).withValues(values);
ops.add(b.build());
}
// a new event or an existing event. or is this a paranoia check?
if (hasAttendeeData && (newEvent || uri != null)) {
String attendees = model.getAttendeesString();
String originalAttendeesString;
if (originalModel != null) {
originalAttendeesString = originalModel.getAttendeesString();
} else {
originalAttendeesString = "";
}
// has changed it
if (newEvent || !TextUtils.equals(originalAttendeesString, attendees)) {
// figure out which attendees need to be added and which ones
// need to be deleted. use a linked hash set, so we maintain
// order (but also remove duplicates).
HashMap<String, Attendee> newAttendees = model.mAttendeesList;
LinkedList<String> removedAttendees = new LinkedList<String>();
// the eventId is only used if eventIdIndex is -1.
// TODO: clean up this code.
long eventId = uri != null ? ContentUris.parseId(uri) : -1;
// have any existing attendees.
if (!newEvent) {
removedAttendees.clear();
HashMap<String, Attendee> originalAttendees = originalModel.mAttendeesList;
for (String originalEmail : originalAttendees.keySet()) {
if (newAttendees.containsKey(originalEmail)) {
// existing attendee. remove from new attendees set.
newAttendees.remove(originalEmail);
} else {
// no longer in attendees. mark as removed.
removedAttendees.add(originalEmail);
}
}
// delete removed attendees if necessary
if (removedAttendees.size() > 0) {
b = ContentProviderOperation.newDelete(Attendees.CONTENT_URI);
String[] args = new String[removedAttendees.size() + 1];
args[0] = Long.toString(eventId);
int i = 1;
StringBuilder deleteWhere = new StringBuilder(ATTENDEES_DELETE_PREFIX);
for (String removedAttendee : removedAttendees) {
if (i > 1) {
deleteWhere.append(",");
}
deleteWhere.append("?");
args[i++] = removedAttendee;
}
deleteWhere.append(")");
b.withSelection(deleteWhere.toString(), args);
ops.add(b.build());
}
}
if (newAttendees.size() > 0) {
// Insert the new attendees
for (Attendee attendee : newAttendees.values()) {
values.clear();
values.put(Attendees.ATTENDEE_NAME, attendee.mName);
values.put(Attendees.ATTENDEE_EMAIL, attendee.mEmail);
values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);
if (newEvent) {
b = ContentProviderOperation.newInsert(Attendees.CONTENT_URI).withValues(values);
b.withValueBackReference(Attendees.EVENT_ID, eventIdIndex);
} else {
values.put(Attendees.EVENT_ID, eventId);
b = ContentProviderOperation.newInsert(Attendees.CONTENT_URI).withValues(values);
}
ops.add(b.build());
}
}
}
}
mService.startBatch(mService.getNextToken(), null, android.provider.CalendarContract.AUTHORITY, ops, Utils.UNDO_DELAY);
return true;
}
use of com.android.calendar.CalendarEventModel.Attendee in project Etar-Calendar by Etar-Group.
the class AttendeesView method updateAttendeeView.
/**
* Set up each element in {@link AttendeeItem#mView} using the latest information. View
* object is reused.
*/
private View updateAttendeeView(AttendeeItem item) {
final Attendee attendee = item.mAttendee;
final View view = item.mView;
final TextView nameView = (TextView) view.findViewById(R.id.name);
nameView.setText(TextUtils.isEmpty(attendee.mName) ? attendee.mEmail : attendee.mName);
if (item.mRemoved) {
nameView.setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG | nameView.getPaintFlags());
} else {
nameView.setPaintFlags((~Paint.STRIKE_THRU_TEXT_FLAG) & nameView.getPaintFlags());
}
// Set up the Image button even if the view is disabled
// Everything will be ready when the view is enabled later
final ImageButton button = (ImageButton) view.findViewById(R.id.contact_remove);
button.setVisibility(isEnabled() ? View.VISIBLE : View.GONE);
button.setTag(item);
if (item.mRemoved) {
button.setImageResource(R.drawable.ic_menu_add_field_holo_light);
button.setContentDescription(mContext.getString(R.string.accessibility_add_attendee));
} else {
button.setImageResource(R.drawable.ic_menu_remove_field_holo_light);
button.setContentDescription(mContext.getString(R.string.accessibility_remove_attendee));
}
button.setOnClickListener(this);
final QuickContactBadge badgeView = (QuickContactBadge) view.findViewById(R.id.badge);
Drawable badge = null;
// Search for photo in recycled photos
if (mRecycledPhotos != null) {
badge = mRecycledPhotos.get(item.mAttendee.mEmail);
}
if (badge != null) {
item.mBadge = badge;
}
badgeView.setImageDrawable(item.mBadge);
if (item.mAttendee.mStatus == Attendees.ATTENDEE_STATUS_NONE) {
item.mBadge.setAlpha(mNoResponsePhotoAlpha);
} else {
item.mBadge.setAlpha(mDefaultPhotoAlpha);
}
if (item.mAttendee.mStatus == Attendees.ATTENDEE_STATUS_DECLINED) {
item.mBadge.setColorFilter(mGrayscaleFilter);
} else {
item.mBadge.setColorFilter(null);
}
// the lookup uri (yet), we can set Email and QuickContact will lookup once tapped.
if (item.mContactLookupUri != null) {
badgeView.assignContactUri(item.mContactLookupUri);
} else {
badgeView.assignContactFromEmail(item.mAttendee.mEmail, true);
}
badgeView.setMaxHeight(60);
return view;
}
use of com.android.calendar.CalendarEventModel.Attendee in project Etar-Calendar by Etar-Group.
the class EventInfoFragment method shareEvent.
/**
* 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);
// Create and share ics file
boolean isShareSuccessful = false;
try {
// Event title serves as the file name prefix
String filePrefix = event.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
filePrefix = "invite";
}
filePrefix = filePrefix.replaceAll("\\W+", " ");
if (!filePrefix.endsWith(" ")) {
filePrefix += " ";
}
File dir;
if (type == ShareType.SDCARD) {
dir = EXPORT_SDCARD_DIRECTORY;
if (!dir.exists()) {
dir.mkdir();
}
} else {
dir = mActivity.getExternalCacheDir();
}
File inviteFile = IcalendarUtils.createTempFile(filePrefix, ".ics", dir);
if (IcalendarUtils.writeCalendarToFile(calendar, inviteFile)) {
if (type == ShareType.INTENT) {
// Set world-readable
inviteFile.setReadable(true, false);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(inviteFile));
// The ics file is sent as an extra, the receiving application decides whether
// to parse the file to extract calendar events or treat it as a regular file
shareIntent.setType("application/octet-stream");
Intent chooserIntent = Intent.createChooser(shareIntent, getResources().getString(R.string.cal_share_intent_title));
// The MMS app only responds to "text/x-vcalendar" so we create a chooser intent
// that includes the targeted mms intent + any that respond to the above general
// purpose "application/octet-stream" intent.
File vcsInviteFile = File.createTempFile(filePrefix, ".vcs", mActivity.getExternalCacheDir());
// TODO: revisit above
if (IcalendarUtils.copyFile(inviteFile, vcsInviteFile)) {
Intent mmsShareIntent = new Intent();
mmsShareIntent.setAction(Intent.ACTION_SEND);
mmsShareIntent.setPackage("com.android.mms");
mmsShareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(vcsInviteFile));
mmsShareIntent.setType("text/x-vcalendar");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { mmsShareIntent });
}
startActivity(chooserIntent);
} else {
String msg = getString(R.string.cal_export_succ_msg);
Toast.makeText(mActivity, String.format(msg, inviteFile), Toast.LENGTH_SHORT).show();
}
isShareSuccessful = true;
} else {
// Error writing event info to file
isShareSuccessful = false;
}
} catch (IOException e) {
e.printStackTrace();
isShareSuccessful = false;
}
if (!isShareSuccessful) {
Log.e(TAG, "Couldn't generate ics file");
Toast.makeText(mActivity, R.string.error_generating_ics, Toast.LENGTH_SHORT).show();
}
}
use of com.android.calendar.CalendarEventModel.Attendee in project Etar-Calendar by Etar-Group.
the class AttendeesView method addAttendees.
public void addAttendees(String attendees) {
final LinkedHashSet<Rfc822Token> addresses = EditEventHelper.getAddressesFromList(attendees, mValidator);
synchronized (this) {
for (final Rfc822Token address : addresses) {
final Attendee attendee = new Attendee(address.getName(), address.getAddress());
if (TextUtils.isEmpty(attendee.mName)) {
attendee.mName = attendee.mEmail;
}
addOneAttendee(attendee);
}
}
}
use of com.android.calendar.CalendarEventModel.Attendee in project Etar-Calendar by Etar-Group.
the class EventInfoFragment method initAttendeesCursor.
@SuppressWarnings("fallthrough")
private void initAttendeesCursor(View view) {
mOriginalAttendeeResponse = Attendees.ATTENDEE_STATUS_NONE;
mCalendarOwnerAttendeeId = EditEventHelper.ATTENDEE_ID_NONE;
mNumOfAttendees = 0;
if (mAttendeesCursor != null) {
mNumOfAttendees = mAttendeesCursor.getCount();
if (mAttendeesCursor.moveToFirst()) {
mAcceptedAttendees.clear();
mDeclinedAttendees.clear();
mTentativeAttendees.clear();
mNoResponseAttendees.clear();
do {
int status = mAttendeesCursor.getInt(ATTENDEES_INDEX_STATUS);
String name = mAttendeesCursor.getString(ATTENDEES_INDEX_NAME);
String email = mAttendeesCursor.getString(ATTENDEES_INDEX_EMAIL);
if (mAttendeesCursor.getInt(ATTENDEES_INDEX_RELATIONSHIP) == Attendees.RELATIONSHIP_ORGANIZER) {
// Overwrites the one from Event table if available
if (!TextUtils.isEmpty(name)) {
mEventOrganizerDisplayName = name;
if (!mIsOrganizer) {
setVisibilityCommon(view, R.id.organizer_container, View.VISIBLE);
setTextCommon(view, R.id.organizer, mEventOrganizerDisplayName);
}
}
}
if (mCalendarOwnerAttendeeId == EditEventHelper.ATTENDEE_ID_NONE && mCalendarOwnerAccount.equalsIgnoreCase(email)) {
mCalendarOwnerAttendeeId = mAttendeesCursor.getInt(ATTENDEES_INDEX_ID);
mOriginalAttendeeResponse = mAttendeesCursor.getInt(ATTENDEES_INDEX_STATUS);
} else {
String identity = null;
String idNamespace = null;
if (Utils.isJellybeanOrLater()) {
identity = mAttendeesCursor.getString(ATTENDEES_INDEX_IDENTITY);
idNamespace = mAttendeesCursor.getString(ATTENDEES_INDEX_ID_NAMESPACE);
}
// 2) there's a spinner for that for events with guests.
switch(status) {
case Attendees.ATTENDEE_STATUS_ACCEPTED:
mAcceptedAttendees.add(new Attendee(name, email, Attendees.ATTENDEE_STATUS_ACCEPTED, identity, idNamespace));
break;
case Attendees.ATTENDEE_STATUS_DECLINED:
mDeclinedAttendees.add(new Attendee(name, email, Attendees.ATTENDEE_STATUS_DECLINED, identity, idNamespace));
break;
case Attendees.ATTENDEE_STATUS_TENTATIVE:
mTentativeAttendees.add(new Attendee(name, email, Attendees.ATTENDEE_STATUS_TENTATIVE, identity, idNamespace));
break;
default:
mNoResponseAttendees.add(new Attendee(name, email, Attendees.ATTENDEE_STATUS_NONE, identity, idNamespace));
}
}
} while (mAttendeesCursor.moveToNext());
mAttendeesCursor.moveToFirst();
updateAttendees(view);
}
}
}
Aggregations