From f677446d512a206a64e8fe9316baf42127a13435 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 16 Jun 2015 12:38:33 +0200 Subject: use KeyAdapter in KeySpinner --- .../compatibility/ClipboardReflection.java | 4 + .../keychain/ui/EncryptModeAsymmetricFragment.java | 2 +- .../keychain/ui/EncryptTextFragment.java | 2 +- .../keychain/ui/adapter/KeyAdapter.java | 69 +++++---- .../keychain/ui/widget/CertifyKeySpinner.java | 36 ++--- .../ui/widget/EncryptKeyCompletionView.java | 13 +- .../keychain/ui/widget/KeySpinner.java | 170 ++++++--------------- .../keychain/ui/widget/SignKeySpinner.java | 33 +--- 8 files changed, 127 insertions(+), 202 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/compatibility/ClipboardReflection.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/compatibility/ClipboardReflection.java index fa3600ffb..2f2838f70 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/compatibility/ClipboardReflection.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/compatibility/ClipboardReflection.java @@ -74,6 +74,10 @@ public class ClipboardReflection { Method methodGetPrimaryClip = clipboard.getClass().getMethod("getPrimaryClip"); Object clipData = methodGetPrimaryClip.invoke(clipboard); + if (clipData == null) { + return null; + } + // ClipData.Item clipDataItem = clipData.getItemAt(0); Method methodGetItemAt = clipData.getClass().getMethod("getItemAt", int.class); Object clipDataItem = methodGetItemAt.invoke(clipData, 0); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java index ccc8bfa14..355c649e7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java @@ -167,7 +167,7 @@ public class EncryptModeAsymmetricFragment extends EncryptModeFragment { @Override public long getAsymmetricSigningKeyId() { - return mSignKeySpinner.getSelectedItemId(); + return mSignKeySpinner.getSelectedKeyId(); } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java index 83fede917..d93b52453 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java @@ -240,7 +240,7 @@ public class EncryptTextFragment boolean gotEncryptionKeys = (encryptionKeyIds != null && encryptionKeyIds.length > 0); - if (!gotEncryptionKeys && signingKeyId == 0L) { + if (!gotEncryptionKeys && signingKeyId == Constants.key.none) { Notify.create(getActivity(), R.string.select_encryption_or_signature_key, Notify.Style.ERROR) .show(this); return null; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java index deaaee87a..1fc24775b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java @@ -19,15 +19,16 @@ package org.sufficientlysecure.keychain.ui.adapter; import java.io.Serializable; -import java.util.Calendar; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Date; -import java.util.TimeZone; +import java.util.List; import android.content.Context; import android.database.Cursor; import android.graphics.PorterDuff; import android.support.v4.widget.CursorAdapter; -import android.text.format.DateFormat; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; @@ -60,7 +61,6 @@ public class KeyAdapter extends CursorAdapter { KeyRings.VERIFIED, KeyRings.HAS_ANY_SECRET, KeyRings.HAS_DUPLICATE_USER_ID, - KeyRings.HAS_ENCRYPT, KeyRings.FINGERPRINT, KeyRings.CREATION, }; @@ -72,9 +72,8 @@ public class KeyAdapter extends CursorAdapter { public static final int INDEX_VERIFIED = 5; public static final int INDEX_HAS_ANY_SECRET = 6; public static final int INDEX_HAS_DUPLICATE_USER_ID = 7; - public static final int INDEX_HAS_ENCRYPT = 8; - public static final int INDEX_FINGERPRINT = 9; - public static final int INDEX_CREATION = 10; + public static final int INDEX_FINGERPRINT = 8; + public static final int INDEX_CREATION = 9; public KeyAdapter(Context context, Cursor c, int flags) { super(context, c, flags); @@ -87,6 +86,7 @@ public class KeyAdapter extends CursorAdapter { } public static class KeyItemViewHolder { + public View mView; public Long mMasterKeyId; public TextView mMainUserId; public TextView mMainUserIdRest; @@ -96,6 +96,7 @@ public class KeyAdapter extends CursorAdapter { public ImageButton mSlingerButton; public KeyItemViewHolder(View view) { + mView = view; mMainUserId = (TextView) view.findViewById(R.id.key_list_item_name); mMainUserIdRest = (TextView) view.findViewById(R.id.key_list_item_email); mStatus = (ImageView) view.findViewById(R.id.key_list_item_status_icon); @@ -104,11 +105,10 @@ public class KeyAdapter extends CursorAdapter { mCreationDate = (TextView) view.findViewById(R.id.key_list_item_creation); } - public void setData(Context context, Cursor cursor, Highlighter highlighter) { + public void setData(Context context, KeyItem item, Highlighter highlighter) { { // set name and stuff, common to both key types - String userId = cursor.getString(INDEX_USER_ID); - KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId); + KeyRing.UserId userIdSplit = item.mUserId; if (userIdSplit.name != null) { mMainUserId.setText(highlighter.highlight(userIdSplit.name)); } else { @@ -124,30 +124,23 @@ public class KeyAdapter extends CursorAdapter { { // set edit button and status, specific by key type - long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID); - boolean isSecret = cursor.getInt(INDEX_HAS_ANY_SECRET) != 0; - boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; - boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0; - boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; - boolean hasDuplicate = cursor.getInt(INDEX_HAS_DUPLICATE_USER_ID) != 0; - - mMasterKeyId = masterKeyId; + mMasterKeyId = item.mKeyId; // Note: order is important! - if (isRevoked) { + if (item.mIsRevoked) { KeyFormattingUtils .setStatusImage(context, mStatus, null, State.REVOKED, R.color.bg_gray); mStatus.setVisibility(View.VISIBLE); mSlinger.setVisibility(View.GONE); mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray)); mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.bg_gray)); - } else if (isExpired) { + } else if (item.mIsExpired) { KeyFormattingUtils.setStatusImage(context, mStatus, null, State.EXPIRED, R.color.bg_gray); mStatus.setVisibility(View.VISIBLE); mSlinger.setVisibility(View.GONE); mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray)); mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.bg_gray)); - } else if (isSecret) { + } else if (item.mIsSecret) { mStatus.setVisibility(View.GONE); if (mSlingerButton.hasOnClickListeners()) { mSlinger.setVisibility(View.VISIBLE); @@ -158,7 +151,7 @@ public class KeyAdapter extends CursorAdapter { mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.black)); } else { // this is a public key - show if it's verified - if (isVerified) { + if (item.mIsVerified) { KeyFormattingUtils.setStatusImage(context, mStatus, State.VERIFIED); mStatus.setVisibility(View.VISIBLE); } else { @@ -170,9 +163,9 @@ public class KeyAdapter extends CursorAdapter { mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.black)); } - if (hasDuplicate) { + if (item.mHasDuplicate) { String dateTime = DateUtils.formatDateTime(context, - cursor.getLong(INDEX_CREATION) * 1000, + item.mCreation.getTime(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH); @@ -190,6 +183,10 @@ public class KeyAdapter extends CursorAdapter { } + public boolean isEnabled(Cursor cursor) { + return true; + } + @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = mInflater.inflate(R.layout.key_list_item, parent, false); @@ -204,7 +201,8 @@ public class KeyAdapter extends CursorAdapter { public void bindView(View view, Context context, Cursor cursor) { Highlighter highlighter = new Highlighter(context, mQuery); KeyItemViewHolder h = (KeyItemViewHolder) view.getTag(); - h.setData(context, cursor, highlighter); + KeyItem item = new KeyItem(cursor); + h.setData(context, item, highlighter); } public boolean isSecretAvailable(int id) { @@ -234,8 +232,9 @@ public class KeyAdapter extends CursorAdapter { @Override public long getItemId(int position) { + Cursor cursor = getCursor(); // prevent a crash on rapid cursor changes - if (getCursor().isClosed()) { + if (cursor != null && getCursor().isClosed()) { return 0L; } return super.getItemId(position); @@ -250,6 +249,7 @@ public class KeyAdapter extends CursorAdapter { public final boolean mHasDuplicate; public final Date mCreation; public final String mFingerprint; + public final boolean mIsSecret, mIsRevoked, mIsExpired, mIsVerified; private KeyItem(Cursor cursor) { String userId = cursor.getString(INDEX_USER_ID); @@ -260,6 +260,10 @@ public class KeyAdapter extends CursorAdapter { mCreation = new Date(cursor.getLong(INDEX_CREATION) * 1000); mFingerprint = KeyFormattingUtils.convertFingerprintToHex( cursor.getBlob(INDEX_FINGERPRINT)); + mIsSecret = cursor.getInt(INDEX_HAS_ANY_SECRET) != 0; + mIsRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; + mIsExpired = cursor.getInt(INDEX_IS_EXPIRED) > 0; + mIsVerified = cursor.getInt(INDEX_VERIFIED) > 0; } public KeyItem(CanonicalizedPublicKeyRing ring) { @@ -272,6 +276,12 @@ public class KeyAdapter extends CursorAdapter { mCreation = key.getCreationTime(); mFingerprint = KeyFormattingUtils.convertFingerprintToHex( ring.getFingerprint()); + mIsRevoked = key.isRevoked(); + mIsExpired = key.isExpired(); + + // these two are actually "don't know"s + mIsSecret = false; + mIsVerified = false; } public String getReadableName() { @@ -284,4 +294,11 @@ public class KeyAdapter extends CursorAdapter { } + public static String[] getProjectionWith(String[] projection) { + List list = new ArrayList<>(); + list.addAll(Arrays.asList(PROJECTION)); + list.addAll(Arrays.asList(projection)); + return list.toArray(new String[list.size()]); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index 845b35512..0fed46544 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -17,6 +17,10 @@ package org.sufficientlysecure.keychain.ui.widget; + +import java.util.Arrays; +import java.util.List; + import android.content.Context; import android.database.Cursor; import android.net.Uri; @@ -24,14 +28,11 @@ import android.os.Bundle; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.AttributeSet; -import android.widget.ImageView; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainDatabase; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; +import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter; public class CertifyKeySpinner extends KeySpinner { private long mHiddenMasterKeyId = Constants.key.none; @@ -59,19 +60,9 @@ public class CertifyKeySpinner extends KeySpinner { // sample only has one Loader, so we don't care about the ID. Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingsUri(); - // These are the rows that we will retrieve. - String[] projection = new String[]{ - KeychainContract.KeyRings._ID, - KeychainContract.KeyRings.MASTER_KEY_ID, - KeychainContract.KeyRings.KEY_ID, - KeychainContract.KeyRings.USER_ID, - KeychainContract.KeyRings.IS_REVOKED, - KeychainContract.KeyRings.IS_EXPIRED, + String[] projection = KeyAdapter.getProjectionWith(new String[] { KeychainContract.KeyRings.HAS_CERTIFY, - KeychainContract.KeyRings.HAS_ANY_SECRET, - KeychainContract.KeyRings.HAS_DUPLICATE_USER_ID, - KeychainContract.KeyRings.CREATION - }; + }); String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1 AND " + KeychainDatabase.Tables.KEYS + "." + KeychainContract.KeyRings.MASTER_KEY_ID @@ -82,7 +73,7 @@ public class CertifyKeySpinner extends KeySpinner { return new CursorLoader(getContext(), baseUri, projection, where, null, null); } - private int mIndexHasCertify, mIndexIsRevoked, mIndexIsExpired; + private int mIndexHasCertify; @Override public void onLoadFinished(Loader loader, Cursor data) { @@ -90,8 +81,6 @@ public class CertifyKeySpinner extends KeySpinner { if (loader.getId() == LOADER_ID) { mIndexHasCertify = data.getColumnIndex(KeychainContract.KeyRings.HAS_CERTIFY); - mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); - mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED); // If: // - no key has been pre-selected (e.g. by SageSlinger) @@ -119,18 +108,15 @@ public class CertifyKeySpinner extends KeySpinner { @Override - boolean setStatus(Context context, Cursor cursor, ImageView statusView) { - if (cursor.getInt(mIndexIsRevoked) != 0) { - KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.REVOKED, R.color.bg_gray); + boolean isItemEnabled(Cursor cursor) { + if (cursor.getInt(KeyAdapter.INDEX_IS_REVOKED) != 0) { return false; } - if (cursor.getInt(mIndexIsExpired) != 0) { - KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.EXPIRED, R.color.bg_gray); + if (cursor.getInt(KeyAdapter.INDEX_IS_EXPIRED) != 0) { return false; } // don't invalidate the "None" entry, which is also null! if (cursor.getPosition() != 0 && cursor.isNull(mIndexHasCertify)) { - KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.UNAVAILABLE, R.color.bg_gray); return false; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index 63a1aade9..48e6c2cee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -38,6 +38,7 @@ import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter; @@ -126,7 +127,13 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView public Loader onCreateLoader(int id, Bundle args) { // These are the rows that we will retrieve. Uri baseUri = KeyRings.buildUnifiedKeyRingsUri(); - String where = KeyRings.HAS_ENCRYPT + " NOT NULL AND " + KeyRings.IS_EXPIRED + " = 0 AND " + + String[] projection = KeyAdapter.getProjectionWith(new String[] { + KeychainContract.KeyRings.HAS_ENCRYPT, + }); + + String where = KeyRings.HAS_ENCRYPT + " NOT NULL AND " + + KeyRings.IS_EXPIRED + " = 0 AND " + Tables.KEYS + "." + KeyRings.IS_REVOKED + " = 0"; if (args != null && args.containsKey(ARG_QUERY)) { @@ -135,12 +142,12 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView where += " AND " + KeyRings.USER_ID + " LIKE ?"; - return new CursorLoader(getContext(), baseUri, KeyAdapter.PROJECTION, where, + return new CursorLoader(getContext(), baseUri, projection, where, new String[]{"%" + query + "%"}, null); } mAdapter.setSearchQuery(null); - return new CursorLoader(getContext(), baseUri, KeyAdapter.PROJECTION, where, null, null); + return new CursorLoader(getContext(), baseUri, projection, where, null, null); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index ad1a14a33..5050c01af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -17,33 +17,30 @@ package org.sufficientlysecure.keychain.ui.widget; -import android.annotation.SuppressLint; + import android.content.Context; import android.database.Cursor; -import android.graphics.Color; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; -import android.support.v4.widget.CursorAdapter; import android.support.v7.widget.AppCompatSpinner; -import android.text.format.DateUtils; import android.util.AttributeSet; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; -import android.widget.ImageView; import android.widget.SpinnerAdapter; -import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter; +import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter.KeyItem; + /** * Use AppCompatSpinner from AppCompat lib instead of Spinner. Fixes white dropdown icon. @@ -119,7 +116,8 @@ public abstract class KeySpinner extends AppCompatSpinner implements if (getContext() instanceof FragmentActivity) { ((FragmentActivity) getContext()).getSupportLoaderManager().restartLoader(LOADER_ID, null, this); } else { - Log.e(Constants.TAG, "KeySpinner must be attached to FragmentActivity, this is " + getContext().getClass()); + throw new AssertionError("KeySpinner must be attached to FragmentActivity, this is " + + getContext().getClass()); } } @@ -138,7 +136,11 @@ public abstract class KeySpinner extends AppCompatSpinner implements } public long getSelectedKeyId() { - return getSelectedItemId(); + Object item = getSelectedItem(); + if (item instanceof KeyItem) { + return ((KeyItem) item).mKeyId; + } + return Constants.key.none; } public void setPreSelectedKeyId(long selectedKeyId) { @@ -146,161 +148,87 @@ public abstract class KeySpinner extends AppCompatSpinner implements } protected class SelectKeyAdapter extends BaseAdapter implements SpinnerAdapter { - private CursorAdapter inner; - private int mIndexUserId; - private int mIndexDuplicate; + private KeyAdapter inner; private int mIndexMasterKeyId; - private int mIndexCreationDate; public SelectKeyAdapter() { - inner = new CursorAdapter(getContext(), null, 0) { - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - return View.inflate(getContext(), R.layout.keyspinner_item, null); - } + inner = new KeyAdapter(getContext(), null, 0) { @Override - public void bindView(View view, Context context, Cursor cursor) { - TextView vKeyName = (TextView) view.findViewById(R.id.keyspinner_key_name); - ImageView vKeyStatus = (ImageView) view.findViewById(R.id.keyspinner_key_status); - TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); - TextView vDuplicate = (TextView) view.findViewById(R.id.keyspinner_duplicate); - - KeyRing.UserId userId = KeyRing.splitUserId(cursor.getString(mIndexUserId)); - vKeyName.setText(userId.name); - vKeyEmail.setText(userId.email); - - boolean duplicate = cursor.getLong(mIndexDuplicate) > 0; - if (duplicate) { - String dateTime = DateUtils.formatDateTime(context, - cursor.getLong(mIndexCreationDate) * 1000, - DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_SHOW_YEAR - | DateUtils.FORMAT_ABBREV_MONTH); - - vDuplicate.setText(context.getString(R.string.label_key_created, dateTime)); - vDuplicate.setVisibility(View.VISIBLE); - } else { - vDuplicate.setVisibility(View.GONE); - } - - boolean valid = setStatus(getContext(), cursor, vKeyStatus); - setItemEnabled(view, valid); + public boolean isEnabled(Cursor cursor) { + return KeySpinner.this.isItemEnabled(cursor); } - @Override - public long getItemId(int position) { - try { - return ((Cursor) getItem(position)).getLong(mIndexMasterKeyId); - } catch (Exception e) { - // This can happen on concurrent modification :( - return Constants.key.none; - } - } }; } - private void setItemEnabled(View view, boolean enabled) { - TextView vKeyName = (TextView) view.findViewById(R.id.keyspinner_key_name); - ImageView vKeyStatus = (ImageView) view.findViewById(R.id.keyspinner_key_status); - TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); - TextView vKeyDuplicate = (TextView) view.findViewById(R.id.keyspinner_duplicate); - - if (enabled) { - vKeyName.setTextColor(Color.BLACK); - vKeyEmail.setTextColor(Color.BLACK); - vKeyDuplicate.setTextColor(Color.BLACK); - vKeyStatus.setVisibility(View.GONE); - view.setClickable(false); - } else { - vKeyName.setTextColor(Color.GRAY); - vKeyEmail.setTextColor(Color.GRAY); - vKeyDuplicate.setTextColor(Color.GRAY); - vKeyStatus.setVisibility(View.VISIBLE); - // this is a HACK. the trick is, if the element itself is clickable, the - // click is not passed on to the view list - view.setClickable(true); - } - } - public Cursor swapCursor(Cursor newCursor) { if (newCursor == null) return inner.swapCursor(null); - mIndexDuplicate = newCursor.getColumnIndex(KeychainContract.KeyRings.HAS_DUPLICATE_USER_ID); - mIndexUserId = newCursor.getColumnIndex(KeychainContract.KeyRings.USER_ID); mIndexMasterKeyId = newCursor.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID); - mIndexCreationDate = newCursor.getColumnIndex(KeychainContract.KeyRings.CREATION); + + Cursor oldCursor = inner.swapCursor(newCursor); // pre-select key if mPreSelectedKeyId is given if (mPreSelectedKeyId != Constants.key.none && newCursor.moveToFirst()) { do { if (newCursor.getLong(mIndexMasterKeyId) == mPreSelectedKeyId) { - setSelection(newCursor.getPosition() + 1); + setSelection(newCursor.getPosition() +1); } } while (newCursor.moveToNext()); } - return inner.swapCursor(newCursor); + return oldCursor; } @Override public int getCount() { - return inner.getCount() + 1; + return inner.getCount() +1; } @Override public Object getItem(int position) { - if (position == 0) return null; - return inner.getItem(position - 1); + if (position == 0) { + return null; + } + return inner.getItem(position -1); } @Override public long getItemId(int position) { - if (position == 0) return Constants.key.none; - return inner.getItemId(position - 1); + if (position == 0) { + return Constants.key.none; + } + return inner.getItemId(position -1); } - @SuppressLint("ViewHolder") // inflate call is for the preview only @Override public View getView(int position, View convertView, ViewGroup parent) { - try { - View v = getDropDownView(position, convertView, parent); - v.findViewById(R.id.keyspinner_key_email).setVisibility(View.GONE); - return v; - } catch (NullPointerException e) { - // This is for the preview... - return View.inflate(getContext(), android.R.layout.simple_list_item_1, null); - } - } - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - View view; - if (position == 0) { - if (convertView == null) { - view = inner.newView(null, null, parent); - } else { - view = convertView; + // Unfortunately, SpinnerAdapter does not support multiple view + // types. For this reason, we throw away convertViews of a bad + // type. This is sort of a hack, but since the number of elements + // we deal with in KeySpinners is usually very small (number of + // secret keys), this is the easiest solution. (I'm sorry.) + if (convertView != null) { + // This assumes that the inner view has non-null tags on its views! + boolean isWrongType = (convertView.getTag() == null) != (position == 0); + if (isWrongType) { + convertView = null; } - TextView vKeyName = (TextView) view.findViewById(R.id.keyspinner_key_name); - ImageView vKeyStatus = (ImageView) view.findViewById(R.id.keyspinner_key_status); - TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); - TextView vKeyDuplicate = (TextView) view.findViewById(R.id.keyspinner_duplicate); - - vKeyName.setText(R.string.choice_none); - vKeyEmail.setVisibility(View.GONE); - vKeyDuplicate.setVisibility(View.GONE); - vKeyStatus.setVisibility(View.GONE); - setItemEnabled(view, true); - } else { - view = inner.getView(position - 1, convertView, parent); - TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); - vKeyEmail.setVisibility(View.VISIBLE); } - return view; + + if (position > 0) { + return inner.getView(position -1, convertView, parent); + } + + return convertView != null ? convertView : + LayoutInflater.from(getContext()).inflate( + R.layout.keyspinner_item_none, parent, false); } + } - boolean setStatus(Context context, Cursor cursor, ImageView statusView) { + boolean isItemEnabled(Cursor cursor) { return true; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java index df7347fa4..c59ad7a12 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java @@ -17,6 +17,7 @@ package org.sufficientlysecure.keychain.ui.widget; + import android.content.Context; import android.database.Cursor; import android.net.Uri; @@ -24,12 +25,9 @@ import android.os.Bundle; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.AttributeSet; -import android.widget.ImageView; -import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; +import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter; public class SignKeySpinner extends KeySpinner { public SignKeySpinner(Context context) { @@ -50,19 +48,9 @@ public class SignKeySpinner extends KeySpinner { // sample only has one Loader, so we don't care about the ID. Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingsUri(); - // These are the rows that we will retrieve. - String[] projection = new String[]{ - KeychainContract.KeyRings._ID, - KeychainContract.KeyRings.MASTER_KEY_ID, - KeychainContract.KeyRings.KEY_ID, - KeychainContract.KeyRings.USER_ID, - KeychainContract.KeyRings.IS_REVOKED, - KeychainContract.KeyRings.IS_EXPIRED, + String[] projection = KeyAdapter.getProjectionWith(new String[] { KeychainContract.KeyRings.HAS_SIGN, - KeychainContract.KeyRings.HAS_ANY_SECRET, - KeychainContract.KeyRings.HAS_DUPLICATE_USER_ID, - KeychainContract.KeyRings.CREATION - }; + }); String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1"; @@ -71,7 +59,7 @@ public class SignKeySpinner extends KeySpinner { return new CursorLoader(getContext(), baseUri, projection, where, null, null); } - private int mIndexHasSign, mIndexIsRevoked, mIndexIsExpired; + private int mIndexHasSign; @Override public void onLoadFinished(Loader loader, Cursor data) { @@ -79,23 +67,18 @@ public class SignKeySpinner extends KeySpinner { if (loader.getId() == LOADER_ID) { mIndexHasSign = data.getColumnIndex(KeychainContract.KeyRings.HAS_SIGN); - mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); - mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED); } } @Override - boolean setStatus(Context context, Cursor cursor, ImageView statusView) { - if (cursor.getInt(mIndexIsRevoked) != 0) { - KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.REVOKED, R.color.bg_gray); + boolean isItemEnabled(Cursor cursor) { + if (cursor.getInt(KeyAdapter.INDEX_IS_REVOKED) != 0) { return false; } - if (cursor.getInt(mIndexIsExpired) != 0) { - KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.EXPIRED, R.color.bg_gray); + if (cursor.getInt(KeyAdapter.INDEX_IS_EXPIRED) != 0) { return false; } if (cursor.getInt(mIndexHasSign) == 0) { - KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.UNAVAILABLE, R.color.bg_gray); return false; } -- cgit v1.2.3