aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2014-01-27 14:18:25 +0100
committerDominik Schürmann <dominik@dominikschuermann.de>2014-01-27 14:18:25 +0100
commitcb3ca37db9c5c3da05df804979e99628fff6f7b0 (patch)
treed32bd573bdd0cbbcde68a562a48915e95386ba4d /OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter
parent08e57019b092d8abcd443a6801cc040d46403021 (diff)
downloadopen-keychain-cb3ca37db9c5c3da05df804979e99628fff6f7b0.tar.gz
open-keychain-cb3ca37db9c5c3da05df804979e99628fff6f7b0.tar.bz2
open-keychain-cb3ca37db9c5c3da05df804979e99628fff6f7b0.zip
New Gradle project structure
Diffstat (limited to 'OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter')
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java159
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java105
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java128
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java221
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java139
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java101
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java167
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java123
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java76
9 files changed, 1219 insertions, 0 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
new file mode 100644
index 000000000..41539d0f8
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import java.util.List;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Build;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.TextView;
+
+public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
+ protected LayoutInflater mInflater;
+ protected Activity mActivity;
+
+ protected List<ImportKeysListEntry> data;
+
+ public ImportKeysAdapter(Activity activity) {
+ super(activity, -1);
+ mActivity = activity;
+ mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @SuppressLint("NewApi")
+ public void setData(List<ImportKeysListEntry> data) {
+ clear();
+ if (data != null) {
+ this.data = data;
+
+ // add data to extended ArrayAdapter
+ if (Build.VERSION.SDK_INT >= 11) {
+ addAll(data);
+ } else {
+ for (ImportKeysListEntry entry : data) {
+ add(entry);
+ }
+ }
+ }
+ }
+
+ public List<ImportKeysListEntry> getData() {
+ return data;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImportKeysListEntry entry = data.get(position);
+
+ View view = mInflater.inflate(R.layout.import_keys_list_entry, null);
+
+ 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("");
+ TextView keyId = (TextView) view.findViewById(R.id.keyId);
+ keyId.setText(R.string.no_key);
+ TextView fingerprint = (TextView) view.findViewById(R.id.fingerprint);
+ TextView algorithm = (TextView) view.findViewById(R.id.algorithm);
+ algorithm.setText("");
+ TextView status = (TextView) view.findViewById(R.id.status);
+ status.setText("");
+
+ String userId = entry.userIds.get(0);
+ if (userId != null) {
+ String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
+
+ if (userIdSplit[0] != null && userIdSplit[0].length() > 0) {
+ // show red user id if it is a secret key
+ if (entry.secretKey) {
+ userId = mActivity.getString(R.string.secret_key) + " " + userId;
+ mainUserId.setTextColor(Color.RED);
+ } else {
+ mainUserId.setText(userIdSplit[0]);
+ }
+ }
+
+ if (userIdSplit[1] != null && userIdSplit[1].length() > 0) {
+ mainUserIdRest.setText(userIdSplit[1]);
+ mainUserIdRest.setVisibility(View.VISIBLE);
+ } else {
+ mainUserIdRest.setVisibility(View.GONE);
+ }
+
+ }
+
+ keyId.setText(entry.hexKeyId);
+ fingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrint);
+
+ algorithm.setText("" + entry.bitStrength + "/" + entry.algorithm);
+
+ if (entry.revoked) {
+ status.setText("revoked");
+ } else {
+ status.setVisibility(View.GONE);
+ }
+
+ LinearLayout ll = (LinearLayout) view.findViewById(R.id.list);
+ if (entry.userIds.size() == 1) {
+ ll.setVisibility(View.GONE);
+ } else {
+ boolean first = true;
+ boolean second = true;
+ for (String uid : entry.userIds) {
+ if (first) {
+ first = false;
+ continue;
+ }
+ if (!second) {
+ View sep = new View(mActivity);
+ sep.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 1));
+ sep.setBackgroundResource(android.R.drawable.divider_horizontal_dark);
+ ll.addView(sep);
+ }
+ TextView uidView = (TextView) mInflater.inflate(
+ R.layout.import_keys_list_entry_user_id, null);
+ uidView.setText(uid);
+ ll.addView(uidView);
+ second = false;
+ }
+ }
+
+ CheckBox cBox = (CheckBox) view.findViewById(R.id.selected);
+ cBox.setChecked(entry.isSelected());
+
+ return view;
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java
new file mode 100644
index 000000000..1a100a585
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+import org.spongycastle.openpgp.PGPKeyRing;
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.util.AlgorithmNames;
+import org.sufficientlysecure.keychain.util.IterableIterator;
+
+public class ImportKeysListEntry implements Serializable {
+ private static final long serialVersionUID = -7797972103284992662L;
+ public ArrayList<String> userIds;
+ public long keyId;
+
+ public boolean revoked;
+ // public Date date;
+ public String fingerPrint;
+ public String hexKeyId;
+ public int bitStrength;
+ public String algorithm;
+ public boolean secretKey;
+ AlgorithmNames algorithmNames;
+
+ private boolean selected;
+
+ /**
+ * Constructor for later querying from keyserver
+ */
+ public ImportKeysListEntry() {
+ secretKey = false;
+ userIds = new ArrayList<String>();
+ }
+
+ public boolean isSelected() {
+ return selected;
+ }
+
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+ /**
+ * Constructor based on key object, used for import from NFC, QR Codes, files
+ *
+ * @param pgpKey
+ */
+ @SuppressWarnings("unchecked")
+ public ImportKeysListEntry(PGPKeyRing pgpKeyRing) {
+ // selected is default
+ this.selected = true;
+
+ if (pgpKeyRing instanceof PGPSecretKeyRing) {
+ secretKey = true;
+ } else {
+ secretKey = false;
+ }
+
+ userIds = new ArrayList<String>();
+ for (String userId : new IterableIterator<String>(pgpKeyRing.getPublicKey().getUserIDs())) {
+ userIds.add(userId);
+ }
+ this.keyId = pgpKeyRing.getPublicKey().getKeyID();
+
+ this.revoked = pgpKeyRing.getPublicKey().isRevoked();
+ this.fingerPrint = PgpKeyHelper.convertFingerprintToHex(pgpKeyRing.getPublicKey()
+ .getFingerprint());
+ this.hexKeyId = PgpKeyHelper.convertKeyIdToHex(keyId);
+ this.bitStrength = pgpKeyRing.getPublicKey().getBitStrength();
+ int algorithm = pgpKeyRing.getPublicKey().getAlgorithm();
+ if (algorithm == PGPPublicKey.RSA_ENCRYPT || algorithm == PGPPublicKey.RSA_GENERAL
+ || algorithm == PGPPublicKey.RSA_SIGN) {
+ this.algorithm = "RSA";
+ } else if (algorithm == PGPPublicKey.DSA) {
+ this.algorithm = "DSA";
+ } else if (algorithm == PGPPublicKey.ELGAMAL_ENCRYPT
+ || algorithm == PGPPublicKey.ELGAMAL_GENERAL) {
+ this.algorithm = "ElGamal";
+ } else if (algorithm == PGPPublicKey.EC || algorithm == PGPPublicKey.ECDSA) {
+ this.algorithm = "ECC";
+ } else {
+ // TODO: with resources
+ this.algorithm = "unknown";
+ }
+ }
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
new file mode 100644
index 000000000..00ad8c957
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.spongycastle.openpgp.PGPKeyRing;
+import org.spongycastle.openpgp.PGPObjectFactory;
+import org.spongycastle.openpgp.PGPUtil;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.util.InputData;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
+
+import android.content.Context;
+import android.support.v4.content.AsyncTaskLoader;
+
+public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> {
+ Context mContext;
+
+ InputData mInputData;
+
+ ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
+
+ public ImportKeysListLoader(Context context, InputData inputData) {
+ super(context);
+ this.mContext = context;
+ this.mInputData = inputData;
+ }
+
+ @Override
+ public List<ImportKeysListEntry> loadInBackground() {
+ if (mInputData == null) {
+ Log.e(Constants.TAG, "Input data is null!");
+ return data;
+ }
+
+ generateListOfKeyrings(mInputData);
+
+ return data;
+ }
+
+ @Override
+ protected void onReset() {
+ super.onReset();
+
+ // Ensure the loader is stopped
+ onStopLoading();
+ }
+
+ @Override
+ protected void onStartLoading() {
+ forceLoad();
+ }
+
+ @Override
+ protected void onStopLoading() {
+ cancelLoad();
+ }
+
+ @Override
+ public void deliverResult(List<ImportKeysListEntry> data) {
+ super.deliverResult(data);
+ }
+
+ /**
+ * Reads all PGPKeyRing objects from input
+ *
+ * @param keyringBytes
+ * @return
+ */
+ private void generateListOfKeyrings(InputData inputData) {
+ PositionAwareInputStream progressIn = new PositionAwareInputStream(
+ inputData.getInputStream());
+
+ // need to have access to the bufferedInput, so we can reuse it for the possible
+ // PGPObject chunks after the first one, e.g. files with several consecutive ASCII
+ // armour blocks
+ BufferedInputStream bufferedInput = new BufferedInputStream(progressIn);
+ try {
+
+ // read all available blocks... (asc files can contain many blocks with BEGIN END)
+ while (bufferedInput.available() > 0) {
+ InputStream in = PGPUtil.getDecoderStream(bufferedInput);
+ PGPObjectFactory objectFactory = new PGPObjectFactory(in);
+
+ // go through all objects in this block
+ Object obj;
+ while ((obj = objectFactory.nextObject()) != null) {
+ Log.d(Constants.TAG, "Found class: " + obj.getClass());
+
+ if (obj instanceof PGPKeyRing) {
+ PGPKeyRing newKeyring = (PGPKeyRing) obj;
+ addToData(newKeyring);
+ } else {
+ Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!");
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(Constants.TAG, "Exception on parsing key file!", e);
+ }
+ }
+
+ private void addToData(PGPKeyRing keyring) {
+ ImportKeysListEntry item = new ImportKeysListEntry(keyring);
+ data.add(item);
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
new file mode 100644
index 000000000..42afa2e95
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.util.Log;
+
+import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * Implements StickyListHeadersAdapter from library
+ */
+public class KeyListPublicAdapter extends CursorAdapter implements StickyListHeadersAdapter {
+ private LayoutInflater mInflater;
+ private int mSectionColumnIndex;
+ private int mIndexUserId;
+
+ @SuppressLint("UseSparseArrays")
+ private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
+
+ public KeyListPublicAdapter(Context context, Cursor c, int flags, int sectionColumnIndex) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+ mSectionColumnIndex = sectionColumnIndex;
+ initIndex(c);
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor newCursor) {
+ initIndex(newCursor);
+
+ return super.swapCursor(newCursor);
+ }
+
+ /**
+ * Get column indexes for performance reasons just once in constructor and swapCursor. For a
+ * performance comparison see http://stackoverflow.com/a/17999582
+ *
+ * @param cursor
+ */
+ private void initIndex(Cursor cursor) {
+ if (cursor != null) {
+ mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
+ }
+ }
+
+ /**
+ * Bind cursor data to the item list view
+ *
+ * NOTE: CursorAdapter already implements the ViewHolder pattern in its getView() method. Thus
+ * no ViewHolder is required here.
+ */
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ 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(mIndexUserId);
+ if (userId != null) {
+ String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
+
+ if (userIdSplit[0] != null && userIdSplit[0].length() > 0) {
+ mainUserId.setText(userIdSplit[0]);
+ }
+
+ if (userIdSplit[1] != null && userIdSplit[1].length() > 0) {
+ mainUserIdRest.setText(userIdSplit[1]);
+ }
+ }
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.key_list_item, null);
+ }
+
+ /**
+ * Creates a new header view and binds the section headers to it. It uses the ViewHolder
+ * pattern. Most functionality is similar to getView() from Android's CursorAdapter.
+ *
+ * NOTE: The variables mDataValid and mCursor are available due to the super class
+ * CursorAdapter.
+ */
+ @Override
+ public View getHeaderView(int position, View convertView, ViewGroup parent) {
+ HeaderViewHolder holder;
+ if (convertView == null) {
+ holder = new HeaderViewHolder();
+ convertView = mInflater.inflate(R.layout.key_list_public_header, parent, false);
+ holder.text = (TextView) convertView.findViewById(R.id.stickylist_header_text);
+ convertView.setTag(holder);
+ } else {
+ holder = (HeaderViewHolder) convertView.getTag();
+ }
+
+ if (!mDataValid) {
+ // no data available at this point
+ Log.d(Constants.TAG, "getHeaderView: No data available at this point!");
+ return convertView;
+ }
+
+ if (!mCursor.moveToPosition(position)) {
+ throw new IllegalStateException("couldn't move cursor to position " + position);
+ }
+
+ // set header text as first char in user id
+ String userId = mCursor.getString(mSectionColumnIndex);
+ String headerText = convertView.getResources().getString(R.string.unknown_user_id);
+ if (userId != null && userId.length() > 0) {
+ headerText = "" + mCursor.getString(mSectionColumnIndex).subSequence(0, 1).charAt(0);
+ }
+ holder.text.setText(headerText);
+ return convertView;
+ }
+
+ /**
+ * Header IDs should be static, position=1 should always return the same Id that is.
+ */
+ @Override
+ public long getHeaderId(int position) {
+ if (!mDataValid) {
+ // no data available at this point
+ Log.d(Constants.TAG, "getHeaderView: No data available at this point!");
+ return -1;
+ }
+
+ if (!mCursor.moveToPosition(position)) {
+ throw new IllegalStateException("couldn't move cursor to position " + position);
+ }
+
+ // return the first character of the name as ID because this is what
+ // headers private HashMap<Integer, Boolean> mSelection = new HashMap<Integer,
+ // Boolean>();are based upon
+ String userId = mCursor.getString(mSectionColumnIndex);
+ if (userId != null && userId.length() > 0) {
+ return userId.subSequence(0, 1).charAt(0);
+ } else {
+ return Long.MAX_VALUE;
+ }
+ }
+
+ class HeaderViewHolder {
+ 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;
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java
new file mode 100644
index 000000000..0043203bf
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class KeyListSecretAdapter extends CursorAdapter {
+ private LayoutInflater mInflater;
+
+ private int mIndexUserId;
+
+ @SuppressLint("UseSparseArrays")
+ private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
+
+ public KeyListSecretAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+ initIndex(c);
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor newCursor) {
+ initIndex(newCursor);
+
+ return super.swapCursor(newCursor);
+ }
+
+ /**
+ * Get column indexes for performance reasons just once in constructor and swapCursor. For a
+ * performance comparison see http://stackoverflow.com/a/17999582
+ *
+ * @param cursor
+ */
+ private void initIndex(Cursor cursor) {
+ if (cursor != null) {
+ mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
+ }
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ 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(mIndexUserId);
+ if (userId != null) {
+ String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
+
+ if (userIdSplit[0] != null && userIdSplit[0].length() > 0) {
+ mainUserId.setText(userIdSplit[0]);
+ }
+
+ if (userIdSplit[1] != null && userIdSplit[1].length() > 0) {
+ mainUserIdRest.setText(userIdSplit[1]);
+ }
+ }
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.key_list_item, null);
+ }
+
+ /** -------------------------- MULTI-SELECTION METHODS -------------- */
+ public void setNewSelection(int position, boolean value) {
+ mSelection.put(position, value);
+ notifyDataSetChanged();
+ }
+
+ public boolean isPositionChecked(int position) {
+ Boolean result = mSelection.get(position);
+ return result == null ? false : result;
+ }
+
+ public Set<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;
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java
new file mode 100644
index 000000000..78f7b1f7e
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import android.content.Context;
+import android.widget.ArrayAdapter;
+
+public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
+ private final HashMap<Integer, String> mData;
+ private final int[] mKeys;
+ private final String[] mValues;
+
+ static <K, V extends Comparable<? super V>> SortedSet<Map.Entry<K, V>> entriesSortedByValues(
+ Map<K, V> map) {
+ SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<Map.Entry<K, V>>(
+ new Comparator<Map.Entry<K, V>>() {
+ @Override
+ public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
+ return e1.getValue().compareTo(e2.getValue());
+ }
+ });
+ sortedEntries.addAll(map.entrySet());
+ return sortedEntries;
+ }
+
+ public KeyValueSpinnerAdapter(Context context, HashMap<Integer, String> objects) {
+ // To make the drop down a simple text box
+ super(context, android.R.layout.simple_spinner_item);
+ mData = objects;
+
+ // To make the drop down view a radio button list
+ setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+ SortedSet<Map.Entry<Integer, String>> sorted = entriesSortedByValues(objects);
+
+ // Assign hash keys with a position so that we can present and retrieve them
+ int i = 0;
+ mKeys = new int[mData.size()];
+ mValues = new String[mData.size()];
+ for (Map.Entry<Integer, String> entry : sorted) {
+ mKeys[i] = entry.getKey();
+ mValues[i] = entry.getValue();
+ i++;
+ }
+ }
+
+ public int getCount() {
+ return mData.size();
+ }
+
+ /**
+ * Returns the value
+ */
+ @Override
+ public String getItem(int position) {
+ // return the value based on the position. This is displayed in the list.
+ return mValues[position];
+ }
+
+ /**
+ * Returns item key
+ */
+ public long getItemId(int position) {
+ // Return an id to represent the item.
+
+ return mKeys[position];
+ }
+
+ /**
+ * Find position from key
+ */
+ public int getPosition(long itemId) {
+ for (int i = 0; i < mKeys.length; i++) {
+ if ((int) itemId == mKeys[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
new file mode 100644
index 000000000..f4a5e1a5d
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+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 android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.TextView;
+
+public class SelectKeyCursorAdapter extends CursorAdapter {
+
+ protected int mKeyType;
+
+ private LayoutInflater mInflater;
+ private ListView mListView;
+
+ private int mIndexUserId;
+ private int mIndexMasterKeyId;
+ private int mIndexProjectionValid;
+ private int mIndexProjectionAvailable;
+
+ public final static String PROJECTION_ROW_AVAILABLE = "available";
+ public final static String PROJECTION_ROW_VALID = "valid";
+
+ public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView,
+ int keyType) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+ mListView = listView;
+ mKeyType = keyType;
+
+ initIndex(c);
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor newCursor) {
+ initIndex(newCursor);
+
+ return super.swapCursor(newCursor);
+ }
+
+ /**
+ * Get column indexes for performance reasons just once in constructor and swapCursor. For a
+ * performance comparison see http://stackoverflow.com/a/17999582
+ *
+ * @param cursor
+ */
+ private void initIndex(Cursor cursor) {
+ if (cursor != null) {
+ mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
+ mIndexMasterKeyId = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID);
+ mIndexProjectionValid = cursor.getColumnIndexOrThrow(PROJECTION_ROW_VALID);
+ mIndexProjectionAvailable = cursor.getColumnIndexOrThrow(PROJECTION_ROW_AVAILABLE);
+ }
+ }
+
+ public String getUserId(int position) {
+ mCursor.moveToPosition(position);
+ return mCursor.getString(mIndexUserId);
+ }
+
+ public long getMasterKeyId(int position) {
+ mCursor.moveToPosition(position);
+ return mCursor.getLong(mIndexMasterKeyId);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ boolean valid = cursor.getInt(mIndexProjectionValid) > 0;
+
+ 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("");
+ TextView keyId = (TextView) view.findViewById(R.id.keyId);
+ keyId.setText(R.string.no_key);
+ TextView status = (TextView) view.findViewById(R.id.status);
+ status.setText(R.string.unknown_status);
+
+ String userId = cursor.getString(mIndexUserId);
+ if (userId != null) {
+ String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
+
+ if (userIdSplit[0] != null && userIdSplit[0].length() > 0) {
+ mainUserId.setText(userIdSplit[0]);
+ }
+
+ if (userIdSplit[1] != null && userIdSplit[1].length() > 0) {
+ mainUserIdRest.setText(userIdSplit[1]);
+ }
+ }
+
+ long masterKeyId = cursor.getLong(mIndexMasterKeyId);
+ keyId.setText(PgpKeyHelper.convertKeyIdToHex(masterKeyId));
+
+ if (valid) {
+ if (mKeyType == Id.type.public_key) {
+ status.setText(R.string.can_encrypt);
+ } else {
+ status.setText(R.string.can_sign);
+ }
+ } 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);
+ }
+ }
+
+ CheckBox selected = (CheckBox) view.findViewById(R.id.selected);
+ if (mKeyType == Id.type.public_key) {
+ selected.setVisibility(View.VISIBLE);
+
+ if (!valid) {
+ mListView.setItemChecked(cursor.getPosition(), false);
+ }
+
+ selected.setChecked(mListView.isItemChecked(cursor.getPosition()));
+ selected.setEnabled(valid);
+ } else {
+ selected.setVisibility(View.GONE);
+ }
+
+ status.setText(status.getText() + " ");
+
+ 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);
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java
new file mode 100644
index 000000000..d5162c403
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class ViewKeyKeysAdapter extends CursorAdapter {
+ private LayoutInflater mInflater;
+
+ private int mIndexKeyId;
+ private int mIndexAlgorithm;
+ private int mIndexKeySize;
+ private int mIndexIsMasterKey;
+ private int mIndexCanCertify;
+ private int mIndexCanEncrypt;
+ private int mIndexCanSign;
+
+ public ViewKeyKeysAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+
+ initIndex(c);
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor newCursor) {
+ initIndex(newCursor);
+
+ return super.swapCursor(newCursor);
+ }
+
+ /**
+ * Get column indexes for performance reasons just once in constructor and swapCursor. For a
+ * performance comparison see http://stackoverflow.com/a/17999582
+ *
+ * @param cursor
+ */
+ private void initIndex(Cursor cursor) {
+ if (cursor != null) {
+ mIndexKeyId = cursor.getColumnIndexOrThrow(Keys.KEY_ID);
+ mIndexAlgorithm = cursor.getColumnIndexOrThrow(Keys.ALGORITHM);
+ mIndexKeySize = cursor.getColumnIndexOrThrow(Keys.KEY_SIZE);
+ mIndexIsMasterKey = cursor.getColumnIndexOrThrow(Keys.IS_MASTER_KEY);
+ mIndexCanCertify = cursor.getColumnIndexOrThrow(Keys.CAN_CERTIFY);
+ mIndexCanEncrypt = cursor.getColumnIndexOrThrow(Keys.CAN_ENCRYPT);
+ mIndexCanSign = cursor.getColumnIndexOrThrow(Keys.CAN_SIGN);
+ }
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ String keyIdStr = "0x" + PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId));
+ String algorithmStr = PgpKeyHelper.getAlgorithmInfo(cursor.getInt(mIndexAlgorithm),
+ cursor.getInt(mIndexKeySize));
+
+ 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(mIndexIsMasterKey) != 1) {
+ masterKeyIcon.setVisibility(View.INVISIBLE);
+ } else {
+ masterKeyIcon.setVisibility(View.VISIBLE);
+ }
+
+ ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
+ if (cursor.getInt(mIndexCanCertify) != 1) {
+ certifyIcon.setVisibility(View.GONE);
+ } else {
+ certifyIcon.setVisibility(View.VISIBLE);
+ }
+
+ ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
+ if (cursor.getInt(mIndexCanEncrypt) != 1) {
+ encryptIcon.setVisibility(View.GONE);
+ } else {
+ encryptIcon.setVisibility(View.VISIBLE);
+ }
+
+ ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
+ if (cursor.getInt(mIndexCanSign) != 1) {
+ signIcon.setVisibility(View.GONE);
+ } else {
+ signIcon.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.view_key_keys_item, null);
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java
new file mode 100644
index 000000000..cf8699417
--- /dev/null
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class ViewKeyUserIdsAdapter extends CursorAdapter {
+ private LayoutInflater mInflater;
+
+ private int mIndexUserId;
+
+ public ViewKeyUserIdsAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+
+ initIndex(c);
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor newCursor) {
+ initIndex(newCursor);
+
+ return super.swapCursor(newCursor);
+ }
+
+ /**
+ * Get column indexes for performance reasons just once in constructor and swapCursor. For a
+ * performance comparison see http://stackoverflow.com/a/17999582
+ *
+ * @param cursor
+ */
+ private void initIndex(Cursor cursor) {
+ if (cursor != null) {
+ mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
+ }
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ String userIdStr = cursor.getString(mIndexUserId);
+
+ TextView userId = (TextView) view.findViewById(R.id.userId);
+ userId.setText(userIdStr);
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.view_key_userids_item, null);
+ }
+
+}