@Override public View getChildView( int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.custom_contact_list_filter_group, parent, false); } final TextView text1 = (TextView) convertView.findViewById(android.R.id.text1); final TextView text2 = (TextView) convertView.findViewById(android.R.id.text2); final CheckBox checkbox = (CheckBox) convertView.findViewById(android.R.id.checkbox); final AccountDisplay account = mAccounts.get(groupPosition); final GroupDelta child = (GroupDelta) this.getChild(groupPosition, childPosition); if (child != null) { // Handle normal group, with title and checkbox final boolean groupVisible = child.getVisible(); checkbox.setVisibility(View.VISIBLE); checkbox.setChecked(groupVisible); final CharSequence groupTitle = child.getTitle(mContext); text1.setText(groupTitle); text2.setVisibility(View.GONE); } else { // When unknown child, this is "more" footer view checkbox.setVisibility(View.GONE); text1.setText(R.string.display_more_groups); text2.setVisibility(View.GONE); } return convertView; }
@Override public long getChildId(int groupPosition, int childPosition) { final GroupDelta child = (GroupDelta) getChild(groupPosition, childPosition); if (child != null) { final Long childId = child.getId(); return childId != null ? childId : Long.MIN_VALUE; } else { return Long.MIN_VALUE; } }
/** * Build set of {@link ContentProviderOperation} to persist any user changes to {@link * GroupDelta} rows under this {@link AccountWithDataSet}. */ public void buildDiff(ArrayList<ContentProviderOperation> diff) { for (GroupDelta group : mSyncedGroups) { final ContentProviderOperation oper = group.buildDiff(); if (oper != null) diff.add(oper); } for (GroupDelta group : mUnsyncedGroups) { final ContentProviderOperation oper = group.buildDiff(); if (oper != null) diff.add(oper); } }
@Override public AccountSet loadInBackground() { Context context = getContext(); final AccountTypeManager accountTypes = AccountTypeManager.getInstance(context); final ContentResolver resolver = context.getContentResolver(); final AccountSet accounts = new AccountSet(); for (AccountWithDataSet account : accountTypes.getAccounts(false)) { final AccountType accountType = accountTypes.getAccountTypeForAccount(account); if (accountType.isExtension() && !account.hasData(context)) { // Extension with no data -- skip. continue; } AccountDisplay accountDisplay = new AccountDisplay(resolver, account.name, account.type, account.dataSet); final Uri.Builder groupsUri = Groups.CONTENT_URI .buildUpon() .appendQueryParameter(Groups.ACCOUNT_NAME, account.name) .appendQueryParameter(Groups.ACCOUNT_TYPE, account.type); if (account.dataSet != null) { groupsUri.appendQueryParameter(Groups.DATA_SET, account.dataSet).build(); } final Cursor cursor = resolver.query(groupsUri.build(), null, null, null, null); if (cursor == null) { continue; } android.content.EntityIterator iterator = ContactsContract.Groups.newEntityIterator(cursor); try { boolean hasGroups = false; // Create entries for each known group while (iterator.hasNext()) { final ContentValues values = iterator.next().getEntityValues(); final GroupDelta group = GroupDelta.fromBefore(values); accountDisplay.addGroup(group); hasGroups = true; } // Create single entry handling ungrouped status accountDisplay.mUngrouped = GroupDelta.fromSettings( resolver, account.name, account.type, account.dataSet, hasGroups); accountDisplay.addGroup(accountDisplay.mUngrouped); } finally { iterator.close(); } accounts.add(accountDisplay); } return accounts; }
protected void handleRemoveSync( final AccountDisplay account, final GroupDelta child, final int syncMode, CharSequence title) { final boolean shouldSyncUngrouped = account.mUngrouped.getShouldSync(); if (syncMode == SYNC_MODE_EVERYTHING && shouldSyncUngrouped && !child.equals(account.mUngrouped)) { // Warn before removing this group when it would cause ungrouped to stop syncing final AlertDialog.Builder builder = new AlertDialog.Builder(this); final CharSequence removeMessage = this.getString(R.string.display_warn_remove_ungrouped, title); builder.setTitle(R.string.menu_sync_remove); builder.setMessage(removeMessage); builder.setNegativeButton(android.R.string.cancel, null); builder.setPositiveButton( android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // Mark both this group and ungrouped to stop syncing account.setShouldSync(account.mUngrouped, false); account.setShouldSync(child, false); mAdapter.notifyDataSetChanged(); } }); builder.show(); } else { // Mark this group to not sync account.setShouldSync(child, false); mAdapter.notifyDataSetChanged(); } }
/** * Handle any clicks on {@link ExpandableListAdapter} children, which usually mean toggling its * visible state. */ @Override public boolean onChildClick( ExpandableListView parent, View view, int groupPosition, int childPosition, long id) { final CheckBox checkbox = (CheckBox) view.findViewById(android.R.id.checkbox); final AccountDisplay account = (AccountDisplay) mAdapter.getGroup(groupPosition); final GroupDelta child = (GroupDelta) mAdapter.getChild(groupPosition, childPosition); if (child != null) { checkbox.toggle(); child.putVisible(checkbox.isChecked()); } else { // Open context menu for bringing back unsynced this.openContextMenu(view); } return true; }
/** * Add the given {@link GroupDelta} internally, filing based on its {@link * GroupDelta#getShouldSync()} status. */ private void addGroup(GroupDelta group) { if (group.getShouldSync()) { mSyncedGroups.add(group); } else { mUnsyncedGroups.add(group); } }
public int compare(GroupDelta object1, GroupDelta object2) { final Long id1 = object1.getId(); final Long id2 = object2.getId(); if (id1 == null && id2 == null) { return 0; } else if (id1 == null) { return -1; } else if (id2 == null) { return 1; } else if (id1 < id2) { return -1; } else if (id1 > id2) { return 1; } else { return 0; } }
protected void showRemoveSync( ContextMenu menu, final AccountDisplay account, final GroupDelta child, final int syncMode) { final CharSequence title = child.getTitle(this); menu.setHeaderTitle(title); menu.add(R.string.menu_sync_remove) .setOnMenuItemClickListener( new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { handleRemoveSync(account, child, syncMode, title); return true; } }); }
protected void showAddSync(ContextMenu menu, final AccountDisplay account, final int syncMode) { menu.setHeaderTitle(R.string.dialog_sync_add); // Create item for each available, unsynced group for (final GroupDelta child : account.mUnsyncedGroups) { if (!child.getShouldSync()) { final CharSequence title = child.getTitle(this); menu.add(title) .setOnMenuItemClickListener( new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { // Adding specific group for syncing if (child.mUngrouped && syncMode == SYNC_MODE_EVERYTHING) { account.setShouldSync(true); } else { account.setShouldSync(child, true); } mAdapter.notifyDataSetChanged(); return true; } }); } } }
/** * Set {@link GroupDelta#putShouldSync(boolean)}, and file internally based on updated state. */ public void setShouldSync(GroupDelta child, boolean shouldSync, boolean attemptRemove) { child.putShouldSync(shouldSync); if (shouldSync) { if (attemptRemove) { mUnsyncedGroups.remove(child); } mSyncedGroups.add(child); Collections.sort(mSyncedGroups, sIdComparator); } else { if (attemptRemove) { mSyncedGroups.remove(child); } mUnsyncedGroups.add(child); } }
public static GroupDelta fromAfter(ContentValues after) { final GroupDelta entry = new GroupDelta(); entry.mBefore = null; entry.mAfter = after; return entry; }
public static GroupDelta fromBefore(ContentValues before) { final GroupDelta entry = new GroupDelta(); entry.mBefore = before; entry.mAfter = new ContentValues(); return entry; }