Work on multiselect in key list

This commit is contained in:
Dominik Schürmann 2014-01-06 00:58:04 +01:00
parent 28d9a2f26b
commit 708baaa68c
8 changed files with 208 additions and 312 deletions

View File

@ -194,6 +194,7 @@
<string name="specify_file_to_export_to">Please specify which file to export to.\nWARNING! File will be overwritten if it exists.</string> <string name="specify_file_to_export_to">Please specify which file to export to.\nWARNING! File will be overwritten if it exists.</string>
<string name="specify_file_to_export_secret_keys_to">Please specify which file to export to.\nWARNING! You are about to export SECRET keys.\nWARNING! File will be overwritten if it exists.</string> <string name="specify_file_to_export_secret_keys_to">Please specify which file to export to.\nWARNING! You are about to export SECRET keys.\nWARNING! File will be overwritten if it exists.</string>
<string name="key_deletion_confirmation">Do you really want to delete the key \'%s\'?\nYou can\'t undo this!</string> <string name="key_deletion_confirmation">Do you really want to delete the key \'%s\'?\nYou can\'t undo this!</string>
<string name="key_deletion_confirmation_multi">Do you really want to delete all selected keys?\nYou can\'t undo this!</string>
<string name="secret_key_deletion_confirmation">Do you really want to delete the SECRET key \'%s\'?\nYou can\'t undo this!</string> <string name="secret_key_deletion_confirmation">Do you really want to delete the SECRET key \'%s\'?\nYou can\'t undo this!</string>
<string name="keys_added_and_updated">Successfully added %1$s key(s) and updated %2$s key(s).</string> <string name="keys_added_and_updated">Successfully added %1$s key(s) and updated %2$s key(s).</string>
<string name="keys_added">Successfully added %s key(s).</string> <string name="keys_added">Successfully added %s key(s).</string>
@ -348,4 +349,9 @@
<string name="share_qr_code_dialog_progress">QR Code %1$d of %2$d</string> <string name="share_qr_code_dialog_progress">QR Code %1$d of %2$d</string>
<string name="share_nfc_dialog">Share with NFC</string> <string name="share_nfc_dialog">Share with NFC</string>
<plurals name="key_list_selected_keys">
<item quantity="one">1 key selected.</item>
<item quantity="other">%d keys selected.</item>
</plurals>
</resources> </resources>

View File

@ -225,9 +225,9 @@ public class KeyListActivity extends SherlockFragmentActivity {
/** /**
* Show dialog to delete key * Show dialog to delete key
* *
* @param keyRingId * @param keyRingIds
*/ */
public void showDeleteKeyDialog(long keyRingId) { public void showDeleteKeyDialog(long[] keyRingIds) {
// Message is received after key is deleted // Message is received after key is deleted
Handler returnHandler = new Handler() { Handler returnHandler = new Handler() {
@Override @Override
@ -242,7 +242,7 @@ public class KeyListActivity extends SherlockFragmentActivity {
Messenger messenger = new Messenger(returnHandler); Messenger messenger = new Messenger(returnHandler);
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
keyRingId, mKeyType); keyRingIds, mKeyType);
deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog"); deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog");
} }

View File

@ -17,12 +17,16 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList;
import java.util.Set;
import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.ui.adapter.KeyListPublicAdapter; import org.sufficientlysecure.keychain.ui.adapter.KeyListPublicAdapter;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import se.emilsjolander.stickylistheaders.ApiLevelTooLowException; import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView; import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
@ -30,23 +34,32 @@ import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.provider.BaseColumns;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader; import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.view.ActionMode;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ListView;
import com.actionbarsherlock.app.SherlockFragment;
/** /**
* Public key list with sticky list headers. It does _not_ extend ListFragment because it uses * Public key list with sticky list headers. It does _not_ extend ListFragment because it uses
* StickyListHeaders library which does not extend upon ListView. * StickyListHeaders library which does not extend upon ListView.
*/ */
public class KeyListPublicFragment extends SherlockFragment implements public class KeyListPublicFragment extends Fragment implements AdapterView.OnItemClickListener,
AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor> { LoaderManager.LoaderCallbacks<Cursor> {
private KeyListPublicActivity mKeyListPublicActivity; private KeyListPublicActivity mKeyListPublicActivity;
private KeyListPublicAdapter mAdapter; private KeyListPublicAdapter mAdapter;
@ -84,6 +97,73 @@ public class KeyListPublicFragment extends SherlockFragment implements
// this view is made visible if no data is available // this view is made visible if no data is available
mStickyList.setEmptyView(getActivity().findViewById(R.id.empty)); mStickyList.setEmptyView(getActivity().findViewById(R.id.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) {
mStickyList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mStickyList.getWrappedList().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_multi_selection, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// StringBuilder sb = new StringBuilder();
Set<Integer> positions = mAdapter.getCurrentCheckedPosition();
// for (Integer pos : positions) {
// sb.append(" " + pos + ",");
// }
switch (item.getItemId()) {
case R.id.delete_entry:
long[] ids = new long[positions.size()];
for (int i=0; i < positions.size(); i++) {
ids[i] = mAdapter.getItemId(positions.);
}
showDeleteKeyDialog(ids.to);
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);
}
});
}
// NOTE: Not supported by StickyListHeader, thus no indicator is shown while loading // NOTE: Not supported by StickyListHeader, thus no indicator is shown while loading
// Start out with a progress indicator. // Start out with a progress indicator.
// setListShown(false); // setListShown(false);
@ -152,4 +232,31 @@ public class KeyListPublicFragment extends SherlockFragment implements
startActivity(detailsIntent); startActivity(detailsIntent);
} }
} /**
* Show dialog to delete key
*
* TODO: no messenger needed etc!
*
* @param keyRingRowIds
*/
public void showDeleteKeyDialog(long[] keyRingRowIds) {
// Message is received after key is deleted
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
// no further actions needed
}
}
};
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler);
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
keyRingRowIds, Id.type.public_key);
deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog");
}
}

View File

@ -1,273 +0,0 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sufficientlysecure.keychain.ui.adapter;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MergeCursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorTreeAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class KeyListAdapter extends CursorTreeAdapter {
private Context mContext;
private LayoutInflater mInflater;
protected int mKeyType;
private static final int CHILD_KEY = 0;
private static final int CHILD_USER_ID = 1;
private static final int CHILD_FINGERPRINT = 2;
public KeyListAdapter(Context context, Cursor groupCursor, int keyType) {
super(groupCursor, context);
mContext = context;
mInflater = LayoutInflater.from(context);
mKeyType = keyType;
}
/**
* Inflate new view for group items
*/
@Override
public View newGroupView(Context context, Cursor cursor, boolean isExpanded, ViewGroup parent) {
return mInflater.inflate(R.layout.key_list_item, null);
}
/**
* Binds TextViews from group view to results from database group cursor.
*/
@Override
protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded) {
int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknown_user_id);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
String userId = cursor.getString(userIdIndex);
if (userId != null) {
String[] userIdSplit = OtherHelper.splitUserId(userId);
if (userIdSplit[1] != null) {
mainUserIdRest.setText(userIdSplit[1]);
}
mainUserId.setText(userIdSplit[0]);
}
if (mainUserId.getText().length() == 0) {
mainUserId.setText(R.string.unknown_user_id);
}
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
} else {
mainUserIdRest.setVisibility(View.VISIBLE);
}
}
/**
* Inflate new view for child items
*/
@Override
public View newChildView(Context context, Cursor cursor, boolean isLastChild, ViewGroup parent) {
return mInflater.inflate(R.layout.key_list_child_item, null);
}
/**
* Bind TextViews from view of childs based on query results
*/
@Override
protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
LinearLayout keyLayout = (LinearLayout) view.findViewById(R.id.keyLayout);
LinearLayout userIdLayout = (LinearLayout) view.findViewById(R.id.userIdLayout);
// first entry is fingerprint
if (cursor.getPosition() == 0) {
// show only userId layout
keyLayout.setVisibility(View.GONE);
userIdLayout.setVisibility(View.VISIBLE);
String fingerprint = PgpKeyHelper.getFingerPrint(context,
cursor.getLong(cursor.getColumnIndex(Keys.KEY_ID)));
fingerprint = fingerprint.replace(" ", "\n");
TextView userId = (TextView) view.findViewById(R.id.userId);
if (userId == null) {
Log.d(Constants.TAG, "userId is null!");
}
userId.setText(context.getString(R.string.fingerprint) + "\n" + fingerprint);
} else {
// differentiate between keys and userIds in MergeCursor
if (cursor.getColumnIndex(Keys.KEY_ID) != -1) {
keyLayout.setVisibility(View.VISIBLE);
userIdLayout.setVisibility(View.GONE);
String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(cursor
.getColumnIndex(Keys.KEY_ID)));
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
cursor.getInt(cursor.getColumnIndex(Keys.ALGORITHM)),
cursor.getInt(cursor.getColumnIndex(Keys.KEY_SIZE)));
TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(keyIdStr);
TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
keyDetails.setText("(" + algorithmStr + ")");
ImageView masterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.IS_MASTER_KEY)) != 1) {
masterKeyIcon.setVisibility(View.INVISIBLE);
} else {
masterKeyIcon.setVisibility(View.VISIBLE);
}
ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_CERTIFY)) != 1) {
certifyIcon.setVisibility(View.GONE);
} else {
certifyIcon.setVisibility(View.VISIBLE);
}
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
encryptIcon.setVisibility(View.GONE);
} else {
encryptIcon.setVisibility(View.VISIBLE);
}
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
signIcon.setVisibility(View.GONE);
} else {
signIcon.setVisibility(View.VISIBLE);
}
} else {
keyLayout.setVisibility(View.GONE);
userIdLayout.setVisibility(View.VISIBLE);
String userIdStr = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(userIdStr);
}
}
}
/**
* Given the group cursor, we start cursors for a fingerprint, keys, and userIds, which are
* merged together and build the child cursor
*/
@Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
final long keyRingRowId = groupCursor.getLong(groupCursor.getColumnIndex(BaseColumns._ID));
Cursor fingerprintCursor = getChildCursor(keyRingRowId, CHILD_FINGERPRINT);
Cursor keyCursor = getChildCursor(keyRingRowId, CHILD_KEY);
Cursor userIdCursor = getChildCursor(keyRingRowId, CHILD_USER_ID);
MergeCursor mergeCursor = new MergeCursor(new Cursor[] { fingerprintCursor, keyCursor,
userIdCursor });
Log.d(Constants.TAG, "mergeCursor:" + DatabaseUtils.dumpCursorToString(mergeCursor));
return mergeCursor;
}
/**
* This builds a cursor for a specific type of children
*
* @param keyRingRowId
* foreign row id of the keyRing
* @param type
* @return
*/
private Cursor getChildCursor(long keyRingRowId, int type) {
Uri uri = null;
String[] projection = null;
String sortOrder = null;
String selection = null;
switch (type) {
case CHILD_FINGERPRINT:
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
sortOrder = Keys.RANK + " ASC";
// use only master key for fingerprint
selection = Keys.IS_MASTER_KEY + " = 1 ";
if (mKeyType == Id.type.public_key) {
uri = Keys.buildPublicKeysUri(String.valueOf(keyRingRowId));
} else {
uri = Keys.buildSecretKeysUri(String.valueOf(keyRingRowId));
}
break;
case CHILD_KEY:
projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
sortOrder = Keys.RANK + " ASC";
if (mKeyType == Id.type.public_key) {
uri = Keys.buildPublicKeysUri(String.valueOf(keyRingRowId));
} else {
uri = Keys.buildSecretKeysUri(String.valueOf(keyRingRowId));
}
break;
case CHILD_USER_ID:
projection = new String[] { UserIds._ID, UserIds.USER_ID, UserIds.RANK, };
sortOrder = UserIds.RANK + " ASC";
// not the main user id
selection = UserIds.RANK + " > 0 ";
if (mKeyType == Id.type.public_key) {
uri = UserIds.buildPublicUserIdsUri(String.valueOf(keyRingRowId));
} else {
uri = UserIds.buildSecretUserIdsUri(String.valueOf(keyRingRowId));
}
break;
default:
return null;
}
return mContext.getContentResolver().query(uri, projection, selection, null, sortOrder);
}
}

View File

@ -17,15 +17,18 @@
package org.sufficientlysecure.keychain.ui.adapter; package org.sufficientlysecure.keychain.ui.adapter;
import java.util.HashMap;
import java.util.Set;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Color;
import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -39,6 +42,9 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
private LayoutInflater mInflater; private LayoutInflater mInflater;
private int mSectionColumnIndex; private int mSectionColumnIndex;
@SuppressLint("UseSparseArrays")
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
public KeyListPublicAdapter(Context context, Cursor c, int flags, int sectionColumnIndex) { public KeyListPublicAdapter(Context context, Cursor c, int flags, int sectionColumnIndex) {
super(context, c, flags); super(context, c, flags);
@ -138,7 +144,8 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
} }
// return the first character of the name as ID because this is what // return the first character of the name as ID because this is what
// headers are based upon // headers private HashMap<Integer, Boolean> mSelection = new HashMap<Integer,
// Boolean>();are based upon
return mCursor.getString(mSectionColumnIndex).subSequence(0, 1).charAt(0); return mCursor.getString(mSectionColumnIndex).subSequence(0, 1).charAt(0);
} }
@ -146,4 +153,46 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
TextView text; TextView text;
} }
/** -------------------------- 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<Integer> 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;
}
} }

View File

@ -19,19 +19,14 @@ package org.sufficientlysecure.keychain.ui.adapter;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor; import android.database.Cursor;
import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
public class KeyListSecretAdapter extends CursorAdapter { public class KeyListSecretAdapter extends CursorAdapter {

View File

@ -38,7 +38,7 @@ import android.support.v4.app.FragmentActivity;
public class DeleteKeyDialogFragment extends DialogFragment { public class DeleteKeyDialogFragment extends DialogFragment {
private static final String ARG_MESSENGER = "messenger"; private static final String ARG_MESSENGER = "messenger";
private static final String ARG_DELETE_KEY_RING_ROW_ID = "delete_file"; private static final String ARG_DELETE_KEY_RING_ROW_IDS = "delete_file";
private static final String ARG_KEY_TYPE = "key_type"; private static final String ARG_KEY_TYPE = "key_type";
public static final int MESSAGE_OKAY = 1; public static final int MESSAGE_OKAY = 1;
@ -48,13 +48,13 @@ public class DeleteKeyDialogFragment extends DialogFragment {
/** /**
* Creates new instance of this delete file dialog fragment * Creates new instance of this delete file dialog fragment
*/ */
public static DeleteKeyDialogFragment newInstance(Messenger messenger, long deleteKeyRingRowId, public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] keyRingRowIds,
int keyType) { int keyType) {
DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putParcelable(ARG_MESSENGER, messenger); args.putParcelable(ARG_MESSENGER, messenger);
args.putLong(ARG_DELETE_KEY_RING_ROW_ID, deleteKeyRingRowId); args.putLongArray(ARG_DELETE_KEY_RING_ROW_IDS, keyRingRowIds);
args.putInt(ARG_KEY_TYPE, keyType); args.putInt(ARG_KEY_TYPE, keyType);
frag.setArguments(args); frag.setArguments(args);
@ -70,36 +70,48 @@ public class DeleteKeyDialogFragment extends DialogFragment {
final FragmentActivity activity = getActivity(); final FragmentActivity activity = getActivity();
mMessenger = getArguments().getParcelable(ARG_MESSENGER); mMessenger = getArguments().getParcelable(ARG_MESSENGER);
final long deleteKeyRingRowId = getArguments().getLong(ARG_DELETE_KEY_RING_ROW_ID); final long[] keyRingRowIds = getArguments().getLongArray(ARG_DELETE_KEY_RING_ROW_IDS);
final int keyType = getArguments().getInt(ARG_KEY_TYPE); final int keyType = getArguments().getInt(ARG_KEY_TYPE);
// TODO: better way to do this?
String userId = activity.getString(R.string.unknown_user_id);
if (keyType == Id.type.public_key) {
PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByRowId(activity,
deleteKeyRingRowId);
userId = PgpKeyHelper.getMainUserIdSafe(activity, PgpKeyHelper.getMasterKey(keyRing));
} else {
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByRowId(activity,
deleteKeyRingRowId);
userId = PgpKeyHelper.getMainUserIdSafe(activity, PgpKeyHelper.getMasterKey(keyRing));
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity); AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.warning); builder.setTitle(R.string.warning);
builder.setMessage(getString(
keyType == Id.type.public_key ? R.string.key_deletion_confirmation if (keyRingRowIds.length == 1) {
: R.string.secret_key_deletion_confirmation, userId)); // TODO: better way to do this?
String userId = activity.getString(R.string.unknown_user_id);
if (keyType == Id.type.public_key) {
PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByRowId(activity,
keyRingRowIds[0]);
userId = PgpKeyHelper.getMainUserIdSafe(activity,
PgpKeyHelper.getMasterKey(keyRing));
} else {
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByRowId(activity,
keyRingRowIds[0]);
userId = PgpKeyHelper.getMainUserIdSafe(activity,
PgpKeyHelper.getMasterKey(keyRing));
}
builder.setMessage(getString(
keyType == Id.type.public_key ? R.string.key_deletion_confirmation
: R.string.secret_key_deletion_confirmation, userId));
} else {
builder.setMessage(R.string.key_deletion_confirmation_multi);
}
builder.setIcon(android.R.drawable.ic_dialog_alert); builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
if (keyType == Id.type.public_key) { if (keyType == Id.type.public_key) {
ProviderHelper.deletePublicKeyRing(activity, deleteKeyRingRowId); for (long keyRowId : keyRingRowIds) {
ProviderHelper.deletePublicKeyRing(activity, keyRowId);
}
} else { } else {
ProviderHelper.deleteSecretKeyRing(activity, deleteKeyRingRowId); for (long keyRowId : keyRingRowIds) {
ProviderHelper.deleteSecretKeyRing(activity, keyRowId);
}
} }
dismiss(); dismiss();

View File

@ -17,8 +17,8 @@ I am happy about every code contribution and appreciate your effort to help us d
## Build with Gradle ## Build with Gradle
1. Have Android SDK "tools", "platform-tools", and "build-tools" directories in your PATH (http://developer.android.com/sdk/index.html) 1. Have Android SDK "tools", "platform-tools", and "build-tools" directories in your PATH (http://developer.android.com/sdk/index.html)
2. Export ANDROID_HOME pointing to your Android SDK 2. Open the Android SDK Manager (shell command: ``android``). Expand the Extras directory and install "Android Support Repository"
3. Download Android Support Repository, and Google Repository using Android SDK Manager 3. Export ANDROID_HOME pointing to your Android SDK
4. Execute ``./gradlew build`` 4. Execute ``./gradlew build``
## Development with Eclipse ## Development with Eclipse