diff --git a/OpenPGP-Keychain/res/values/strings.xml b/OpenPGP-Keychain/res/values/strings.xml index 792f2cc85..b02d72bb8 100644 --- a/OpenPGP-Keychain/res/values/strings.xml +++ b/OpenPGP-Keychain/res/values/strings.xml @@ -364,7 +364,7 @@ You can start by or creating your own key pair - importing public keys. + importing keys. Encrypt to this contact diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java index 40579a3c2..c0b67719e 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java @@ -17,22 +17,32 @@ package org.sufficientlysecure.keychain.ui; +import java.util.Set; + import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.ui.adapter.KeyListSecretAdapter; +import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; +import android.annotation.SuppressLint; import android.content.Intent; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.view.ActionMode; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; +import android.widget.ListView; +import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView.OnItemClickListener; import com.actionbarsherlock.app.SherlockListFragment; @@ -47,6 +57,7 @@ public class KeyListSecretFragment extends SherlockListFragment implements /** * Define Adapter and Loader on create of Activity */ + @SuppressLint("NewApi") @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -59,6 +70,75 @@ public class KeyListSecretFragment extends SherlockListFragment implements // application this would come from a resource. setEmptyText(getString(R.string.list_empty)); + /* + * ActionBarSherlock does not support MultiChoiceModeListener. Thus multi-selection is only + * available for Android >= 3.0 + */ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); + getListView().setMultiChoiceModeListener(new MultiChoiceModeListener() { + + private int count = 0; + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + android.view.MenuInflater inflater = getActivity().getMenuInflater(); + inflater.inflate(R.menu.key_list_secret_multi, menu); + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + Set positions = mAdapter.getCurrentCheckedPosition(); + + // get IDs for checked positions as long array + long[] ids = new long[positions.size()]; + int i = 0; + for (int pos : positions) { + ids[i] = mAdapter.getItemId(pos); + i++; + } + + switch (item.getItemId()) { + case R.id.menu_key_list_public_multi_delete: { + showDeleteKeyDialog(ids); + + break; + } + } + return false; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + count = 0; + mAdapter.clearSelection(); + } + + @Override + public void onItemCheckedStateChanged(ActionMode mode, int position, long id, + boolean checked) { + if (checked) { + count++; + mAdapter.setNewSelection(position, checked); + } else { + count--; + mAdapter.removeSelection(position); + } + + String keysSelected = getResources().getQuantityString( + R.plurals.key_list_selected_keys, count, count); + mode.setTitle(keysSelected); + } + + }); + } + // We have a menu item to show in action bar. setHasOptionsMenu(true); @@ -123,4 +203,16 @@ public class KeyListSecretFragment extends SherlockListFragment implements editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); startActivityForResult(editIntent, 0); } + + /** + * Show dialog to delete key + * + * @param keyRingRowIds + */ + public void showDeleteKeyDialog(long[] keyRingRowIds) { + DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(null, + keyRingRowIds, Id.type.secret_key); + + deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog"); + } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java index 2fda8a9f7..f78eaf627 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java @@ -17,12 +17,17 @@ package org.sufficientlysecure.keychain.ui.adapter; +import java.util.HashMap; +import java.util.Set; + import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; +import android.annotation.SuppressLint; import android.content.Context; import android.database.Cursor; +import android.graphics.Color; import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; import android.view.View; @@ -30,9 +35,11 @@ import android.view.ViewGroup; import android.widget.TextView; public class KeyListSecretAdapter extends CursorAdapter { - private LayoutInflater mInflater; + @SuppressLint("UseSparseArrays") + private HashMap mSelection = new HashMap(); + public KeyListSecretAdapter(Context context, Cursor c, int flags) { super(context, c, flags); @@ -74,4 +81,46 @@ public class KeyListSecretAdapter extends CursorAdapter { return mInflater.inflate(R.layout.key_list_item, null); } + /** -------------------------- MULTI-SELECTION METHODS -------------- */ + public void setNewSelection(int position, boolean value) { + mSelection.put(position, value); + notifyDataSetChanged(); + } + + public boolean isPositionChecked(int position) { + Boolean result = mSelection.get(position); + return result == null ? false : result; + } + + public Set getCurrentCheckedPosition() { + return mSelection.keySet(); + } + + public void removeSelection(int position) { + mSelection.remove(position); + notifyDataSetChanged(); + } + + public void clearSelection() { + mSelection.clear(); + notifyDataSetChanged(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + // let the adapter handle setting up the row views + View v = super.getView(position, convertView, parent); + + /** + * Change color for multi-selection + */ + // default color + v.setBackgroundColor(Color.TRANSPARENT); + if (mSelection.get(position) != null) { + // this is a selected position, change color! + v.setBackgroundColor(parent.getResources().getColor(R.color.emphasis)); + } + return v; + } + }