From 593d6ad3f790ab4b56a10375e8e21849f749d856 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 10 Apr 2014 18:40:32 +0200 Subject: [PATCH] Select*KeyFragment rewrites - moved all specific Public/Secret logic from the Adapter class into inner subclasses in the Fragments - more versatile status display ("revoked", "expired", "can certify"...) - applied view holder pattern - query logic, including subqueries, moved into provider classes Closes #375 --- .../keychain/provider/KeychainContract.java | 2 + .../keychain/provider/KeychainProvider.java | 34 +++-- .../keychain/ui/KeyListFragment.java | 7 +- .../keychain/ui/SelectPublicKeyFragment.java | 75 +++++++---- .../keychain/ui/SelectSecretKeyFragment.java | 107 ++++++++++------ .../ui/adapter/SelectKeyCursorAdapter.java | 121 +++++++++--------- OpenKeychain/src/main/res/values/strings.xml | 2 + 7 files changed, 211 insertions(+), 137 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index fc25faecd..0999cc754 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -112,6 +112,8 @@ public class KeychainContract { public static final String IS_REVOKED = KeysColumns.IS_REVOKED; public static final String VERIFIED = CertsColumns.VERIFIED; public static final String HAS_SECRET = "has_secret"; + public static final String HAS_ENCRYPT = "has_encrypt"; + public static final String HAS_SIGN = "has_encrypt"; public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() .appendPath(BASE_KEY_RINGS).build(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 78eedf315..012948f63 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -38,9 +38,11 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; +import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter; import org.sufficientlysecure.keychain.util.Log; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; public class KeychainProvider extends ContentProvider { @@ -264,7 +266,29 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.FINGERPRINT, Keys.FINGERPRINT); projectionMap.put(KeyRings.USER_ID, UserIds.USER_ID); projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED); - projectionMap.put(KeyRings.HAS_SECRET, "(" + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NOT NULL) AS " + KeyRings.HAS_SECRET); + projectionMap.put(KeyRings.HAS_SECRET, + "(EXISTS (SELECT * FROM " + Tables.KEY_RINGS_SECRET + + " WHERE " + Tables.KEY_RINGS_SECRET + "." + KeyRingData.MASTER_KEY_ID + + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + ")) AS " + KeyRings.HAS_SECRET); + projectionMap.put(KeyRings.HAS_ENCRYPT, + "(EXISTS (SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" + +" WHERE k." + Keys.MASTER_KEY_ID + + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND k." + Keys.IS_REVOKED + " = 0" + + " AND k." + Keys.CAN_ENCRYPT + " = 1" + + " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY + + " >= '" + new Date().getTime() / 1000 + "' )" + + ")) AS " + KeyRings.HAS_ENCRYPT); + projectionMap.put(KeyRings.HAS_SIGN, + "(EXISTS (SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" + +" WHERE k." + Keys.MASTER_KEY_ID + + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND k." + Keys.IS_REVOKED + " = 0" + + " AND k." + Keys.CAN_SIGN + " = 1" + + " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY + + " >= '" + new Date().getTime() / 1000 + "' )" + + ")) AS " + KeyRings.HAS_SIGN); qb.setProjectionMap(projectionMap); qb.setTables( @@ -274,10 +298,6 @@ public class KeychainProvider extends ContentProvider { + " = " + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID + " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = 0" - + ") LEFT JOIN " + Tables.KEY_RINGS_SECRET + " ON (" - + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " = " - + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + ") LEFT JOIN " + Tables.CERTS + " ON (" + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = " @@ -345,9 +365,7 @@ public class KeychainProvider extends ContentProvider { } if (TextUtils.isEmpty(sortOrder)) { - sortOrder = - Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NULL ASC, " - + Tables.USER_IDS + "." + UserIds.USER_ID + " ASC"; + sortOrder = Tables.USER_IDS + "." + UserIds.USER_ID + " ASC"; } // uri to watch is all /key_rings/ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 63f4ec7c4..0371e664f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -265,6 +265,10 @@ public class KeyListFragment extends Fragment static final int INDEX_VERIFIED = 5; static final int INDEX_HAS_SECRET = 6; + static final String ORDER = // IN THE COURT + KeyRings.HAS_SECRET + " DESC, " + KeyRings.USER_ID + " ASC"; + + @Override public Loader onCreateLoader(int id, Bundle args) { // This is called when a new Loader needs to be created. This @@ -276,9 +280,10 @@ public class KeyListFragment extends Fragment where = KeyRings.USER_ID + " LIKE ?"; whereArgs = new String[]{"%" + mCurQuery + "%"}; } + // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. - return new CursorLoader(getActivity(), baseUri, PROJECTION, where, whereArgs, null); + return new CursorLoader(getActivity(), baseUri, PROJECTION, where, whereArgs, ORDER); } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java index 52b400481..dca960e27 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java @@ -40,17 +40,12 @@ import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; -import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; -import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter; -import java.util.Date; import java.util.Vector; public class SelectPublicKeyFragment extends ListFragmentWorkaround implements TextWatcher, @@ -180,7 +175,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T mSearchView.addTextChangedListener(this); - mAdapter = new SelectKeyCursorAdapter(getActivity(), null, 0, getListView(), Id.type.public_key); + mAdapter = new SelectPublicKeyCursorAdapter(getActivity(), null, 0, getListView()); setListAdapter(mAdapter); @@ -258,25 +253,14 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T Uri baseUri = KeyRings.buildUnifiedKeyRingsUri(); // These are the rows that we will retrieve. - long now = new Date().getTime() / 1000; String[] projection = new String[]{ KeyRings._ID, KeyRings.MASTER_KEY_ID, - UserIds.USER_ID, - "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" - +" WHERE k." + Keys.MASTER_KEY_ID + " = " - + KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND k." + Keys.IS_REVOKED + " = '0'" - + " AND k." + Keys.CAN_ENCRYPT + " = '1'" - + ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE, - "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" - + " WHERE k." + Keys.MASTER_KEY_ID + " = " - + KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND k." + Keys.IS_REVOKED + " = '0'" - + " AND k." + Keys.CAN_ENCRYPT + " = '1'" - + " AND k." + Keys.CREATION + " <= '" + now + "'" - + " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY + " >= '" + now + "' )" - + ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, }; + KeyRings.USER_ID, + KeyRings.EXPIRY, + KeyRings.IS_REVOKED, + KeyRings.HAS_ENCRYPT, + }; String inMasterKeyList = null; if (mSelectedMasterKeyIds != null && mSelectedMasterKeyIds.length > 0) { @@ -290,7 +274,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T inMasterKeyList += ")"; } - String orderBy = UserIds.USER_ID + " ASC"; + String orderBy = KeyRings.USER_ID + " ASC"; if (inMasterKeyList != null) { // sort by selected master keys orderBy = inMasterKeyList + " DESC, " + orderBy; @@ -298,7 +282,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T String where = null; String whereArgs[] = null; if (mCurQuery != null) { - where = UserIds.USER_ID + " LIKE ?"; + where = KeyRings.USER_ID + " LIKE ?"; whereArgs = new String[]{"%" + mCurQuery + "%"}; } @@ -348,4 +332,47 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T mCurQuery = !TextUtils.isEmpty(editable.toString()) ? editable.toString() : null; getLoaderManager().restartLoader(0, null, this); } + + private class SelectPublicKeyCursorAdapter extends SelectKeyCursorAdapter { + + private int mIndexHasEncrypt; + + public SelectPublicKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView) { + super(context, c, flags, listView); + } + + @Override + protected void initIndex(Cursor cursor) { + super.initIndex(cursor); + if (cursor != null) { + mIndexHasEncrypt = cursor.getColumnIndexOrThrow(KeyRings.HAS_ENCRYPT); + } + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + super.bindView(view, context, cursor); + ViewHolderItem h = (SelectKeyCursorAdapter.ViewHolderItem) view.getTag(); + + // We care about the checkbox + h.selected.setVisibility(View.VISIBLE); + // the getListView works because this is not a static subclass! + h.selected.setChecked(getListView().isItemChecked(cursor.getPosition())); + + boolean enabled = false; + if((Boolean) h.status.getTag()) { + // Check if key is viable for our purposes + if (cursor.getInt(mIndexHasEncrypt) == 0) { + h.status.setText(R.string.no_key); + } else { + h.status.setText(R.string.can_encrypt); + enabled = true; + } + } + + h.setEnabled(enabled); + } + + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java index 08ab5af77..47f4f52d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ui; +import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -30,23 +31,15 @@ import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; -import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; -import org.sufficientlysecure.keychain.provider.KeychainDatabase; -import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter; -import java.util.Date; - public class SelectSecretKeyFragment extends ListFragment implements LoaderManager.LoaderCallbacks { private SelectSecretKeyActivity mActivity; private SelectKeyCursorAdapter mAdapter; - private ListView mListView; private boolean mFilterCertify; @@ -80,9 +73,9 @@ public class SelectSecretKeyFragment extends ListFragment implements super.onActivityCreated(savedInstanceState); mActivity = (SelectSecretKeyActivity) getActivity(); - mListView = getListView(); - mListView.setOnItemClickListener(new OnItemClickListener() { + ListView listView = getListView(); + listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int position, long id) { long masterKeyId = mAdapter.getMasterKeyId(position); @@ -97,7 +90,7 @@ public class SelectSecretKeyFragment extends ListFragment implements // application this would come from a resource. setEmptyText(getString(R.string.list_empty)); - mAdapter = new SelectKeyCursorAdapter(mActivity, null, 0, mListView, Id.type.secret_key); + mAdapter = new SelectSecretKeyCursorAdapter(mActivity, null, 0, listView); setListAdapter(mAdapter); @@ -116,41 +109,22 @@ public class SelectSecretKeyFragment extends ListFragment implements Uri baseUri = KeyRings.buildUnifiedKeyRingsUri(); // These are the rows that we will retrieve. - long now = new Date().getTime() / 1000; String[] projection = new String[]{ KeyRings._ID, KeyRings.MASTER_KEY_ID, - UserIds.USER_ID, - "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" - + " WHERE k." + Keys.MASTER_KEY_ID + " = " - + KeychainDatabase.Tables.KEYS + "." + KeyRings.MASTER_KEY_ID - + " AND k." + Keys.CAN_CERTIFY + " = '1'" - + ") AS cert", - "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" - +" WHERE k." + Keys.MASTER_KEY_ID + " = " - + KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND k." + Keys.IS_REVOKED + " = '0'" - + " AND k." + Keys.CAN_SIGN + " = '1'" - + ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE, - "(SELECT COUNT(*) FROM " + Tables.KEYS + " AS k" - + " WHERE k." + Keys.MASTER_KEY_ID + " = " - + KeychainDatabase.Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND k." + Keys.IS_REVOKED + " = '0'" - + " AND k." + Keys.CAN_SIGN + " = '1'" - + " AND k." + Keys.CREATION + " <= '" + now + "'" - + " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY + " >= '" + now + "' )" - + ") AS " + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, }; + KeyRings.USER_ID, + KeyRings.EXPIRY, + KeyRings.IS_REVOKED, + KeyRings.CAN_CERTIFY, + KeyRings.HAS_SIGN, + KeyRings.HAS_SECRET + }; - String orderBy = UserIds.USER_ID + " ASC"; - - String where = Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NOT NULL"; - if (mFilterCertify) { - where += " AND (cert > 0)"; - } + String where = KeyRings.HAS_SECRET + " = 1"; // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. - return new CursorLoader(getActivity(), baseUri, projection, where, null, orderBy); + return new CursorLoader(getActivity(), baseUri, projection, where, null, null); } @Override @@ -174,4 +148,57 @@ public class SelectSecretKeyFragment extends ListFragment implements // longer using it. mAdapter.swapCursor(null); } -} + + private class SelectSecretKeyCursorAdapter extends SelectKeyCursorAdapter { + + private int mIndexHasSign, mIndexCanCertify; + + public SelectSecretKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView) { + super(context, c, flags, listView); + } + + @Override + protected void initIndex(Cursor cursor) { + super.initIndex(cursor); + if (cursor != null) { + mIndexCanCertify = cursor.getColumnIndexOrThrow(KeyRings.CAN_CERTIFY); + mIndexHasSign = cursor.getColumnIndexOrThrow(KeyRings.HAS_SIGN); + } + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + super.bindView(view, context, cursor); + ViewHolderItem h = (SelectKeyCursorAdapter.ViewHolderItem) view.getTag(); + + // We don't care about the checkbox + h.selected.setVisibility(View.GONE); + + // Special from superclass: Te + boolean enabled = false; + if((Boolean) h.status.getTag()) { + // Check if key is viable for our purposes (certify or sign) + if(mFilterCertify) { + if (cursor.getInt(mIndexCanCertify) == 0) { + h.status.setText(R.string.can_certify_not); + } else { + h.status.setText(R.string.can_certify); + enabled = true; + } + } else { + if (cursor.getInt(mIndexHasSign) == 0) { + h.status.setText(R.string.no_key); + } else { + h.status.setText(R.string.can_sign); + enabled = true; + } + } + } + h.setEnabled(enabled); + // refresh this, too, for use in the ItemClickListener above + h.status.setTag(enabled); + } + + } + +} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java index d7f8c8e7a..0c2f7add2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java @@ -26,35 +26,25 @@ import android.widget.CheckBox; import android.widget.ListView; import android.widget.TextView; -import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; + +import java.util.Date; -public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter { - - protected int mKeyType; +/** + * Yes this class is abstract! + */ +abstract public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter { private LayoutInflater mInflater; - private ListView mListView; - private int mIndexUserId; - private int mIndexMasterKeyId; - private int mIndexProjectionValid; - private int mIndexProjectionAvailable; + protected int mIndexUserId, mIndexMasterKeyId, mIndexRevoked, mIndexExpiry; - public static final String PROJECTION_ROW_AVAILABLE = "available"; - public static final String PROJECTION_ROW_VALID = "valid"; - - public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView, - int keyType) { + public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView) { super(context, c, flags); - mInflater = LayoutInflater.from(context); - mListView = listView; - mKeyType = keyType; initIndex(c); } @@ -71,12 +61,12 @@ public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter { * * @param cursor */ - private void initIndex(Cursor cursor) { + protected void initIndex(Cursor cursor) { if (cursor != null) { - mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID); + mIndexUserId = cursor.getColumnIndexOrThrow(KeyRings.USER_ID); mIndexMasterKeyId = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID); - mIndexProjectionValid = cursor.getColumnIndexOrThrow(PROJECTION_ROW_VALID); - mIndexProjectionAvailable = cursor.getColumnIndexOrThrow(PROJECTION_ROW_AVAILABLE); + mIndexExpiry= cursor.getColumnIndexOrThrow(KeyRings.EXPIRY); + mIndexRevoked= cursor.getColumnIndexOrThrow(KeyRings.IS_REVOKED); } } @@ -90,70 +80,73 @@ public class SelectKeyCursorAdapter extends HighlightQueryCursorAdapter { return mCursor.getLong(mIndexMasterKeyId); } + public static class ViewHolderItem { + public View view; + public TextView mainUserId, mainUserIdRest, keyId, status; + public CheckBox selected; + + public void setEnabled(boolean enabled) { + view.setEnabled(enabled); + selected.setEnabled(enabled); + mainUserId.setEnabled(enabled); + mainUserIdRest.setEnabled(enabled); + keyId.setEnabled(enabled); + status.setEnabled(enabled); + + // Sorta special: We set an item as clickable to disable it in the ListView. This works + // because the list item will handle the clicks itself (which is a nop) + view.setClickable(!enabled); + } + } + @Override public void bindView(View view, Context context, Cursor cursor) { - TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); - TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - TextView keyId = (TextView) view.findViewById(R.id.keyId); - TextView status = (TextView) view.findViewById(R.id.status); + ViewHolderItem h = (ViewHolderItem) view.getTag(); String userId = cursor.getString(mIndexUserId); String[] userIdSplit = PgpKeyHelper.splitUserId(userId); if (userIdSplit[0] != null) { - mainUserId.setText(highlightSearchQuery(userIdSplit[0])); + h.mainUserId.setText(highlightSearchQuery(userIdSplit[0])); } else { - mainUserId.setText(R.string.user_id_no_name); + h.mainUserId.setText(R.string.user_id_no_name); } if (userIdSplit[1] != null) { - mainUserIdRest.setText(highlightSearchQuery(userIdSplit[1])); + h.mainUserIdRest.setText(highlightSearchQuery(userIdSplit[1])); } else { - mainUserIdRest.setText(""); + h.mainUserIdRest.setText(""); } long masterKeyId = cursor.getLong(mIndexMasterKeyId); - keyId.setText(PgpKeyHelper.convertKeyIdToHexShort(masterKeyId)); + h.keyId.setText(PgpKeyHelper.convertKeyIdToHexShort(masterKeyId)); - boolean valid = cursor.getInt(mIndexProjectionValid) > 0; - if (valid) { - if (mKeyType == Id.type.public_key) { - status.setText(R.string.can_encrypt); - } else { - status.setText(R.string.can_sign); - } + boolean enabled = true; + if(cursor.getInt(mIndexRevoked) != 0) { + h.status.setText(R.string.revoked); + enabled = false; + } else if (!cursor.isNull(mIndexExpiry) + && new Date(cursor.getLong(mIndexExpiry) * 1000).before(new Date())) { + h.status.setText(R.string.expired); + enabled = false; } else { - if (cursor.getInt(mIndexProjectionAvailable) > 0) { - // has some CAN_ENCRYPT keys, but col(ROW_VALID) = 0, so must be revoked or - // expired - status.setText(R.string.expired); - } else { - status.setText(R.string.no_key); - } + h.status.setText(""); } - CheckBox selected = (CheckBox) view.findViewById(R.id.selected); - if (mKeyType == Id.type.public_key) { - selected.setVisibility(View.VISIBLE); + h.status.setTag(enabled); - if (!valid) { - mListView.setItemChecked(cursor.getPosition(), false); - } - - selected.setChecked(mListView.isItemChecked(cursor.getPosition())); - selected.setEnabled(valid); - } else { - selected.setVisibility(View.GONE); - } - - view.setEnabled(valid); - mainUserId.setEnabled(valid); - mainUserIdRest.setEnabled(valid); - keyId.setEnabled(valid); - status.setEnabled(valid); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { - return mInflater.inflate(R.layout.select_key_item, null); + View view = mInflater.inflate(R.layout.select_key_item, null); + ViewHolderItem holder = new ViewHolderItem(); + holder.view = view; + holder.mainUserId = (TextView) view.findViewById(R.id.mainUserId); + holder.mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); + holder.keyId = (TextView) view.findViewById(R.id.keyId); + holder.status = (TextView) view.findViewById(R.id.status); + holder.selected = (CheckBox) view.findViewById(R.id.selected); + view.setTag(holder); + return view; } } diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index ecc57de49..c21a120a2 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -523,5 +523,7 @@ Revocation Reason Verification Status Type + can certify + cannot certify