aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-06-16 12:38:33 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-06-17 18:53:01 +0200
commitf677446d512a206a64e8fe9316baf42127a13435 (patch)
tree6c2877c601f02679f2e6ab1364c3009bb985863d /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget
parentb87a7372c9f5c5cca6cc90a5f4a95486b0766dda (diff)
downloadopen-keychain-f677446d512a206a64e8fe9316baf42127a13435.tar.gz
open-keychain-f677446d512a206a64e8fe9316baf42127a13435.tar.bz2
open-keychain-f677446d512a206a64e8fe9316baf42127a13435.zip
use KeyAdapter in KeySpinner
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java36
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java170
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java33
4 files changed, 78 insertions, 174 deletions
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<Cursor> 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<Cursor> 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<Cursor> 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;
}