aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/settings
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/settings')
-rw-r--r--main/src/cgeo/geocaching/settings/AuthorizeOcDePreference.java41
-rw-r--r--main/src/cgeo/geocaching/settings/AuthorizeTwitterPreference.java41
-rw-r--r--main/src/cgeo/geocaching/settings/CheckBoxWithPopupPreference.java93
-rw-r--r--main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java123
-rw-r--r--main/src/cgeo/geocaching/settings/EditPasswordPreference.java29
-rw-r--r--main/src/cgeo/geocaching/settings/InfoPreference.java91
-rw-r--r--main/src/cgeo/geocaching/settings/LogSignaturePreference.java60
-rw-r--r--main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java122
-rw-r--r--main/src/cgeo/geocaching/settings/Settings.java967
-rw-r--r--main/src/cgeo/geocaching/settings/SettingsActivity.java532
-rw-r--r--main/src/cgeo/geocaching/settings/TextPreference.java86
-rw-r--r--main/src/cgeo/geocaching/settings/WpThresholdPreference.java73
12 files changed, 2258 insertions, 0 deletions
diff --git a/main/src/cgeo/geocaching/settings/AuthorizeOcDePreference.java b/main/src/cgeo/geocaching/settings/AuthorizeOcDePreference.java
new file mode 100644
index 0000000..d6768b9
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/AuthorizeOcDePreference.java
@@ -0,0 +1,41 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.connector.oc.OCAuthorizationActivity;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class AuthorizeOcDePreference extends Preference {
+
+ public AuthorizeOcDePreference(Context context) {
+ super(context);
+ }
+
+ public AuthorizeOcDePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AuthorizeOcDePreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+ setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Intent authIntent = new Intent(preference.getContext(),
+ OCAuthorizationActivity.class);
+ preference.getContext().startActivity(authIntent);
+
+ return false; // no shared preference has to be changed
+ }
+ });
+ return super.onCreateView(parent);
+ }
+}
diff --git a/main/src/cgeo/geocaching/settings/AuthorizeTwitterPreference.java b/main/src/cgeo/geocaching/settings/AuthorizeTwitterPreference.java
new file mode 100644
index 0000000..cfccad3
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/AuthorizeTwitterPreference.java
@@ -0,0 +1,41 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.twitter.TwitterAuthorizationActivity;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class AuthorizeTwitterPreference extends Preference {
+
+ public AuthorizeTwitterPreference(Context context) {
+ super(context);
+ }
+
+ public AuthorizeTwitterPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AuthorizeTwitterPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+ setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Intent authIntent = new Intent(preference.getContext(),
+ TwitterAuthorizationActivity.class);
+ preference.getContext().startActivity(authIntent);
+
+ return false; // no shared preference has to be changed
+ }
+ });
+ return super.onCreateView(parent);
+ }
+}
diff --git a/main/src/cgeo/geocaching/settings/CheckBoxWithPopupPreference.java b/main/src/cgeo/geocaching/settings/CheckBoxWithPopupPreference.java
new file mode 100644
index 0000000..4e64b9a
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/CheckBoxWithPopupPreference.java
@@ -0,0 +1,93 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.R;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.net.Uri;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class CheckBoxWithPopupPreference extends CheckBoxPreference {
+
+ // strings for the popup dialog
+ private String title;
+ private String text;
+ private String url;
+ private String urlButton;
+
+ public CheckBoxWithPopupPreference(Context context) {
+ super(context);
+ }
+
+ public CheckBoxWithPopupPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ processAttributes(context, attrs, 0);
+ }
+
+ public CheckBoxWithPopupPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ processAttributes(context, attrs, defStyle);
+ }
+
+ private void processAttributes(Context context, AttributeSet attrs, int defStyle) {
+ if (attrs == null) {
+ return; // coward's retreat
+ }
+
+ TypedArray types = context.obtainStyledAttributes(attrs, new int[] {
+ R.attr.title, R.attr.text, R.attr.url, R.attr.urlButton },
+ defStyle, 0);
+
+ title = types.getString(0);
+ text = types.getString(1);
+ url = types.getString(2);
+ urlButton = types.getString(3);
+
+ types.recycle();
+ }
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+
+ // show dialog when checkbox enabled
+ setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(final Preference preference, Object newValue) {
+ if (!(Boolean) newValue) {
+ return true;
+ }
+ AlertDialog.Builder builder = new AlertDialog.Builder(
+ preference.getContext());
+ builder.setMessage(text)
+ .setIcon(android.R.drawable.ic_dialog_info)
+ .setTitle(title)
+ .setPositiveButton(R.string.err_none, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ })
+ .setNegativeButton(urlButton, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setData(Uri.parse(url));
+ preference.getContext().startActivity(i);
+ }
+ });
+ builder.create().show();
+ return true;
+ }
+ });
+
+ return super.onCreateView(parent);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java b/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java
new file mode 100644
index 0000000..877a6c7
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java
@@ -0,0 +1,123 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.R;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.connector.gc.Login;
+import cgeo.geocaching.enumerations.StatusCode;
+import cgeo.geocaching.network.Cookies;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class CheckGcCredentialsPreference extends Preference {
+
+ public CheckGcCredentialsPreference(Context context) {
+ super(context);
+ }
+
+ public CheckGcCredentialsPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CheckGcCredentialsPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+ setOnPreferenceClickListener(GC_LOGIN_CHECK);
+ return super.onCreateView(parent);
+ }
+
+ private final GcLoginCheck GC_LOGIN_CHECK = new GcLoginCheck();
+
+ private class GcLoginCheck implements OnPreferenceClickListener {
+ private Resources res;
+ private Activity activity;
+
+ private ProgressDialog loginDialog;
+ @SuppressLint("HandlerLeak")
+ private Handler logInHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ if (loginDialog != null && loginDialog.isShowing()) {
+ loginDialog.dismiss();
+ }
+
+ if (msg.obj == null || (msg.obj instanceof Drawable)) {
+ ActivityMixin.helpDialog(activity,
+ res.getString(R.string.init_login_popup),
+ res.getString(R.string.init_login_popup_ok),
+ (Drawable) msg.obj);
+ } else {
+ ActivityMixin.helpDialog(activity,
+ res.getString(R.string.init_login_popup),
+ res.getString(R.string.init_login_popup_failed_reason)
+ + " "
+ + ((StatusCode) msg.obj).getErrorString(res)
+ + ".");
+ }
+ } catch (Exception e) {
+ ActivityMixin.showToast(activity, R.string.err_login_failed);
+ Log.e("SettingsActivity.logInHandler", e);
+ }
+
+ if (loginDialog != null && loginDialog.isShowing()) {
+ loginDialog.dismiss();
+ }
+ }
+ };
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ this.activity = (Activity) CheckGcCredentialsPreference.this.getContext();
+ this.res = activity.getResources();
+
+ ImmutablePair<String, String> credentials = Settings.getGcLogin();
+
+ // check credentials for validity
+ if (credentials == null || StringUtils.isBlank(credentials.getLeft())
+ || StringUtils.isBlank(credentials.getRight())) {
+ ActivityMixin.showToast(activity, R.string.err_missing_auth);
+ return false;
+ }
+
+ loginDialog = ProgressDialog.show(activity,
+ res.getString(R.string.init_login_popup),
+ res.getString(R.string.init_login_popup_working), true);
+ loginDialog.setCancelable(false);
+ Cookies.clearCookies();
+
+ (new Thread() {
+ @Override
+ public void run() {
+ final StatusCode loginResult = Login.login();
+ Object payload = loginResult;
+ if (loginResult == StatusCode.NO_ERROR) {
+ Login.detectGcCustomDate();
+ payload = Login.downloadAvatarAndGetMemberStatus();
+ }
+ logInHandler.obtainMessage(0, payload).sendToTarget();
+ }
+ }).start();
+
+ return false; // no shared preference has to be changed
+ }
+ }
+}
diff --git a/main/src/cgeo/geocaching/settings/EditPasswordPreference.java b/main/src/cgeo/geocaching/settings/EditPasswordPreference.java
new file mode 100644
index 0000000..d89f128
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/EditPasswordPreference.java
@@ -0,0 +1,29 @@
+package cgeo.geocaching.settings;
+
+import android.content.Context;
+import android.preference.EditTextPreference;
+import android.util.AttributeSet;
+
+/**
+ * This is just a dummy preference, to be able check for the type.
+ * <p>
+ * Use it exactly as an EditTextPreference
+ *
+ * @see SettingsActivity - search for EditPasswordPreference
+ * @author koem
+ */
+public class EditPasswordPreference extends EditTextPreference {
+
+ public EditPasswordPreference(Context context) {
+ super(context);
+ }
+
+ public EditPasswordPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public EditPasswordPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/settings/InfoPreference.java b/main/src/cgeo/geocaching/settings/InfoPreference.java
new file mode 100644
index 0000000..465cf12
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/InfoPreference.java
@@ -0,0 +1,91 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.R;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.net.Uri;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class InfoPreference extends Preference {
+
+ // strings for the popup dialog
+ private String text;
+ private String url;
+ private String urlButton;
+
+ public InfoPreference(Context context) {
+ super(context);
+ init(context, null, 0);
+ }
+
+ public InfoPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context, attrs, 0);
+ }
+
+ public InfoPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context, attrs, defStyle);
+ }
+
+ private void init(Context context, AttributeSet attrs, int defStyle) {
+ setPersistent(false);
+
+ if (attrs == null) {
+ return; // coward's retreat
+ }
+
+ TypedArray types = context.obtainStyledAttributes(attrs, new int[] {
+ android.R.attr.text, R.attr.url, R.attr.urlButton },
+ defStyle, 0);
+
+ text = types.getString(0);
+ url = types.getString(1);
+ urlButton = types.getString(2);
+
+ types.recycle();
+ }
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+
+ // show popup when clicked
+ setOnPreferenceClickListener(new OnPreferenceClickListener() {
+
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(
+ preference.getContext());
+ builder.setMessage(text)
+ .setIcon(android.R.drawable.ic_dialog_info)
+ .setTitle(preference.getTitle())
+ .setPositiveButton(R.string.err_none, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ })
+ .setNegativeButton(urlButton, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setData(Uri.parse(url));
+ preference.getContext().startActivity(i);
+ }
+ });
+ builder.create().show();
+ return false;
+ }
+ });
+
+ return super.onCreateView(parent);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/settings/LogSignaturePreference.java b/main/src/cgeo/geocaching/settings/LogSignaturePreference.java
new file mode 100644
index 0000000..d0c9739
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/LogSignaturePreference.java
@@ -0,0 +1,60 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.R;
+
+import android.content.Context;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+public class LogSignaturePreference extends DialogPreference {
+
+ private SettingsActivity settingsActivity;
+ private EditText editText;
+
+ public LogSignaturePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public LogSignaturePreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ setDialogLayoutResource(R.layout.log_signature_preference_dialog);
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ settingsActivity = (SettingsActivity) this.getContext();
+
+ editText = (EditText) view.findViewById(R.id.signature_dialog_text);
+ editText.setText(getPersistedString(""));
+ settingsActivity.setSignatureTextView(editText);
+
+ Button templates = (Button) view.findViewById(R.id.signature_templates);
+ settingsActivity.registerForContextMenu(templates);
+ templates.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View templates) {
+ settingsActivity.openContextMenu(templates);
+ }
+ });
+
+ super.onBindDialogView(view);
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ if (positiveResult) {
+ String text = editText.getText().toString();
+ persistString(text);
+ callChangeListener(text);
+ }
+ super.onDialogClosed(positiveResult);
+ }
+}
diff --git a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
new file mode 100644
index 0000000..a019c4a
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java
@@ -0,0 +1,122 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.network.Network;
+import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.utils.Log;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class RegisterSend2CgeoPreference extends Preference {
+
+ ProgressDialog progressDialog;
+ SettingsActivity activity;
+
+ public RegisterSend2CgeoPreference(Context context) {
+ super(context);
+ }
+
+ public RegisterSend2CgeoPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public RegisterSend2CgeoPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ private Handler webAuthHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ if (progressDialog != null && progressDialog.isShowing()) {
+ progressDialog.dismiss();
+ }
+
+ if (msg.what > 0) {
+ ActivityMixin.helpDialog(activity,
+ activity.getString(R.string.init_sendToCgeo),
+ activity.getString(R.string.init_sendToCgeo_register_ok)
+ .replace("####", String.valueOf(msg.what)));
+ } else {
+ ActivityMixin.helpDialog(activity,
+ activity.getString(R.string.init_sendToCgeo),
+ activity.getString(R.string.init_sendToCgeo_register_fail));
+ }
+ } catch (Exception e) {
+ ActivityMixin.showToast(activity, R.string.init_sendToCgeo_register_fail);
+ Log.e("SettingsActivity.webHandler", e);
+ }
+
+ if (progressDialog != null && progressDialog.isShowing()) {
+ progressDialog.dismiss();
+ }
+ }
+ };
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+ activity = (SettingsActivity) getContext();
+
+ setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ final String deviceName = Settings.getWebDeviceName();
+ final String deviceCode = Settings.getWebDeviceCode();
+
+ if (StringUtils.isBlank(deviceName)) {
+ ActivityMixin.showToast(activity, R.string.err_missing_device_name);
+ return false;
+ }
+
+ progressDialog = ProgressDialog.show(activity,
+ activity.getString(R.string.init_sendToCgeo),
+ activity.getString(R.string.init_sendToCgeo_registering), true);
+ progressDialog.setCancelable(false);
+
+ (new Thread() {
+
+ @Override
+ public void run() {
+ int pin = 0;
+
+ final String nam = StringUtils.defaultString(deviceName);
+ final String cod = StringUtils.defaultString(deviceCode);
+
+ final Parameters params = new Parameters("name", nam, "code", cod);
+ HttpResponse response = Network.getRequest("http://send2.cgeo.org/auth.html", params);
+
+ if (response != null && response.getStatusLine().getStatusCode() == 200) {
+ //response was OK
+ String[] strings = Network.getResponseData(response).split(",");
+ try {
+ pin = Integer.parseInt(strings[1].trim());
+ } catch (Exception e) {
+ Log.e("webDialog", e);
+ }
+ String code = strings[0];
+ Settings.setWebNameCode(nam, code);
+ }
+
+ webAuthHandler.sendEmptyMessage(pin);
+ }
+ }).start();
+
+ return true;
+ }
+ });
+ return super.onCreateView(parent);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java
new file mode 100644
index 0000000..08f30af
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/Settings.java
@@ -0,0 +1,967 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.StoredList;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum;
+import cgeo.geocaching.connector.gc.GCConstants;
+import cgeo.geocaching.connector.gc.Login;
+import cgeo.geocaching.enumerations.CacheType;
+import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy;
+import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.maps.MapProviderFactory;
+import cgeo.geocaching.maps.google.GoogleMapProvider;
+import cgeo.geocaching.maps.interfaces.GeoPointImpl;
+import cgeo.geocaching.maps.interfaces.MapProvider;
+import cgeo.geocaching.maps.interfaces.MapSource;
+import cgeo.geocaching.maps.mapsforge.MapsforgeMapProvider;
+import cgeo.geocaching.maps.mapsforge.MapsforgeMapProvider.OfflineMapSource;
+import cgeo.geocaching.utils.CryptUtils;
+import cgeo.geocaching.utils.FileUtils;
+import cgeo.geocaching.utils.FileUtils.FileSelector;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Environment;
+import android.preference.PreferenceManager;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * General c:geo preferences/settings set by the user
+ */
+public final class Settings {
+
+ public static final int SHOW_WP_THRESHOLD_DEFAULT = 5;
+ public static final int SHOW_WP_THRESHOLD_MAX = 50;
+ private static final int MAP_SOURCE_DEFAULT = GoogleMapProvider.GOOGLE_MAP_ID.hashCode();
+
+ private final static int unitsMetric = 1;
+
+ // twitter api keys
+ private final static String keyConsumerPublic = CryptUtils.rot13("ESnsCvAv3kEupF1GCR3jGj");
+ private final static String keyConsumerSecret = CryptUtils.rot13("7vQWceACV9umEjJucmlpFe9FCMZSeqIqfkQ2BnhV9x");
+
+ public enum coordInputFormatEnum {
+ Plain,
+ Deg,
+ Min,
+ Sec;
+
+ public static coordInputFormatEnum fromInt(int id) {
+ final coordInputFormatEnum[] values = coordInputFormatEnum.values();
+ if (id < 0 || id >= values.length) {
+ return Min;
+ }
+ return values[id];
+ }
+ }
+
+ private static final SharedPreferences sharedPrefs = PreferenceManager
+ .getDefaultSharedPreferences(cgeoapplication.getInstance().getBaseContext());
+ static {
+ migrateSettings();
+ Log.setDebug(sharedPrefs.getBoolean(getKey(R.string.pref_debug), false));
+ }
+
+ // maps
+ private static MapProvider mapProvider = null;
+
+ private Settings() {
+ // this class is not to be instantiated;
+ }
+
+ private static void migrateSettings() {
+ // migrate from non standard file location and integer based boolean types
+ int oldVersion = getInt(R.string.pref_settingsversion, 0);
+ if (oldVersion < 1) {
+ final String oldPreferencesName = "cgeo.pref";
+ final SharedPreferences old = cgeoapplication.getInstance().getSharedPreferences(oldPreferencesName, Context.MODE_PRIVATE);
+ final Editor e = sharedPrefs.edit();
+
+ e.putString(getKey(R.string.pref_temp_twitter_token_secret), old.getString(getKey(R.string.pref_temp_twitter_token_secret), null));
+ e.putString(getKey(R.string.pref_temp_twitter_token_public), old.getString(getKey(R.string.pref_temp_twitter_token_public), null));
+ e.putBoolean(getKey(R.string.pref_help_shown), old.getInt(getKey(R.string.pref_help_shown), 0) != 0);
+ e.putFloat(getKey(R.string.pref_anylongitude), old.getFloat(getKey(R.string.pref_anylongitude), 0));
+ e.putFloat(getKey(R.string.pref_anylatitude), old.getFloat(getKey(R.string.pref_anylatitude), 0));
+ e.putBoolean(getKey(R.string.pref_offlinemaps), 0 != old.getInt(getKey(R.string.pref_offlinemaps), 1));
+ e.putBoolean(getKey(R.string.pref_offlinewpmaps), 0 != old.getInt(getKey(R.string.pref_offlinewpmaps), 0));
+ e.putString(getKey(R.string.pref_webDeviceCode), old.getString(getKey(R.string.pref_webDeviceCode), null));
+ e.putString(getKey(R.string.pref_webDeviceName), old.getString(getKey(R.string.pref_webDeviceName), null));
+ e.putBoolean(getKey(R.string.pref_maplive), old.getInt(getKey(R.string.pref_maplive), 1) != 0);
+ e.putInt(getKey(R.string.pref_mapsource), old.getInt(getKey(R.string.pref_mapsource), MAP_SOURCE_DEFAULT));
+ e.putBoolean(getKey(R.string.pref_twitter), 0 != old.getInt(getKey(R.string.pref_twitter), 0));
+ e.putBoolean(getKey(R.string.pref_showaddress), 0 != old.getInt(getKey(R.string.pref_showaddress), 1));
+ e.putBoolean(getKey(R.string.pref_showcaptcha), old.getBoolean(getKey(R.string.pref_showcaptcha), false));
+ e.putBoolean(getKey(R.string.pref_maptrail), old.getInt(getKey(R.string.pref_maptrail), 1) != 0);
+ e.putInt(getKey(R.string.pref_lastmapzoom), old.getInt(getKey(R.string.pref_lastmapzoom), 14));
+ e.putBoolean(getKey(R.string.pref_livelist), 0 != old.getInt(getKey(R.string.pref_livelist), 1));
+ e.putBoolean(getKey(R.string.pref_units), old.getInt(getKey(R.string.pref_units), unitsMetric) == unitsMetric);
+ e.putBoolean(getKey(R.string.pref_skin), old.getInt(getKey(R.string.pref_skin), 0) != 0);
+ e.putInt(getKey(R.string.pref_lastusedlist), old.getInt(getKey(R.string.pref_lastusedlist), StoredList.STANDARD_LIST_ID));
+ e.putString(getKey(R.string.pref_cachetype), old.getString(getKey(R.string.pref_cachetype), CacheType.ALL.id));
+ e.putString(getKey(R.string.pref_twitter_token_secret), old.getString(getKey(R.string.pref_twitter_token_secret), null));
+ e.putString(getKey(R.string.pref_twitter_token_public), old.getString(getKey(R.string.pref_twitter_token_public), null));
+ e.putInt(getKey(R.string.pref_version), old.getInt(getKey(R.string.pref_version), 0));
+ e.putBoolean(getKey(R.string.pref_autoloaddesc), 0 != old.getInt(getKey(R.string.pref_autoloaddesc), 1));
+ e.putBoolean(getKey(R.string.pref_ratingwanted), old.getBoolean(getKey(R.string.pref_ratingwanted), true));
+ e.putBoolean(getKey(R.string.pref_friendlogswanted), old.getBoolean(getKey(R.string.pref_friendlogswanted), true));
+ e.putBoolean(getKey(R.string.pref_useenglish), old.getBoolean(getKey(R.string.pref_useenglish), false));
+ e.putBoolean(getKey(R.string.pref_usecompass), 0 != old.getInt(getKey(R.string.pref_usecompass), 1));
+ e.putBoolean(getKey(R.string.pref_trackautovisit), old.getBoolean(getKey(R.string.pref_trackautovisit), false));
+ e.putBoolean(getKey(R.string.pref_sigautoinsert), old.getBoolean(getKey(R.string.pref_sigautoinsert), false));
+ e.putBoolean(getKey(R.string.pref_logimages), old.getBoolean(getKey(R.string.pref_logimages), false));
+ e.putBoolean(getKey(R.string.pref_excludedisabled), 0 != old.getInt(getKey(R.string.pref_excludedisabled), 0));
+ e.putBoolean(getKey(R.string.pref_excludemine), 0 != old.getInt(getKey(R.string.pref_excludemine), 0));
+ e.putString(getKey(R.string.pref_mapfile), old.getString(getKey(R.string.pref_mapfile), null));
+ e.putString(getKey(R.string.pref_signature), old.getString(getKey(R.string.pref_signature), null));
+ e.putString(getKey(R.string.pref_pass_vote), old.getString(getKey(R.string.pref_pass_vote), null));
+ e.putString(getKey(R.string.pref_password), old.getString(getKey(R.string.pref_password), null));
+ e.putString(getKey(R.string.pref_username), old.getString(getKey(R.string.pref_username), null));
+ e.putString(getKey(R.string.pref_memberstatus), old.getString(getKey(R.string.pref_memberstatus), ""));
+ e.putInt(getKey(R.string.pref_coordinputformat), old.getInt(getKey(R.string.pref_coordinputformat), 0));
+ e.putBoolean(getKey(R.string.pref_log_offline), old.getBoolean(getKey(R.string.pref_log_offline), false));
+ e.putBoolean(getKey(R.string.pref_choose_list), old.getBoolean(getKey(R.string.pref_choose_list), false));
+ e.putBoolean(getKey(R.string.pref_loaddirectionimg), old.getBoolean(getKey(R.string.pref_loaddirectionimg), true));
+ e.putString(getKey(R.string.pref_gccustomdate), old.getString(getKey(R.string.pref_gccustomdate), null));
+ e.putInt(getKey(R.string.pref_gcshowwaypointsthreshold), old.getInt(getKey(R.string.pref_gcshowwaypointsthreshold), 0));
+ e.putString(getKey(R.string.pref_cookiestore), old.getString(getKey(R.string.pref_cookiestore), null));
+ e.putBoolean(getKey(R.string.pref_opendetailslastpage), old.getBoolean(getKey(R.string.pref_opendetailslastpage), false));
+ e.putInt(getKey(R.string.pref_lastdetailspage), old.getInt(getKey(R.string.pref_lastdetailspage), 1));
+ e.putInt(getKey(R.string.pref_defaultNavigationTool), old.getInt(getKey(R.string.pref_defaultNavigationTool), NavigationAppsEnum.COMPASS.id));
+ e.putInt(getKey(R.string.pref_defaultNavigationTool2), old.getInt(getKey(R.string.pref_defaultNavigationTool2), NavigationAppsEnum.INTERNAL_MAP.id));
+ e.putInt(getKey(R.string.pref_livemapstrategy), old.getInt(getKey(R.string.pref_livemapstrategy), Strategy.AUTO.id));
+ e.putBoolean(getKey(R.string.pref_debug), old.getBoolean(getKey(R.string.pref_debug), false));
+ e.putBoolean(getKey(R.string.pref_hidelivemaphint), old.getInt(getKey(R.string.pref_hidelivemaphint), 0) != 0);
+ e.putInt(getKey(R.string.pref_livemaphintshowcount), old.getInt(getKey(R.string.pref_livemaphintshowcount), 0));
+
+ e.putInt(getKey(R.string.pref_settingsversion), 1); // mark migrated
+ e.commit();
+ }
+
+ // changes for new settings dialog
+ if (oldVersion < 2) {
+ final Editor e = sharedPrefs.edit();
+
+ e.putBoolean(getKey(R.string.pref_units), !isUseImperialUnits());
+
+ // show waypoints threshold now as a slider
+ int wpThreshold = getWayPointsThreshold();
+ if (wpThreshold < 0) {
+ wpThreshold = 0;
+ } else if (wpThreshold > SHOW_WP_THRESHOLD_MAX) {
+ wpThreshold = SHOW_WP_THRESHOLD_MAX;
+ }
+ e.putInt(getKey(R.string.pref_gcshowwaypointsthreshold), wpThreshold);
+
+ // KEY_MAP_SOURCE must be string, because it is the key for a ListPreference now
+ int ms = sharedPrefs.getInt(getKey(R.string.pref_mapsource), MAP_SOURCE_DEFAULT);
+ e.remove(getKey(R.string.pref_mapsource));
+ e.putString(getKey(R.string.pref_mapsource), String.valueOf(ms));
+
+ // navigation tool ids must be string, because ListPreference uses strings as keys
+ int dnt1 = sharedPrefs.getInt(getKey(R.string.pref_defaultNavigationTool), NavigationAppsEnum.COMPASS.id);
+ int dnt2 = sharedPrefs.getInt(getKey(R.string.pref_defaultNavigationTool2), NavigationAppsEnum.INTERNAL_MAP.id);
+ e.remove(getKey(R.string.pref_defaultNavigationTool));
+ e.remove(getKey(R.string.pref_defaultNavigationTool2));
+ e.putString(getKey(R.string.pref_defaultNavigationTool), String.valueOf(dnt1));
+ e.putString(getKey(R.string.pref_defaultNavigationTool2), String.valueOf(dnt2));
+
+ // defaults for gpx directories
+ e.putString(getKey(R.string.pref_gpxImportDir), getGpxImportDir());
+ e.putString(getKey(R.string.pref_gpxExportDir), getGpxExportDir());
+
+ e.putInt(getKey(R.string.pref_settingsversion), 2); // mark migrated
+ e.commit();
+ }
+ }
+
+ private static String getKey(final int prefKeyId) {
+ return cgeoapplication.getInstance().getString(prefKeyId);
+ }
+
+ static String getString(final int prefKeyId, final String defaultValue) {
+ return sharedPrefs.getString(getKey(prefKeyId), defaultValue);
+ }
+
+ private static int getInt(final int prefKeyId, final int defaultValue) {
+ return sharedPrefs.getInt(getKey(prefKeyId), defaultValue);
+ }
+
+ private static boolean getBoolean(final int prefKeyId, final boolean defaultValue) {
+ return sharedPrefs.getBoolean(getKey(prefKeyId), defaultValue);
+ }
+
+ private static float getFloat(final int prefKeyId, final float defaultValue) {
+ return sharedPrefs.getFloat(getKey(prefKeyId), defaultValue);
+ }
+
+ static boolean putString(final int prefKeyId, final String value) {
+ final SharedPreferences.Editor edit = sharedPrefs.edit();
+ edit.putString(getKey(prefKeyId), value);
+ return edit.commit();
+ }
+
+ private static boolean putBoolean(final int prefKeyId, final boolean value) {
+ final SharedPreferences.Editor edit = sharedPrefs.edit();
+ edit.putBoolean(getKey(prefKeyId), value);
+ return edit.commit();
+ }
+
+ private static boolean putInt(final int prefKeyId, final int value) {
+ final SharedPreferences.Editor edit = sharedPrefs.edit();
+ edit.putInt(getKey(prefKeyId), value);
+ return edit.commit();
+ }
+
+ private static boolean putFloat(final int prefKeyId, final float value) {
+ final SharedPreferences.Editor edit = sharedPrefs.edit();
+ edit.putFloat(getKey(prefKeyId), value);
+ return edit.commit();
+ }
+
+ private static boolean remove(final int prefKeyId) {
+ final SharedPreferences.Editor edit = sharedPrefs.edit();
+ edit.remove(getKey(prefKeyId));
+ return edit.commit();
+ }
+
+ private static boolean contains(final int prefKeyId) {
+ return sharedPrefs.contains(getKey(prefKeyId));
+ }
+
+ public static void setLanguage(boolean useEnglish) {
+ final Configuration config = new Configuration();
+ config.locale = useEnglish ? Locale.ENGLISH : Locale.getDefault();
+ final Resources resources = cgeoapplication.getInstance().getResources();
+ resources.updateConfiguration(config, resources.getDisplayMetrics());
+ }
+
+ public static boolean isLogin() {
+ final String preUsername = getString(R.string.pref_username, null);
+ final String prePassword = getString(R.string.pref_password, null);
+
+ return !StringUtils.isBlank(preUsername) && !StringUtils.isBlank(prePassword);
+ }
+
+ /**
+ * Get login and password information.
+ *
+ * @return a pair (login, password) or null if no valid information is stored
+ */
+ public static ImmutablePair<String, String> getGcLogin() {
+
+ final String username = getString(R.string.pref_username, null);
+ final String password = getString(R.string.pref_password, null);
+
+ if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
+ return null;
+ }
+
+ return new ImmutablePair<String, String>(username, password);
+ }
+
+ public static String getUsername() {
+ return getString(R.string.pref_username, null);
+ }
+
+ public static boolean isGCConnectorActive() {
+ return getBoolean(R.string.pref_connectorGCActive, true);
+ }
+
+ public static boolean isPremiumMember() {
+ // Basic Member, Premium Member, ???
+ String memberStatus = Settings.getMemberStatus();
+ if (memberStatus == null) {
+ return false;
+ }
+ return GCConstants.MEMBER_STATUS_PM.equalsIgnoreCase(memberStatus);
+ }
+
+ public static String getMemberStatus() {
+ return getString(R.string.pref_memberstatus, "");
+ }
+
+ public static boolean setMemberStatus(final String memberStatus) {
+ if (StringUtils.isBlank(memberStatus)) {
+ return remove(R.string.pref_memberstatus);
+ }
+ return putString(R.string.pref_memberstatus, memberStatus);
+ }
+
+ public static boolean isOCConnectorActive() {
+ return getBoolean(R.string.pref_connectorOCActive, false);
+ }
+
+ public static boolean setOCConnectorActive(final boolean isActive) {
+ return putBoolean(R.string.pref_connectorOCActive, isActive);
+ }
+
+ public static String getOCDETokenPublic() {
+ return getString(R.string.pref_ocde_tokenpublic, "");
+ }
+
+ public static String getOCDETokenSecret() {
+ return getString(R.string.pref_ocde_tokensecret, "");
+ }
+
+ public static void setOCDETokens(final String tokenPublic,
+ final String tokenSecret, boolean enableOcDe) {
+ putString(R.string.pref_ocde_tokenpublic, tokenPublic);
+ putString(R.string.pref_ocde_tokensecret, tokenSecret);
+ if (tokenPublic != null) {
+ remove(R.string.pref_temp_ocde_token_public);
+ remove(R.string.pref_temp_ocde_token_secret);
+ }
+ setOCConnectorActive(enableOcDe);
+ }
+
+ public static void setOCDETempTokens(final String tokenPublic, final String tokenSecret) {
+ putString(R.string.pref_temp_ocde_token_public, tokenPublic);
+ putString(R.string.pref_temp_ocde_token_secret, tokenSecret);
+ }
+
+ public static ImmutablePair<String, String> getTempOCDEToken() {
+ String tokenPublic = getString(R.string.pref_temp_ocde_token_public, null);
+ String tokenSecret = getString(R.string.pref_temp_ocde_token_secret, null);
+ return new ImmutablePair<String, String>(tokenPublic, tokenSecret);
+ }
+
+ public static boolean isGCvoteLogin() {
+ final String preUsername = getString(R.string.pref_username, null);
+ final String prePassword = getString(R.string.pref_pass_vote, null);
+
+ return !StringUtils.isBlank(preUsername) && !StringUtils.isBlank(prePassword);
+ }
+
+ public static ImmutablePair<String, String> getGCvoteLogin() {
+ final String username = getString(R.string.pref_username, null);
+ final String password = getString(R.string.pref_pass_vote, null);
+
+ if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
+ return null;
+ }
+
+ return new ImmutablePair<String, String>(username, password);
+ }
+
+ public static String getSignature() {
+ return getString(R.string.pref_signature, null);
+ }
+
+ public static boolean setCookieStore(final String cookies) {
+ if (StringUtils.isBlank(cookies)) {
+ // erase cookies
+ return remove(R.string.pref_cookiestore);
+ }
+ // save cookies
+ return putString(R.string.pref_cookiestore, cookies);
+ }
+
+ public static String getCookieStore() {
+ return getString(R.string.pref_cookiestore, null);
+ }
+
+ /**
+ * @param cacheType
+ * The cache type used for future filtering
+ */
+ public static void setCacheType(final CacheType cacheType) {
+ if (cacheType == null) {
+ remove(R.string.pref_cachetype);
+ } else {
+ putString(R.string.pref_cachetype, cacheType.id);
+ }
+ }
+
+ public static int getLastList() {
+ return getInt(R.string.pref_lastusedlist, StoredList.STANDARD_LIST_ID);
+ }
+
+ public static void saveLastList(final int listId) {
+ putInt(R.string.pref_lastusedlist, listId);
+ }
+
+ public static void setWebNameCode(final String name, final String code) {
+ putString(R.string.pref_webDeviceName, name);
+ putString(R.string.pref_webDeviceCode, code);
+ }
+
+ public static MapProvider getMapProvider() {
+ if (mapProvider == null) {
+ mapProvider = getMapSource().getMapProvider();
+ }
+ return mapProvider;
+ }
+
+ public static String getMapFile() {
+ return getString(R.string.pref_mapfile, null);
+ }
+
+ public static boolean setMapFile(final String mapFile) {
+ boolean result = putString(R.string.pref_mapfile, mapFile);
+ if (mapFile != null) {
+ setMapFileDirectory(new File(mapFile).getParent());
+ }
+ return result;
+ }
+
+ public static String getMapFileDirectory() {
+ final String mapDir = getString(R.string.pref_mapDirectory, null);
+ if (mapDir != null) {
+ return mapDir;
+ }
+ final String mapFile = getMapFile();
+ if (mapFile != null) {
+ return new File(mapFile).getParent();
+ }
+ return null;
+ }
+
+ public static boolean setMapFileDirectory(final String mapFileDirectory) {
+ boolean result = putString(R.string.pref_mapDirectory, mapFileDirectory);
+ MapsforgeMapProvider.getInstance().updateOfflineMaps();
+ return result;
+ }
+
+ public static boolean isValidMapFile() {
+ return isValidMapFile(getMapFile());
+ }
+
+ public static boolean isValidMapFile(final String mapFileIn) {
+ return MapsforgeMapProvider.isValidMapFile(mapFileIn);
+ }
+
+ public static coordInputFormatEnum getCoordInputFormat() {
+ return coordInputFormatEnum.fromInt(getInt(R.string.pref_coordinputformat, 0));
+ }
+
+ public static void setCoordInputFormat(final coordInputFormatEnum format) {
+ putInt(R.string.pref_coordinputformat, format.ordinal());
+ }
+
+ static void setLogOffline(final boolean offline) {
+ putBoolean(R.string.pref_log_offline, offline);
+ }
+
+ public static boolean getLogOffline() {
+ return getBoolean(R.string.pref_log_offline, false);
+ }
+
+ public static boolean getChooseList() {
+ return getBoolean(R.string.pref_choose_list, false);
+ }
+
+ public static boolean getLoadDirImg() {
+ return !isPremiumMember() && getBoolean(R.string.pref_loaddirectionimg, true);
+ }
+
+ public static void setGcCustomDate(final String format) {
+ putString(R.string.pref_gccustomdate, format);
+ }
+
+ /**
+ * @return User selected date format on GC.com
+ * @see Login#gcCustomDateFormats
+ */
+ public static String getGcCustomDate() {
+ return getString(R.string.pref_gccustomdate, null);
+ }
+
+ public static boolean isExcludeMyCaches() {
+ return getBoolean(R.string.pref_excludemine, false);
+ }
+
+ public static void setUseEnglish(final boolean english) {
+ putBoolean(R.string.pref_useenglish, english);
+ setLanguage(english);
+ }
+
+ public static boolean isUseEnglish() {
+ return getBoolean(R.string.pref_useenglish, false);
+ }
+
+ public static boolean isShowAddress() {
+ return getBoolean(R.string.pref_showaddress, true);
+ }
+
+ public static boolean isShowCaptcha() {
+ return !isPremiumMember() && getBoolean(R.string.pref_showcaptcha, false);
+ }
+
+ public static boolean isExcludeDisabledCaches() {
+ return getBoolean(R.string.pref_excludedisabled, false);
+ }
+
+ public static boolean isStoreOfflineMaps() {
+ return getBoolean(R.string.pref_offlinemaps, true);
+ }
+
+ public static boolean isStoreOfflineWpMaps() {
+ return getBoolean(R.string.pref_offlinewpmaps, false);
+ }
+
+ public static boolean isStoreLogImages() {
+ return getBoolean(R.string.pref_logimages, false);
+ }
+
+ public static boolean isAutoLoadDescription() {
+ return getBoolean(R.string.pref_autoloaddesc, true);
+ }
+
+ public static boolean isRatingWanted() {
+ return getBoolean(R.string.pref_ratingwanted, true);
+ }
+
+ public static boolean isFriendLogsWanted() {
+ if (!isLogin()) {
+ // don't show a friends log if the user is anonymous
+ return false;
+ }
+ return getBoolean(R.string.pref_friendlogswanted, true);
+ }
+
+ public static boolean isLiveList() {
+ return getBoolean(R.string.pref_livelist, true);
+ }
+
+ public static boolean isTrackableAutoVisit() {
+ return getBoolean(R.string.pref_trackautovisit, false);
+ }
+
+ public static boolean isAutoInsertSignature() {
+ return getBoolean(R.string.pref_sigautoinsert, false);
+ }
+
+ public static boolean isUseImperialUnits() {
+ return getBoolean(R.string.pref_units, false);
+ }
+
+ public static boolean isLiveMap() {
+ return getBoolean(R.string.pref_maplive, true);
+ }
+
+ public static void setLiveMap(final boolean live) {
+ putBoolean(R.string.pref_maplive, live);
+ }
+
+ public static boolean isMapTrail() {
+ return getBoolean(R.string.pref_maptrail, true);
+ }
+
+ public static void setMapTrail(final boolean showTrail) {
+ putBoolean(R.string.pref_maptrail, showTrail);
+ }
+
+ public static int getMapZoom() {
+ return getInt(R.string.pref_lastmapzoom, 14);
+ }
+
+ public static void setMapZoom(final int mapZoomLevel) {
+ putInt(R.string.pref_lastmapzoom, mapZoomLevel);
+ }
+
+ public static GeoPointImpl getMapCenter() {
+ return getMapProvider().getMapItemFactory()
+ .getGeoPointBase(new Geopoint(getInt(R.string.pref_lastmaplat, 0) / 1e6,
+ getInt(R.string.pref_lastmaplon, 0) / 1e6));
+ }
+
+ public static void setMapCenter(final GeoPointImpl mapViewCenter) {
+ putInt(R.string.pref_lastmaplat, mapViewCenter.getLatitudeE6());
+ putInt(R.string.pref_lastmaplon, mapViewCenter.getLongitudeE6());
+ }
+
+ public static MapSource getMapSource() {
+ final int id = getConvertedMapId();
+ final MapSource map = MapProviderFactory.getMapSource(id);
+ if (map != null) {
+ // don't use offline maps if the map file is not valid
+ if ((!(map instanceof OfflineMapSource)) || (isValidMapFile())) {
+ return map;
+ }
+ }
+ // fallback to first available map
+ return MapProviderFactory.getDefaultSource();
+ }
+
+ private final static int GOOGLEMAP_BASEID = 30;
+ private final static int MAP = 1;
+ private final static int SATELLITE = 2;
+
+ private final static int MFMAP_BASEID = 40;
+ private final static int MAPNIK = 1;
+ private final static int CYCLEMAP = 3;
+ private final static int OFFLINE = 4;
+
+ /**
+ * convert old preference ids for maps (based on constant values) into new hash based ids
+ *
+ * @return
+ */
+ private static int getConvertedMapId() {
+ // what the heck is happening here?? hashCodes of Strings?
+ // why not strings?
+ final int id = Integer.parseInt(getString(R.string.pref_mapsource,
+ String.valueOf(MAP_SOURCE_DEFAULT)));
+ switch (id) {
+ case GOOGLEMAP_BASEID + MAP:
+ return GoogleMapProvider.GOOGLE_MAP_ID.hashCode();
+ case GOOGLEMAP_BASEID + SATELLITE:
+ return GoogleMapProvider.GOOGLE_SATELLITE_ID.hashCode();
+ case MFMAP_BASEID + MAPNIK:
+ return MapsforgeMapProvider.MAPSFORGE_MAPNIK_ID.hashCode();
+ case MFMAP_BASEID + CYCLEMAP:
+ return MapsforgeMapProvider.MAPSFORGE_CYCLEMAP_ID.hashCode();
+ case MFMAP_BASEID + OFFLINE: {
+ final String mapFile = Settings.getMapFile();
+ if (StringUtils.isNotEmpty(mapFile)) {
+ return mapFile.hashCode();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return id;
+ }
+
+ public static void setMapSource(final MapSource newMapSource) {
+ if (!MapProviderFactory.isSameActivity(getMapSource(), newMapSource)) {
+ mapProvider = null;
+ }
+ putString(R.string.pref_mapsource, String.valueOf(newMapSource.getNumericalId()));
+ if (newMapSource instanceof OfflineMapSource) {
+ setMapFile(((OfflineMapSource) newMapSource).getFileName());
+ }
+ }
+
+ public static void setAnyCoordinates(final Geopoint coords) {
+ if (null != coords) {
+ putFloat(R.string.pref_anylatitude, (float) coords.getLatitude());
+ putFloat(R.string.pref_anylatitude, (float) coords.getLongitude());
+ } else {
+ remove(R.string.pref_anylatitude);
+ remove(R.string.pref_anylongitude);
+ }
+ }
+
+ public static Geopoint getAnyCoordinates() {
+ if (contains(R.string.pref_anylatitude) && contains(R.string.pref_anylongitude)) {
+ float lat = getFloat(R.string.pref_anylatitude, 0);
+ float lon = getFloat(R.string.pref_anylongitude, 0);
+ return new Geopoint(lat, lon);
+ }
+ return null;
+ }
+
+ public static boolean isUseCompass() {
+ return getBoolean(R.string.pref_usecompass, true);
+ }
+
+ public static void setUseCompass(final boolean useCompass) {
+ putBoolean(R.string.pref_usecompass, useCompass);
+ }
+
+ public static boolean isLightSkin() {
+ return getBoolean(R.string.pref_skin, false);
+ }
+
+ public static String getKeyConsumerPublic() {
+ return keyConsumerPublic;
+ }
+
+ public static String getKeyConsumerSecret() {
+ return keyConsumerSecret;
+ }
+
+ public static String getWebDeviceCode() {
+ return getString(R.string.pref_webDeviceCode, null);
+ }
+
+ public static String getWebDeviceName() {
+ return getString(R.string.pref_webDeviceName, android.os.Build.MODEL);
+ }
+
+ /**
+ * @return The cache type used for filtering or ALL if no filter is active.
+ * Returns never null
+ */
+ public static CacheType getCacheType() {
+ return CacheType.getById(getString(R.string.pref_cachetype, CacheType.ALL.id));
+ }
+
+ /**
+ * The Threshold for the showing of child waypoints
+ */
+ public static int getWayPointsThreshold() {
+ return getInt(R.string.pref_gcshowwaypointsthreshold, SHOW_WP_THRESHOLD_DEFAULT);
+ }
+
+ public static void setShowWaypointsThreshold(final int threshold) {
+ putInt(R.string.pref_gcshowwaypointsthreshold, threshold);
+ }
+
+ public static boolean isUseTwitter() {
+ return getBoolean(R.string.pref_twitter, false);
+ }
+
+ public static void setUseTwitter(final boolean useTwitter) {
+ putBoolean(R.string.pref_twitter, useTwitter);
+ }
+
+ public static boolean isTwitterLoginValid() {
+ return !StringUtils.isBlank(getTokenPublic())
+ && !StringUtils.isBlank(getTokenSecret());
+ }
+
+ public static String getTokenPublic() {
+ return getString(R.string.pref_twitter_token_public, null);
+ }
+
+ public static String getTokenSecret() {
+ return getString(R.string.pref_twitter_token_secret, null);
+
+ }
+
+ public static void setTwitterTokens(final String tokenPublic,
+ final String tokenSecret, boolean enableTwitter) {
+ putString(R.string.pref_twitter_token_public, tokenPublic);
+ putString(R.string.pref_twitter_token_secret, tokenSecret);
+ if (tokenPublic != null) {
+ remove(R.string.pref_temp_twitter_token_public);
+ remove(R.string.pref_temp_twitter_token_secret);
+ }
+ setUseTwitter(enableTwitter);
+ }
+
+ public static void setTwitterTempTokens(final String tokenPublic,
+ final String tokenSecret) {
+ putString(R.string.pref_temp_twitter_token_public, tokenPublic);
+ putString(R.string.pref_temp_twitter_token_secret, tokenSecret);
+ }
+
+ public static ImmutablePair<String, String> getTempToken() {
+ String tokenPublic = getString(R.string.pref_twitter_token_public, null);
+ String tokenSecret = getString(R.string.pref_temp_twitter_token_secret, null);
+ return new ImmutablePair<String, String>(tokenPublic, tokenSecret);
+ }
+
+ public static int getVersion() {
+ return getInt(R.string.pref_version, 0);
+ }
+
+ public static void setVersion(final int version) {
+ putInt(R.string.pref_version, version);
+ }
+
+ public static boolean isOpenLastDetailsPage() {
+ return getBoolean(R.string.pref_opendetailslastpage, false);
+ }
+
+ public static int getLastDetailsPage() {
+ return getInt(R.string.pref_lastdetailspage, 1);
+ }
+
+ public static void setLastDetailsPage(final int index) {
+ putInt(R.string.pref_lastdetailspage, index);
+ }
+
+ public static int getDefaultNavigationTool() {
+ return Integer.parseInt(getString(
+ R.string.pref_defaultNavigationTool,
+ String.valueOf(NavigationAppsEnum.COMPASS.id)));
+ }
+
+ public static void setDefaultNavigationTool(final int defaultNavigationTool) {
+ putString(R.string.pref_defaultNavigationTool,
+ String.valueOf(defaultNavigationTool));
+ }
+
+ public static int getDefaultNavigationTool2() {
+ return Integer.parseInt(getString(
+ R.string.pref_defaultNavigationTool2,
+ String.valueOf(NavigationAppsEnum.INTERNAL_MAP.id)));
+ }
+
+ public static void setDefaultNavigationTool2(final int defaultNavigationTool) {
+ putString(R.string.pref_defaultNavigationTool2,
+ String.valueOf(defaultNavigationTool));
+ }
+
+ public static Strategy getLiveMapStrategy() {
+ return Strategy.getById(getInt(R.string.pref_livemapstrategy, Strategy.AUTO.id));
+ }
+
+ public static void setLiveMapStrategy(final Strategy strategy) {
+ putInt(R.string.pref_livemapstrategy, strategy.id);
+ }
+
+ public static boolean isDebug() {
+ return Log.isDebug();
+ }
+
+ public static boolean getHideLiveMapHint() {
+ return getBoolean(R.string.pref_hidelivemaphint, false);
+ }
+
+ public static void setHideLiveHint(final boolean hide) {
+ putBoolean(R.string.pref_hidelivemaphint, hide);
+ }
+
+ public static int getLiveMapHintShowCount() {
+ return getInt(R.string.pref_livemaphintshowcount, 0);
+ }
+
+ public static void setLiveMapHintShowCount(final int showCount) {
+ putInt(R.string.pref_livemaphintshowcount, showCount);
+ }
+
+ public static boolean isDbOnSDCard() {
+ return getBoolean(R.string.pref_dbonsdcard, false);
+ }
+
+ public static void setDbOnSDCard(final boolean dbOnSDCard) {
+ putBoolean(R.string.pref_dbonsdcard, dbOnSDCard);
+ }
+
+ public static String getGpxExportDir() {
+ return getString(R.string.pref_gpxExportDir,
+ Environment.getExternalStorageDirectory().getPath() + "/gpx");
+ }
+
+ public static String getGpxImportDir() {
+ return getString(R.string.pref_gpxImportDir,
+ Environment.getExternalStorageDirectory().getPath() + "/gpx");
+ }
+
+ public static boolean getShareAfterExport() {
+ return getBoolean(R.string.pref_shareafterexport, true);
+ }
+
+ public static void setShareAfterExport(final boolean shareAfterExport) {
+ putBoolean(R.string.pref_shareafterexport, shareAfterExport);
+ }
+
+ public static int getTrackableAction() {
+ return getInt(R.string.pref_trackableaction, LogType.RETRIEVED_IT.id);
+ }
+
+ public static void setTrackableAction(final int trackableAction) {
+ putInt(R.string.pref_trackableaction, trackableAction);
+ }
+
+ public static String getCustomRenderThemeBaseFolder() {
+ return getString(R.string.pref_renderthemepath, "");
+ }
+
+ public static String getCustomRenderThemeFilePath() {
+ return getString(R.string.pref_renderthemefile, "");
+ }
+
+ public static void setCustomRenderThemeFile(final String customRenderThemeFile) {
+ putString(R.string.pref_renderthemefile, customRenderThemeFile);
+ }
+
+ public static File[] getMapThemeFiles() {
+ File directory = new File(Settings.getCustomRenderThemeBaseFolder());
+ List<File> result = new ArrayList<File>();
+ FileUtils.listDir(result, directory, new ExtensionsBasedFileSelector(new String[] { "xml" }), null);
+
+ return result.toArray(new File[result.size()]);
+ }
+
+ private static class ExtensionsBasedFileSelector extends FileSelector {
+ private final String[] extensions;
+ public ExtensionsBasedFileSelector(String[] extensions) {
+ this.extensions = extensions;
+ }
+ @Override
+ public boolean isSelected(File file) {
+ String filename = file.getName();
+ for (String ext : extensions) {
+ if (StringUtils.endsWithIgnoreCase(filename, ext)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ @Override
+ public boolean shouldEnd() {
+ return false;
+ }
+ }
+
+ public static boolean getPlainLogs() {
+ return getBoolean(R.string.pref_plainLogs, false);
+ }
+
+ public static boolean getUseNativeUa() {
+ return getBoolean(R.string.pref_nativeUa, false);
+ }
+
+ public static String getCacheTwitterMessage() {
+ // TODO make customizable from UI
+ return "I found [NAME] ([URL])";
+ }
+
+ public static String getTrackableTwitterMessage() {
+ // TODO make customizable from UI
+ return "I touched [NAME] ([URL])!";
+ }
+
+ public static int getLogImageScale() {
+ return getInt(R.string.pref_logImageScale, -1);
+ }
+
+ public static void setLogImageScale(final int scale) {
+ putInt(R.string.pref_logImageScale, scale);
+ }
+
+ // Only for tests!
+ static void setExcludeDisabledCaches(final boolean exclude) {
+ putBoolean(R.string.pref_excludedisabled, exclude);
+ }
+
+ static void setExcludeMine(final boolean exclude) {
+ putBoolean(R.string.pref_excludemine, exclude);
+ }
+
+ static boolean setLogin(final String username, final String password) {
+
+ if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
+ // erase username and password
+ boolean a = remove(R.string.pref_username);
+ boolean b = remove(R.string.pref_password);
+ return a && b;
+ }
+ // save username and password
+ boolean a = putString(R.string.pref_username, username);
+ boolean b = putString(R.string.pref_password, password);
+ return a && b;
+ }
+
+ static void setStoreOfflineMaps(final boolean offlineMaps) {
+ putBoolean(R.string.pref_offlinemaps, offlineMaps);
+ }
+
+ static void setStoreOfflineWpMaps(final boolean offlineWpMaps) {
+ putBoolean(R.string.pref_offlinewpmaps, offlineWpMaps);
+ }
+
+ static void setUseImperialUnits(final boolean imperial) {
+ putBoolean(R.string.pref_units, imperial);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java
new file mode 100644
index 0000000..b9035ec
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java
@@ -0,0 +1,532 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.Intents;
+import cgeo.geocaching.R;
+import cgeo.geocaching.SelectMapfileActivity;
+import cgeo.geocaching.cgData;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
+import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum;
+import cgeo.geocaching.compatibility.Compatibility;
+import cgeo.geocaching.files.SimpleDirChooser;
+import cgeo.geocaching.maps.MapProviderFactory;
+import cgeo.geocaching.maps.interfaces.MapSource;
+import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.LogTemplateProvider;
+import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate;
+
+import org.apache.commons.lang3.StringUtils;
+import org.openintents.intents.FileManagerIntents;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.View;
+import android.widget.EditText;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A {@link PreferenceActivity} that presents a set of application settings. On
+ * handset devices, settings are presented as a single list. On tablets,
+ * settings are split by category, with category headers shown to the left of
+ * the list of settings.
+ * <p>
+ * See <a href="http://developer.android.com/design/patterns/settings.html"> Android Design: Settings</a> for design
+ * guidelines and the <a href="http://developer.android.com/guide/topics/ui/settings.html">Settings API Guide</a> for
+ * more information on developing a Settings UI.
+ *
+ * @author koem (initial author)
+ */
+public class SettingsActivity extends PreferenceActivity {
+
+ private static final String INTENT_GOTO = "GOTO";
+ private static final int INTENT_GOTO_SERVICES = 1;
+
+ private static final int DIR_CHOOSER_MAPS_DIRECTORY_REQUEST = 4;
+
+ private EditText signatureText;
+
+ /**
+ * Enumeration for directory choosers. This is how we can retrieve information about the
+ * directory and preference key in onActivityResult() easily just by knowing
+ * the result code.
+ */
+ private enum DirChooserType {
+ GPX_IMPORT_DIR(1, R.string.pref_gpxImportDir,
+ Environment.getExternalStorageDirectory().getPath() + "/gpx"),
+ GPX_EXPORT_DIR(2, R.string.pref_gpxExportDir,
+ Environment.getExternalStorageDirectory().getPath() + "/gpx"),
+ THEMES_DIR(3, R.string.pref_renderthemepath, "");
+ public final int requestCode;
+ public final int keyId;
+ public final String defaultValue;
+
+ DirChooserType(final int requestCode, final int keyId, final String defaultValue) {
+ this.requestCode = requestCode;
+ this.keyId = keyId;
+ this.defaultValue = defaultValue;
+ }
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+
+ if (Settings.isLightSkin()) {
+ setTheme(R.style.settings_light);
+ } else {
+ setTheme(R.style.settings);
+ }
+
+ super.onCreate(savedInstanceState);
+
+ SettingsActivity.addPreferencesFromResource(this, R.xml.preferences);
+
+ initPreferences();
+
+ Intent intent = getIntent();
+ int gotoPage = intent.getIntExtra(INTENT_GOTO, 0);
+ if (gotoPage == INTENT_GOTO_SERVICES) {
+ // start with services screen
+ PreferenceScreen main = (PreferenceScreen) SettingsActivity.findPreference(this, getKey(R.string.pref_fakekey_main_screen));
+ int index = SettingsActivity.findPreference(this, getKey(R.string.pref_fakekey_services_screen)).getOrder();
+ main.onItemClick(null, null, index, 0);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ Compatibility.dataChanged(getPackageName());
+ super.onPause();
+ }
+
+ private void initPreferences() {
+ initMapSourcePreference();
+ initDirChoosers();
+ initDefaultNavigationPreferences();
+ initBackupButtons();
+ initDbLocationPreference();
+ initDebugPreference();
+ initBasicMemberPreferences();
+ initSend2CgeoPreferences();
+
+ for (int k : new int[] { R.string.pref_username, R.string.pref_password,
+ R.string.pref_pass_vote, R.string.pref_signature,
+ R.string.pref_mapsource, R.string.pref_renderthemepath,
+ R.string.pref_gpxExportDir, R.string.pref_gpxImportDir,
+ R.string.pref_mapDirectory, R.string.pref_defaultNavigationTool,
+ R.string.pref_defaultNavigationTool2, R.string.pref_webDeviceName,
+ R.string.pref_fakekey_preference_backup_info, }) {
+ bindSummaryToStringValue(this, getKey(k));
+ }
+ }
+
+ private static String getKey(final int prefKeyId) {
+ return cgeoapplication.getInstance().getString(prefKeyId);
+ }
+
+ // workaround, because OnContextItemSelected nor onMenuItemSelected is never called
+ OnMenuItemClickListener TEMPLATE_CLICK = new OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(final MenuItem item) {
+ LogTemplate template = LogTemplateProvider.getTemplate(item.getItemId());
+ if (template != null) {
+ insertSignatureTemplate(template);
+ return true;
+ }
+ return false;
+ }
+ };
+
+ // workaround, because OnContextItemSelected nor onMenuItemSelected is never called
+ void setSignatureTextView(final EditText view) {
+ this.signatureText = view;
+ }
+
+ @Override
+ public void onCreateContextMenu(final ContextMenu menu, final View v,
+ final ContextMenuInfo menuInfo) {
+ // context menu for signature templates
+ if (v.getId() == R.id.signature_templates) {
+ menu.setHeaderTitle(R.string.init_signature_template_button);
+ ArrayList<LogTemplate> templates = LogTemplateProvider.getTemplates();
+ for (int i = 0; i < templates.size(); ++i) {
+ menu.add(0, templates.get(i).getItemId(), 0, templates.get(i).getResourceId());
+ menu.getItem(i).setOnMenuItemClickListener(TEMPLATE_CLICK);
+ }
+ }
+ super.onCreateContextMenu(menu, v, menuInfo);
+ }
+
+ private void insertSignatureTemplate(final LogTemplate template) {
+ String insertText = "[" + template.getTemplateString() + "]";
+ ActivityMixin.insertAtPosition(signatureText, insertText, true);
+ }
+
+ /**
+ * Fill the choice list for map sources.
+ */
+ private void initMapSourcePreference() {
+ ListPreference pref = (ListPreference) SettingsActivity.findPreference(this, getKey(R.string.pref_mapsource));
+
+ List<MapSource> mapSources = MapProviderFactory.getMapSources();
+ CharSequence[] entries = new CharSequence[mapSources.size()];
+ CharSequence[] values = new CharSequence[mapSources.size()];
+ for (int i = 0; i < mapSources.size(); ++i) {
+ entries[i] = mapSources.get(i).getName();
+ values[i] = String.valueOf(mapSources.get(i).getNumericalId());
+ }
+ pref.setEntries(entries);
+ pref.setEntryValues(values);
+ }
+
+ /**
+ * Fill the choice list for default navigation tools.
+ */
+ private void initDefaultNavigationPreferences() {
+
+ final List<NavigationAppsEnum> apps = NavigationAppFactory.getInstalledDefaultNavigationApps();
+
+ CharSequence[] entries = new CharSequence[apps.size()];
+ CharSequence[] values = new CharSequence[apps.size()];
+ for (int i = 0; i < apps.size(); ++i) {
+ entries[i] = apps.get(i).toString();
+ values[i] = String.valueOf(apps.get(i).id);
+ }
+
+ ListPreference pref = (ListPreference) SettingsActivity.findPreference(this, getKey(R.string.pref_defaultNavigationTool));
+ pref.setEntries(entries);
+ pref.setEntryValues(values);
+ pref = (ListPreference) SettingsActivity.findPreference(this, getKey(R.string.pref_defaultNavigationTool2));
+ pref.setEntries(entries);
+ pref.setEntryValues(values);
+ }
+
+ private void initDirChoosers() {
+ for (final DirChooserType dct : DirChooserType.values()) {
+
+ SettingsActivity.findPreference(this, getKey(dct.keyId)).setOnPreferenceClickListener(
+ new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ startDirChooser(dct);
+ return false;
+ }
+ });
+ }
+
+ SettingsActivity.findPreference(this, getKey(R.string.pref_mapDirectory)).setOnPreferenceClickListener(
+ new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ Intent i = new Intent(SettingsActivity.this,
+ SelectMapfileActivity.class);
+ startActivityForResult(i, DIR_CHOOSER_MAPS_DIRECTORY_REQUEST);
+ return false;
+ }
+ });
+ }
+
+ /**
+ * Fire up a directory chooser on click on the preference.
+ *
+ * @see #onActivityResult() for processing of the selected directory
+ *
+ * @param dct
+ * type of directory to be selected
+ */
+ private void startDirChooser(final DirChooserType dct) {
+
+ final String startDirectory = Settings.getString(dct.keyId, dct.defaultValue);
+
+ try {
+ final Intent dirChooser = new Intent(FileManagerIntents.ACTION_PICK_DIRECTORY);
+ if (StringUtils.isNotBlank(startDirectory)) {
+ dirChooser.setData(Uri.fromFile(new File(startDirectory)));
+ }
+ dirChooser.putExtra(FileManagerIntents.EXTRA_TITLE,
+ getString(R.string.simple_dir_chooser_title));
+ dirChooser.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT,
+ getString(android.R.string.ok));
+ startActivityForResult(dirChooser, dct.requestCode);
+ } catch (android.content.ActivityNotFoundException ex) {
+ // OI file manager not available
+ final Intent dirChooser = new Intent(this, SimpleDirChooser.class);
+ dirChooser.putExtra(Intents.EXTRA_START_DIR, startDirectory);
+ startActivityForResult(dirChooser, dct.requestCode);
+ }
+ }
+
+ private void setChosenDirectory(final DirChooserType dct, final Intent data) {
+ final String directory = new File(data.getData().getPath()).getAbsolutePath();
+ if (StringUtils.isNotBlank(directory)) {
+ Preference p = SettingsActivity.findPreference(this, getKey(dct.keyId));
+ if (p == null) {
+ return;
+ }
+ Settings.putString(dct.keyId, directory);
+ p.setSummary(directory);
+ }
+ }
+
+ public void initBackupButtons() {
+ Preference backup = SettingsActivity.findPreference(this, getKey(R.string.pref_fakekey_preference_backup));
+ backup.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ final Context context = preference.getContext();
+ // avoid overwriting an existing backup with an empty database
+ // (can happen directly after reinstalling the app)
+ if (cgData.getAllCachesCount() == 0) {
+ ActivityMixin.helpDialog(SettingsActivity.this,
+ context.getString(R.string.init_backup),
+ context.getString(R.string.init_backup_unnecessary));
+ return false;
+ }
+
+ final ProgressDialog dialog = ProgressDialog.show(context,
+ context.getString(R.string.init_backup),
+ context.getString(R.string.init_backup_running), true, false);
+ new Thread() {
+ @Override
+ public void run() {
+ final String backupFileName = cgData.backupDatabase();
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ dialog.dismiss();
+ ActivityMixin.helpDialog(SettingsActivity.this,
+ context.getString(R.string.init_backup_backup),
+ backupFileName != null
+ ? context.getString(R.string.init_backup_success)
+ + "\n" + backupFileName
+ : context.getString(R.string.init_backup_failed));
+ VALUE_CHANGE_LISTENER.onPreferenceChange(SettingsActivity.findPreference(SettingsActivity.this, getKey(R.string.pref_fakekey_preference_backup_info)), "");
+ }
+ });
+ }
+ }.start();
+ return true;
+ }
+ });
+
+ Preference restore = SettingsActivity.findPreference(this, getKey(R.string.pref_fakekey_preference_restore));
+ restore.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ ((cgeoapplication) SettingsActivity.this.getApplication())
+ .restoreDatabase(SettingsActivity.this);
+ return true;
+ }
+ });
+ }
+
+ private void initDbLocationPreference() {
+ Preference p = SettingsActivity.findPreference(this, getKey(R.string.pref_dbonsdcard));
+ p.setPersistent(false);
+ p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ boolean oldValue = Settings.isDbOnSDCard();
+ ((cgeoapplication) SettingsActivity.this.getApplication())
+ .moveDatabase(SettingsActivity.this);
+ return oldValue != Settings.isDbOnSDCard();
+ }
+ });
+ }
+
+ private void initDebugPreference() {
+ Preference p = SettingsActivity.findPreference(this, getKey(R.string.pref_debug));
+ p.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(final Preference preference, final Object newValue) {
+ Log.setDebug((Boolean) newValue);
+ return true;
+ }
+ });
+ }
+
+ private void initBasicMemberPreferences() {
+ SettingsActivity.findPreference(this, getKey(R.string.pref_loaddirectionimg)).setEnabled(
+ !Settings.isPremiumMember());
+ SettingsActivity.findPreference(this, getKey(R.string.pref_showcaptcha)).setEnabled(
+ !Settings.isPremiumMember());
+ }
+
+ private static void initSend2CgeoPreferences() {
+ Settings.putString(R.string.pref_webDeviceName, Settings.getWebDeviceName());
+ }
+
+ public static void startWithServicesPage(final Context fromActivity) {
+ final Intent intent = new Intent(fromActivity, SettingsActivity.class);
+ intent.putExtra(INTENT_GOTO, INTENT_GOTO_SERVICES);
+ fromActivity.startActivity(intent);
+ }
+
+ @Override
+ protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode != RESULT_OK) {
+ return;
+ }
+
+ for (DirChooserType dct : DirChooserType.values()) {
+ if (requestCode == dct.requestCode) {
+ setChosenDirectory(dct, data);
+ return;
+ }
+ }
+
+ switch (requestCode) {
+ case DIR_CHOOSER_MAPS_DIRECTORY_REQUEST:
+ if (data.hasExtra(Intents.EXTRA_MAP_FILE)) {
+ final String mapFile = data.getStringExtra(Intents.EXTRA_MAP_FILE);
+ Settings.setMapFile(mapFile);
+ if (!Settings.isValidMapFile(Settings.getMapFile())) {
+ ActivityMixin.showToast(this, R.string.warn_invalid_mapfile);
+ }
+ }
+ initMapSourcePreference();
+ SettingsActivity.findPreference(this, getKey(R.string.pref_mapDirectory)).setSummary(
+ Settings.getMapFileDirectory());
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * A preference value change listener that updates the preference's summary
+ * to reflect its new value.
+ */
+ private static final Preference.OnPreferenceChangeListener VALUE_CHANGE_LISTENER = new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(final Preference preference, final Object value) {
+ String stringValue = value.toString();
+
+ if (preference instanceof EditPasswordPreference) {
+ if (StringUtils.isBlank((String) value)) {
+ preference.setSummary("");
+ } else {
+ preference.setSummary("\u2022 \u2022 \u2022 \u2022 \u2022 \u2022 \u2022 \u2022 \u2022 \u2022");
+ }
+ } else if (preference instanceof ListPreference) {
+ // For list preferences, look up the correct display value in
+ // the preference's 'entries' list.
+ ListPreference listPreference = (ListPreference) preference;
+ int index = listPreference.findIndexOfValue(stringValue);
+
+ // Set the summary to reflect the new value.
+ preference.setSummary(
+ index >= 0
+ ? listPreference.getEntries()[index]
+ : null);
+ } else if (getKey(R.string.pref_fakekey_preference_backup_info).equals(preference.getKey())) {
+ File lastBackupFile = cgData.getRestoreFile();
+ String text;
+ if (lastBackupFile != null) {
+ text = preference.getContext().getString(R.string.init_backup_last) + " "
+ + Formatter.formatTime(lastBackupFile.lastModified())
+ + ", " + Formatter.formatDate(lastBackupFile.lastModified());
+ } else {
+ text = preference.getContext().getString(R.string.init_backup_last_no);
+ }
+ preference.setSummary(text);
+ } else {
+ // For all other preferences, set the summary to the value's
+ // simple string representation.
+ preference.setSummary(stringValue);
+ }
+ return true;
+ }
+ };
+
+ /**
+ * Binds a preference's summary to its value. More specifically, when the
+ * preference's value is changed, its summary (line of text below the
+ * preference title) is updated to reflect the value. The summary is also
+ * immediately updated upon calling this method. The exact display format is
+ * dependent on the type of preference.
+ *
+ * @see #VALUE_CHANGE_LISTENER
+ */
+ private static void bindSummaryToValue(final Preference preference, final Object value) {
+ // Set the listener to watch for value changes.
+ if (preference == null) {
+ return;
+ }
+ preference.setOnPreferenceChangeListener(VALUE_CHANGE_LISTENER);
+
+ // Trigger the listener immediately with the preference's
+ // current value.
+ VALUE_CHANGE_LISTENER.onPreferenceChange(preference, value);
+ }
+
+ /**
+ * auto-care for the summary of the preference of string type with this key
+ *
+ * @param key
+ */
+ private static void bindSummaryToStringValue(final PreferenceActivity preferenceActivity, final String key) {
+
+ Preference pref = findPreference(preferenceActivity, key);
+
+ if (pref == null) {
+ return;
+ }
+
+ String value = PreferenceManager
+ .getDefaultSharedPreferences(pref.getContext())
+ .getString(pref.getKey(), "");
+
+ bindSummaryToValue(pref, value);
+ }
+
+ /**
+ * auto-care for the summary of the preference of int type with this key
+ *
+ * @param key
+ */
+ private static void bindSummaryToIntValue(final PreferenceActivity preferenceActivity, final String key) {
+
+ Preference pref = findPreference(preferenceActivity, key);
+
+ if (pref == null) {
+ return;
+ }
+
+ int value = PreferenceManager
+ .getDefaultSharedPreferences(pref.getContext())
+ .getInt(pref.getKey(), 0);
+
+ bindSummaryToValue(pref, value);
+ }
+
+ @SuppressWarnings("deprecation")
+ public static Preference findPreference(final PreferenceActivity preferenceActivity, final CharSequence key) {
+ return preferenceActivity.findPreference(key);
+ }
+
+ @SuppressWarnings("deprecation")
+ public static void addPreferencesFromResource(final PreferenceActivity preferenceActivity, final int preferencesResId) {
+ preferenceActivity.addPreferencesFromResource(preferencesResId);
+ }
+}
diff --git a/main/src/cgeo/geocaching/settings/TextPreference.java b/main/src/cgeo/geocaching/settings/TextPreference.java
new file mode 100644
index 0000000..bcd03ff
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/TextPreference.java
@@ -0,0 +1,86 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * Preference to simply show a text message.
+ * <p>
+ * Links are not shown - I tried everything (koem)
+ * <p>
+ * example: <cgeo.geocaching.settings.TextPreference android:text="@string/legal_note"
+ * android:layout="@string/text_preference_default_layout" />
+ */
+public class TextPreference extends Preference {
+
+ private String text;
+ private TextView summaryView;
+ private CharSequence summaryText;
+
+ public TextPreference(Context context) {
+ super(context);
+ }
+
+ public TextPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ processAttributes(context, attrs, 0);
+ }
+
+ public TextPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ processAttributes(context, attrs, defStyle);
+ }
+
+ private void processAttributes(Context context, AttributeSet attrs, int defStyle) {
+ if (attrs == null) {
+ return;
+ }
+
+ TypedArray types = context.obtainStyledAttributes(attrs, new int[] {
+ android.R.attr.text }, defStyle, 0);
+ this.text = types.getString(0);
+ types.recycle();
+ }
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+ this.setSelectable(false);
+
+ View v = super.onCreateView(parent);
+
+ TextView text = (TextView) v.findViewById(R.id.textPreferenceText);
+ text.setText(this.text);
+
+ summaryView = (TextView) v.findViewById(R.id.textPreferenceSummary);
+ setSummary(null); // show saved summary text
+
+ return v;
+ }
+
+ @Override
+ public void setSummary(CharSequence summaryText) {
+ // the layout hasn't been inflated yet, save the summaryText for later use
+ if (this.summaryView == null) {
+ this.summaryText = summaryText;
+ return;
+ }
+
+ // if summaryText is null, take it from the previous saved summary
+ if (summaryText == null) {
+ if (this.summaryText == null) {
+ return;
+ }
+ this.summaryView.setText(this.summaryText);
+ } else {
+ this.summaryView.setText(summaryText);
+ }
+ this.summaryView.setVisibility(View.VISIBLE);
+ }
+}
diff --git a/main/src/cgeo/geocaching/settings/WpThresholdPreference.java b/main/src/cgeo/geocaching/settings/WpThresholdPreference.java
new file mode 100644
index 0000000..867714f
--- /dev/null
+++ b/main/src/cgeo/geocaching/settings/WpThresholdPreference.java
@@ -0,0 +1,73 @@
+package cgeo.geocaching.settings;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.settings.Settings;
+
+import android.content.Context;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+public class WpThresholdPreference extends Preference {
+
+ TextView valueView;
+
+ public WpThresholdPreference(Context context) {
+ super(context);
+ init();
+ }
+
+ public WpThresholdPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public WpThresholdPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ setPersistent(false);
+ }
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+ View v = super.onCreateView(parent);
+
+ // get views
+ SeekBar seekBar = (SeekBar) v.findViewById(R.id.wp_threshold_seekbar);
+ valueView = (TextView) v.findViewById(R.id.wp_threshold_value_view);
+
+ // init seekbar
+ seekBar.setMax(Settings.SHOW_WP_THRESHOLD_MAX);
+
+ // set initial value
+ int threshold = Settings.getWayPointsThreshold();
+ valueView.setText(String.valueOf(threshold));
+ seekBar.setProgress(threshold);
+
+ seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ valueView.setText(String.valueOf(progress));
+ }
+ }
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ Settings.setShowWaypointsThreshold(seekBar.getProgress());
+ }
+ });
+
+ return v;
+ }
+
+}