diff options
Diffstat (limited to 'main/src/cgeo/geocaching/settings')
14 files changed, 3635 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..4edfd49 --- /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); + ((Activity) 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..9476e37 --- /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); + ((Activity) 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..c2fac6a --- /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 NewSettingsActivity - 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..2fdd5ac --- /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 NewSettingsActivity 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 = (NewSettingsActivity) 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/NewSettingsActivity.java b/main/src/cgeo/geocaching/settings/NewSettingsActivity.java new file mode 100644 index 0000000..bf4ad01 --- /dev/null +++ b/main/src/cgeo/geocaching/settings/NewSettingsActivity.java @@ -0,0 +1,524 @@ +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.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 NewSettingsActivity extends PreferenceActivity { + + private static final String INTENT_GOTO = "GOTO"; + private static final int INTENT_GOTO_SERVICES = 1; + private static final String FAKEKEY_MAIN_SCREEN = "fakekey_main_screen"; + private static final String FAKEKEY_SERVICES_SCREEN = "fakekey_services_screen"; + + private EditText signatureText; + + /** + * Enum for dir 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, Settings.KEY_GPX_IMPORT_DIR, + Environment.getExternalStorageDirectory().getPath() + "/gpx"), + GPX_EXPORT_DIR(2, Settings.KEY_GPX_EXPORT_DIR, + Environment.getExternalStorageDirectory().getPath() + "/gpx"), + THEMES_DIR(3, Settings.KEY_RENDER_THEME_BASE_FOLDER, ""); + public final int requestCode; + public final String key; + public final String defaultValue; + + private DirChooserType(int requestCode, String key, String defaultValue) { + this.requestCode = requestCode; + this.key = key; + this.defaultValue = defaultValue; + } + } + + private final static int DIR_CHOOSER_MAPS_DIRECTORY_REQUEST = 4; + + @SuppressWarnings("deprecation") + @Override + protected void onCreate(Bundle savedInstanceState) { + + if (Settings.isLightSkin()) { + setTheme(R.style.settings_light); + } else { + setTheme(R.style.settings); + } + + super.onCreate(savedInstanceState); + + addPreferencesFromResource(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) findPreference(FAKEKEY_MAIN_SCREEN); + int index = findPreference(FAKEKEY_SERVICES_SCREEN).getOrder(); + main.onItemClick(null, null, index, 0); + } + } + + private void initPreferences() { + initMapSourcePreference(); + initDirChoosers(); + initDefaultNavigationPreferences(); + initBackupButtons(); + initDbLocationPreference(); + initDebugPreference(); + initBasicMemberPreferences(); + initSend2CgeoPreferences(); + + for (String k : new String[] { Settings.KEY_USERNAME, Settings.KEY_PASSWORD, + Settings.KEY_GCVOTE_PASSWORD, Settings.KEY_SIGNATURE, + Settings.KEY_MAP_SOURCE, Settings.KEY_RENDER_THEME_BASE_FOLDER, + Settings.KEY_GPX_EXPORT_DIR, Settings.KEY_GPX_IMPORT_DIR, + Settings.KEY_MAP_DIRECTORY, Settings.KEY_DEFAULT_NAVIGATION_TOOL, + Settings.KEY_DEFAULT_NAVIGATION_TOOL_2, Settings.KEY_WEBDEVICE_NAME, + Settings.FAKEKEY_PREFERENCE_BACKUP_INFO, }) { + bindSummaryToStringValue(k); + } + bindSummaryToIntValue(Settings.KEY_ALTITUDE_CORRECTION); + } + + // workaround, because OnContextItemSelected nor onMenuItemSelected is never called + OnMenuItemClickListener TEMPLATE_CLICK = new OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(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(EditText view) { + this.signatureText = view; + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + 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 + */ + @SuppressWarnings("deprecation") + private void initMapSourcePreference() { + ListPreference pref = (ListPreference) findPreference(Settings.KEY_MAP_SOURCE); + + 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 + */ + @SuppressWarnings("deprecation") + 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) findPreference(Settings.KEY_DEFAULT_NAVIGATION_TOOL); + pref.setEntries(entries); + pref.setEntryValues(values); + pref = (ListPreference) findPreference(Settings.KEY_DEFAULT_NAVIGATION_TOOL_2); + pref.setEntries(entries); + pref.setEntryValues(values); + } + + /** + * fire up a dir chooser on click on the preference + * + * @see #onActivityResult() for processing of the selected directory + * + * @param key + * key of the preference + * @param defaultValue + * default directory - in case the preference has never been + * set yet + */ + @SuppressWarnings("deprecation") + private void initDirChoosers() { + for (final DirChooserType dct : DirChooserType.values()) { + final String dir = Settings.getString(dct.key, dct.defaultValue); + + findPreference(dct.key).setOnPreferenceClickListener( + new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + startDirChooser(dct, dir); + return false; + } + }); + } + + findPreference(Settings.KEY_MAP_DIRECTORY).setOnPreferenceClickListener( + new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + Intent i = new Intent(NewSettingsActivity.this, + SelectMapfileActivity.class); + startActivityForResult(i, DIR_CHOOSER_MAPS_DIRECTORY_REQUEST); + return false; + } + }); + } + + private void startDirChooser(DirChooserType dct, String startDirectory) { + 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); + } + } + + @SuppressWarnings("deprecation") + private void setChosenDirectory(DirChooserType dct, Intent data) { + final String directory = new File(data.getData().getPath()).getAbsolutePath(); + if (StringUtils.isNotBlank(directory)) { + Preference p = findPreference(dct.key); + if (p == null) { + return; + } + Settings.putString(dct.key, directory); + p.setSummary(directory); + } + } + + @SuppressWarnings("deprecation") + public void initBackupButtons() { + Preference backup = findPreference(Settings.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(NewSettingsActivity.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(NewSettingsActivity.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(findPreference( + Settings.FAKEKEY_PREFERENCE_BACKUP_INFO), ""); + } + }); + } + }.start(); + return true; + } + }); + + Preference restore = findPreference(Settings.FAKEKEY_PREFERENCE_RESTORE); + restore.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(final Preference preference) { + ((cgeoapplication) NewSettingsActivity.this.getApplication()) + .restoreDatabase(NewSettingsActivity.this); + return true; + } + }); + } + + @SuppressWarnings("deprecation") + private void initDbLocationPreference() { + Preference p = findPreference(Settings.KEY_DB_ON_SDCARD); + p.setPersistent(false); + p.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + boolean oldValue = Settings.isDbOnSDCard(); + ((cgeoapplication) NewSettingsActivity.this.getApplication()) + .moveDatabase(NewSettingsActivity.this); + return oldValue != Settings.isDbOnSDCard(); + } + }); + } + + @SuppressWarnings("deprecation") + private void initDebugPreference() { + Preference p = findPreference(Settings.KEY_DEBUG); + p.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + Log.setDebug((Boolean) newValue); + return true; + } + }); + } + + @SuppressWarnings("deprecation") + private void initBasicMemberPreferences() { + findPreference(Settings.KEY_LOAD_DIRECTION_IMG).setEnabled( + !Settings.isPremiumMember()); + findPreference(Settings.KEY_SHOW_CAPTCHA).setEnabled( + !Settings.isPremiumMember()); + } + + private static void initSend2CgeoPreferences() { + Settings.putString(Settings.KEY_WEBDEVICE_NAME, Settings.getWebDeviceName()); + } + + public static void startWithServicesPage(Context fromActivity) { + final Intent intent = new Intent(fromActivity, NewSettingsActivity.class); + intent.putExtra(INTENT_GOTO, INTENT_GOTO_SERVICES); + fromActivity.startActivity(intent); + } + + @SuppressWarnings("deprecation") + @Override + protected void onActivityResult(int requestCode, 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(); + findPreference(Settings.KEY_MAP_DIRECTORY).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 Preference.OnPreferenceChangeListener VALUE_CHANGE_LISTENER = new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, 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 (Settings.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(Preference preference, 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 + */ + @SuppressWarnings("deprecation") + private void bindSummaryToStringValue(String key) { + Preference p = findPreference(key); + if (p == null) { + return; + } + + String value = PreferenceManager + .getDefaultSharedPreferences(p.getContext()) + .getString(p.getKey(), ""); + + bindSummaryToValue(p, value); + } + + /** + * auto-care for the summary of the preference of int type with this key + * + * @param key + */ + @SuppressWarnings("deprecation") + private void bindSummaryToIntValue(String key) { + Preference p = findPreference(key); + if (p == null) { + return; + } + + int value = PreferenceManager + .getDefaultSharedPreferences(p.getContext()) + .getInt(p.getKey(), 0); + + bindSummaryToValue(p, value); + } +} diff --git a/main/src/cgeo/geocaching/settings/NumberPickerPreference.java b/main/src/cgeo/geocaching/settings/NumberPickerPreference.java new file mode 100644 index 0000000..273b7d3 --- /dev/null +++ b/main/src/cgeo/geocaching/settings/NumberPickerPreference.java @@ -0,0 +1,93 @@ +package cgeo.geocaching.settings; + +import cgeo.geocaching.R; + +import org.apache.commons.lang3.StringUtils; + +import android.content.Context; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +public class NumberPickerPreference extends DialogPreference { + + private EditText editText; + + public NumberPickerPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NumberPickerPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onBindDialogView(View view) { + String msg = (String) this.getDialogMessage(); + if (StringUtils.isNotBlank(msg)) { + TextView tv = (TextView) view.findViewById(R.id.number_picker_message); + tv.setText(msg); + } + + editText = (EditText) view.findViewById(R.id.number_picker_input); + setValue(getPersistedInt(0)); + + Button minus = (Button) view.findViewById(R.id.number_picker_minus); + Button plus = (Button) view.findViewById(R.id.number_picker_plus); + + minus.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View button) { + Integer value = getValue(); + if (value != null) { + setValue(--value); + } + } + }); + + plus.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View button) { + Integer value = getValue(); + if (value != null) { + setValue(++value); + } + } + }); + + super.onBindDialogView(view); + } + + private Integer getValue() { + try { + return Integer.parseInt(editText.getText().toString()); + } catch (NumberFormatException e) { + return null; + } + } + + private void setValue(final int value) { + int v = value; + if (v <= 0) { + v = 0; + } else if (v > Integer.MAX_VALUE) { + v = Integer.MAX_VALUE; + } + editText.setText(String.valueOf(v)); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + if (positiveResult) { + Integer value = getValue(); + if (value != null) { + persistInt(value); + callChangeListener(value); + } + } + 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..70c2c44 --- /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; + NewSettingsActivity 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 = (NewSettingsActivity) 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..2215d25 --- /dev/null +++ b/main/src/cgeo/geocaching/settings/Settings.java @@ -0,0 +1,1186 @@ +package cgeo.geocaching.settings; + +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 { + + private static final String KEY_TEMP_TWITTER_TOKEN_SECRET = "temp-token-secret"; + private static final String KEY_TEMP_TWITTER_TOKEN_PUBLIC = "temp-token-public"; + private static final String KEY_HELP_SHOWN = "helper"; + private static final String KEY_ANYLONGITUDE = "anylongitude"; + private static final String KEY_ANYLATITUDE = "anylatitude"; + private static final String KEY_USE_OFFLINEMAPS = "offlinemaps"; + private static final String KEY_USE_OFFLINEWPMAPS = "offlinewpmaps"; + private static final String KEY_WEB_DEVICE_CODE = "webDeviceCode"; + static final String KEY_WEBDEVICE_NAME = "webDeviceName"; + private static final String KEY_MAP_LIVE = "maplive"; + static final String KEY_MAP_SOURCE = "mapsource"; + private static final String KEY_USE_TWITTER = "twitter"; + private static final String KEY_SHOW_ADDRESS = "showaddress"; + static final String KEY_SHOW_CAPTCHA = "showcaptcha"; + private static final String KEY_MAP_TRAIL = "maptrail"; + private static final String KEY_LAST_MAP_ZOOM = "mapzoom"; + private static final String KEY_LAST_MAP_LAT = "maplat"; + private static final String KEY_LAST_MAP_LON = "maplon"; + private static final String KEY_LIVE_LIST = "livelist"; + private static final String KEY_IMPERIAL_UNITS = "units"; + private static final String KEY_SKIN = "skin"; + private static final String KEY_LAST_USED_LIST = "lastlist"; + private static final String KEY_CACHE_TYPE = "cachetype"; + private static final String KEY_TWITTER_TOKEN_SECRET = "tokensecret"; + private static final String KEY_TWITTER_TOKEN_PUBLIC = "tokenpublic"; + private static final String KEY_VERSION = "version"; + private static final String KEY_LOAD_DESCRIPTION = "autoloaddesc"; + private static final String KEY_RATING_WANTED = "ratingwanted"; + private static final String KEY_ELEVATION_WANTED = "elevationwanted"; + private static final String KEY_FRIENDLOGS_WANTED = "friendlogswanted"; + static final String KEY_USE_ENGLISH = "useenglish"; + private static final String KEY_USE_COMPASS = "usecompass"; + private static final String KEY_AUTO_VISIT_TRACKABLES = "trackautovisit"; + private static final String KEY_AUTO_INSERT_SIGNATURE = "sigautoinsert"; + static final String KEY_ALTITUDE_CORRECTION = "altcorrection"; + private static final String KEY_STORE_LOG_IMAGES = "logimages"; + private static final String KEY_EXCLUDE_DISABLED = "excludedisabled"; + private static final String KEY_EXCLUDE_OWN = "excludemine"; + private static final String KEY_MAPFILE = "mfmapfile"; + static final String KEY_SIGNATURE = "signature"; + static final String KEY_GCVOTE_PASSWORD = "pass-vote"; + static final String KEY_PASSWORD = "password"; + static final String KEY_USERNAME = "username"; + private static final String KEY_MEMBER_STATUS = "memberstatus"; + private static final String KEY_COORD_INPUT_FORMAT = "coordinputformat"; + private static final String KEY_LOG_OFFLINE = "log_offline"; + private static final String KEY_CHOOSE_LIST = "choose_list"; + static final String KEY_LOAD_DIRECTION_IMG = "loaddirectionimg"; + private static final String KEY_GC_CUSTOM_DATE = "gccustomdate"; + private static final String KEY_SHOW_WAYPOINTS_THRESHOLD = "gcshowwaypointsthreshold"; + private static final String KEY_COOKIE_STORE = "cookiestore"; + private static final String KEY_OPEN_LAST_DETAILS_PAGE = "opendetailslastpage"; + private static final String KEY_LAST_DETAILS_PAGE = "lastdetailspage"; + static final String KEY_DEFAULT_NAVIGATION_TOOL = "defaultNavigationTool"; + static final String KEY_DEFAULT_NAVIGATION_TOOL_2 = "defaultNavigationTool2"; + private static final String KEY_LIVE_MAP_STRATEGY = "livemapstrategy"; + static final String KEY_DEBUG = "debug"; + private static final String KEY_HIDE_LIVE_MAP_HINT = "hidelivemaphint"; + private static final String KEY_LIVE_MAP_HINT_SHOW_COUNT = "livemaphintshowcount"; + private static final String KEY_SETTINGS_VERSION = "settingsversion"; + static final String KEY_DB_ON_SDCARD = "dbonsdcard"; + private static final String KEY_LAST_TRACKABLE_ACTION = "trackableaction"; + private static final String KEY_SHARE_AFTER_EXPORT = "shareafterexport"; + public static final String KEY_RENDER_THEME_BASE_FOLDER = "renderthemepath"; + static final String KEY_RENDER_THEME_FILE_PATH = "renderthemefile"; + public static final String KEY_GPX_EXPORT_DIR = "gpxExportDir"; + public static final String KEY_GPX_IMPORT_DIR = "gpxImportDir"; + private static final String KEY_PLAIN_LOGS = "plainLogs"; + private static final String KEY_NATIVE_UA = "nativeUa"; + static final String KEY_MAP_DIRECTORY = "mapDirectory"; + private static final String KEY_CONNECTOR_GC_ACTIVE = "connectorGCActive"; + private static final String KEY_CONNECTOR_OC_ACTIVE = "connectorOCActive"; + private static final String KEY_LOG_IMAGE_SCALE = "logImageScale"; + private static final String KEY_OCDE_TOKEN_SECRET = "ocde_tokensecret"; + private static final String KEY_OCDE_TOKEN_PUBLIC = "ocde_tokenpublic"; + private static final String KEY_TEMP_OCDE_TOKEN_SECRET = "ocde-temp-token-secret"; + private static final String KEY_TEMP_OCDE_TOKEN_PUBLIC = "ocde-temp-token-public"; + + /* + * fake keys are for finding preference objects only, because preferences + * don't have an id. + */ + static final String FAKEKEY_PREFERENCE_BACKUP_INFO = "fakekey_preference_backup_info"; + static final String FAKEKEY_PREFERENCE_BACKUP = "fakekey_preference_backup"; + static final String FAKEKEY_PREFERENCE_RESTORE = "fakekey_preference_restore"; + + 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 String username = null; + private static String password = null; + + private static final SharedPreferences sharedPrefs = PreferenceManager + .getDefaultSharedPreferences(cgeoapplication.getInstance().getBaseContext()); + static { + migrateSettings(); + Log.setDebug(sharedPrefs.getBoolean(KEY_DEBUG, false)); + } + + // maps + private static MapProvider mapProvider = null; + private static String cacheTwitterMessage = "I found [NAME] ([URL])"; + + 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 = sharedPrefs.getInt(KEY_SETTINGS_VERSION, 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(KEY_TEMP_TWITTER_TOKEN_SECRET, old.getString(KEY_TEMP_TWITTER_TOKEN_SECRET, null)); + e.putString(KEY_TEMP_TWITTER_TOKEN_PUBLIC, old.getString(KEY_TEMP_TWITTER_TOKEN_PUBLIC, null)); + e.putBoolean(KEY_HELP_SHOWN, old.getInt(KEY_HELP_SHOWN, 0) != 0); + e.putFloat(KEY_ANYLONGITUDE, old.getFloat(KEY_ANYLONGITUDE, 0)); + e.putFloat(KEY_ANYLATITUDE, old.getFloat(KEY_ANYLATITUDE, 0)); + e.putBoolean(KEY_USE_OFFLINEMAPS, 0 != old.getInt(KEY_USE_OFFLINEMAPS, 1)); + e.putBoolean(KEY_USE_OFFLINEWPMAPS, 0 != old.getInt(KEY_USE_OFFLINEWPMAPS, 0)); + e.putString(KEY_WEB_DEVICE_CODE, old.getString(KEY_WEB_DEVICE_CODE, null)); + e.putString(KEY_WEBDEVICE_NAME, old.getString(KEY_WEBDEVICE_NAME, null)); + e.putBoolean(KEY_MAP_LIVE, old.getInt(KEY_MAP_LIVE, 1) != 0); + e.putInt(KEY_MAP_SOURCE, old.getInt(KEY_MAP_SOURCE, MAP_SOURCE_DEFAULT)); + e.putBoolean(KEY_USE_TWITTER, 0 != old.getInt(KEY_USE_TWITTER, 0)); + e.putBoolean(KEY_SHOW_ADDRESS, 0 != old.getInt(KEY_SHOW_ADDRESS, 1)); + e.putBoolean(KEY_SHOW_CAPTCHA, old.getBoolean(KEY_SHOW_CAPTCHA, false)); + e.putBoolean(KEY_MAP_TRAIL, old.getInt(KEY_MAP_TRAIL, 1) != 0); + e.putInt(KEY_LAST_MAP_ZOOM, old.getInt(KEY_LAST_MAP_ZOOM, 14)); + e.putBoolean(KEY_LIVE_LIST, 0 != old.getInt(KEY_LIVE_LIST, 1)); + e.putBoolean(KEY_IMPERIAL_UNITS, old.getInt(KEY_IMPERIAL_UNITS, unitsMetric) == unitsMetric); + e.putBoolean(KEY_SKIN, old.getInt(KEY_SKIN, 0) != 0); + e.putInt(KEY_LAST_USED_LIST, old.getInt(KEY_LAST_USED_LIST, StoredList.STANDARD_LIST_ID)); + e.putString(KEY_CACHE_TYPE, old.getString(KEY_CACHE_TYPE, CacheType.ALL.id)); + e.putString(KEY_TWITTER_TOKEN_SECRET, old.getString(KEY_TWITTER_TOKEN_SECRET, null)); + e.putString(KEY_TWITTER_TOKEN_PUBLIC, old.getString(KEY_TWITTER_TOKEN_PUBLIC, null)); + e.putInt(KEY_VERSION, old.getInt(KEY_VERSION, 0)); + e.putBoolean(KEY_LOAD_DESCRIPTION, 0 != old.getInt(KEY_LOAD_DESCRIPTION, 1)); + e.putBoolean(KEY_RATING_WANTED, old.getBoolean(KEY_RATING_WANTED, true)); + e.putBoolean(KEY_ELEVATION_WANTED, old.getBoolean(KEY_ELEVATION_WANTED, false)); + e.putBoolean(KEY_FRIENDLOGS_WANTED, old.getBoolean(KEY_FRIENDLOGS_WANTED, true)); + e.putBoolean(KEY_USE_ENGLISH, old.getBoolean(KEY_USE_ENGLISH, false)); + e.putBoolean(KEY_USE_COMPASS, 0 != old.getInt(KEY_USE_COMPASS, 1)); + e.putBoolean(KEY_AUTO_VISIT_TRACKABLES, old.getBoolean(KEY_AUTO_VISIT_TRACKABLES, false)); + e.putBoolean(KEY_AUTO_INSERT_SIGNATURE, old.getBoolean(KEY_AUTO_INSERT_SIGNATURE, false)); + e.putInt(KEY_ALTITUDE_CORRECTION, old.getInt(KEY_ALTITUDE_CORRECTION, 0)); + e.putBoolean(KEY_STORE_LOG_IMAGES, old.getBoolean(KEY_STORE_LOG_IMAGES, false)); + e.putBoolean(KEY_EXCLUDE_DISABLED, 0 != old.getInt(KEY_EXCLUDE_DISABLED, 0)); + e.putBoolean(KEY_EXCLUDE_OWN, 0 != old.getInt(KEY_EXCLUDE_OWN, 0)); + e.putString(KEY_MAPFILE, old.getString(KEY_MAPFILE, null)); + e.putString(KEY_SIGNATURE, old.getString(KEY_SIGNATURE, null)); + e.putString(KEY_GCVOTE_PASSWORD, old.getString(KEY_GCVOTE_PASSWORD, null)); + e.putString(KEY_PASSWORD, old.getString(KEY_PASSWORD, null)); + e.putString(KEY_USERNAME, old.getString(KEY_USERNAME, null)); + e.putString(KEY_MEMBER_STATUS, old.getString(KEY_MEMBER_STATUS, "")); + e.putInt(KEY_COORD_INPUT_FORMAT, old.getInt(KEY_COORD_INPUT_FORMAT, 0)); + e.putBoolean(KEY_LOG_OFFLINE, old.getBoolean(KEY_LOG_OFFLINE, false)); + e.putBoolean(KEY_CHOOSE_LIST, old.getBoolean(KEY_CHOOSE_LIST, false)); + e.putBoolean(KEY_LOAD_DIRECTION_IMG, old.getBoolean(KEY_LOAD_DIRECTION_IMG, true)); + e.putString(KEY_GC_CUSTOM_DATE, old.getString(KEY_GC_CUSTOM_DATE, null)); + e.putInt(KEY_SHOW_WAYPOINTS_THRESHOLD, old.getInt(KEY_SHOW_WAYPOINTS_THRESHOLD, 0)); + e.putString(KEY_COOKIE_STORE, old.getString(KEY_COOKIE_STORE, null)); + e.putBoolean(KEY_OPEN_LAST_DETAILS_PAGE, old.getBoolean(KEY_OPEN_LAST_DETAILS_PAGE, false)); + e.putInt(KEY_LAST_DETAILS_PAGE, old.getInt(KEY_LAST_DETAILS_PAGE, 1)); + e.putInt(KEY_DEFAULT_NAVIGATION_TOOL, old.getInt(KEY_DEFAULT_NAVIGATION_TOOL, NavigationAppsEnum.COMPASS.id)); + e.putInt(KEY_DEFAULT_NAVIGATION_TOOL_2, old.getInt(KEY_DEFAULT_NAVIGATION_TOOL_2, NavigationAppsEnum.INTERNAL_MAP.id)); + e.putInt(KEY_LIVE_MAP_STRATEGY, old.getInt(KEY_LIVE_MAP_STRATEGY, Strategy.AUTO.id)); + e.putBoolean(KEY_DEBUG, old.getBoolean(KEY_DEBUG, false)); + e.putBoolean(KEY_HIDE_LIVE_MAP_HINT, old.getInt(KEY_HIDE_LIVE_MAP_HINT, 0) != 0); + e.putInt(KEY_LIVE_MAP_HINT_SHOW_COUNT, old.getInt(KEY_LIVE_MAP_HINT_SHOW_COUNT, 0)); + + e.putInt(KEY_SETTINGS_VERSION, 1); // mark migrated + e.commit(); + } + + // changes for new settings dialog + if (oldVersion < 2) { + final Editor e = sharedPrefs.edit(); + + e.putBoolean(KEY_IMPERIAL_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(KEY_SHOW_WAYPOINTS_THRESHOLD, wpThreshold); + + // KEY_MAP_SOURCE must be string, because it is the key for a ListPreference now + int ms = sharedPrefs.getInt(KEY_MAP_SOURCE, MAP_SOURCE_DEFAULT); + e.remove(KEY_MAP_SOURCE); + e.putString(KEY_MAP_SOURCE, String.valueOf(ms)); + + // navigation tool ids must be string, because ListPreference uses strings as keys + int dnt1 = sharedPrefs.getInt(KEY_DEFAULT_NAVIGATION_TOOL, NavigationAppsEnum.COMPASS.id); + int dnt2 = sharedPrefs.getInt(KEY_DEFAULT_NAVIGATION_TOOL_2, NavigationAppsEnum.INTERNAL_MAP.id); + e.remove(KEY_DEFAULT_NAVIGATION_TOOL); + e.remove(KEY_DEFAULT_NAVIGATION_TOOL_2); + e.putString(KEY_DEFAULT_NAVIGATION_TOOL, String.valueOf(dnt1)); + e.putString(KEY_DEFAULT_NAVIGATION_TOOL_2, String.valueOf(dnt2)); + + // defaults for gpx directories + e.putString(KEY_GPX_IMPORT_DIR, getGpxImportDir()); + e.putString(KEY_GPX_EXPORT_DIR, getGpxExportDir()); + + e.putInt(KEY_SETTINGS_VERSION, 2); // mark migrated + e.commit(); + } + } + + static String getString(final String key, final String defaultValue) { + return sharedPrefs.getString(key, defaultValue); + } + + static boolean putString(final String key, final String value) { + final SharedPreferences.Editor edit = sharedPrefs.edit(); + edit.putString(key, value); + return edit.commit(); + } + + static boolean putBoolean(final String key, final boolean value) { + final SharedPreferences.Editor edit = sharedPrefs.edit(); + edit.putBoolean(key, value); + return edit.commit(); + } + + static boolean putInt(final String key, final int value) { + final SharedPreferences.Editor edit = sharedPrefs.edit(); + edit.putInt(key, value); + return edit.commit(); + } + + static boolean putFloat(final String key, final float value) { + final SharedPreferences.Editor edit = sharedPrefs.edit(); + edit.putFloat(key, value); + return edit.commit(); + } + + static boolean remove(final String key) { + final SharedPreferences.Editor edit = sharedPrefs.edit(); + edit.remove(key); + return edit.commit(); + } + + 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 = sharedPrefs.getString(KEY_USERNAME, null); + final String prePassword = sharedPrefs.getString(KEY_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() { + if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) { + final String preUsername = sharedPrefs.getString(KEY_USERNAME, null); + final String prePassword = sharedPrefs.getString(KEY_PASSWORD, null); + + if (StringUtils.isBlank(preUsername) || StringUtils.isBlank(prePassword)) { + return null; + } + + username = preUsername; + password = prePassword; + } + return new ImmutablePair<String, String>(username, password); + } + + public static String getUsername() { + return username != null ? username : sharedPrefs.getString(KEY_USERNAME, null); + } + + // TODO: remove with SettingsActivity + public static boolean setLogin(final String username, final String password) { + Settings.username = username; + Settings.password = password; + if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) { + // erase username and password + boolean a = remove(KEY_USERNAME); + boolean b = remove(KEY_PASSWORD); + return a && b; + } + // save username and password + boolean a = putString(KEY_USERNAME, username); + boolean b = putString(KEY_PASSWORD, password); + return a && b; + } + + public static boolean isGCConnectorActive() { + return sharedPrefs.getBoolean(KEY_CONNECTOR_GC_ACTIVE, true); + } + + // TODO: remove with SettingsActivity + public static boolean setGCConnectorActive(final boolean isActive) { + return putBoolean(KEY_CONNECTOR_GC_ACTIVE, isActive); + } + + 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 sharedPrefs.getString(KEY_MEMBER_STATUS, ""); + } + + public static boolean setMemberStatus(final String memberStatus) { + if (StringUtils.isBlank(memberStatus)) { + return remove(KEY_MEMBER_STATUS); + } + return putString(KEY_MEMBER_STATUS, memberStatus); + } + + public static boolean isOCConnectorActive() { + return sharedPrefs.getBoolean(KEY_CONNECTOR_OC_ACTIVE, false); + } + + public static boolean setOCConnectorActive(final boolean isActive) { + return putBoolean(KEY_CONNECTOR_OC_ACTIVE, isActive); + } + + public static String getOCDETokenPublic() { + return sharedPrefs.getString(KEY_OCDE_TOKEN_PUBLIC, ""); + } + + public static String getOCDETokenSecret() { + return sharedPrefs.getString(KEY_OCDE_TOKEN_SECRET, ""); + } + + public static void setOCDETokens(final String tokenPublic, + final String tokenSecret, boolean enableOcDe) { + putString(KEY_OCDE_TOKEN_PUBLIC, tokenPublic); + putString(KEY_OCDE_TOKEN_SECRET, tokenSecret); + if (tokenPublic != null) { + remove(KEY_TEMP_OCDE_TOKEN_PUBLIC); + remove(KEY_TEMP_OCDE_TOKEN_SECRET); + } + setOCConnectorActive(enableOcDe); + } + + public static void setOCDETempTokens(final String tokenPublic, final String tokenSecret) { + putString(KEY_TEMP_OCDE_TOKEN_PUBLIC, tokenPublic); + putString(KEY_TEMP_OCDE_TOKEN_SECRET, tokenSecret); + } + + public static ImmutablePair<String, String> getTempOCDEToken() { + String tokenPublic = sharedPrefs.getString(KEY_TEMP_OCDE_TOKEN_PUBLIC, null); + String tokenSecret = sharedPrefs.getString(KEY_TEMP_OCDE_TOKEN_SECRET, null); + return new ImmutablePair<String, String>(tokenPublic, tokenSecret); + } + + public static boolean isGCvoteLogin() { + final String preUsername = sharedPrefs.getString(KEY_USERNAME, null); + final String prePassword = sharedPrefs.getString(KEY_GCVOTE_PASSWORD, null); + + return !StringUtils.isBlank(preUsername) && !StringUtils.isBlank(prePassword); + } + + // TODO: remove with SettingsActivity + public static boolean setGCvoteLogin(final String password) { + if (StringUtils.isBlank(password)) { + // erase password + return remove(KEY_GCVOTE_PASSWORD); + } + // save password + return putString(KEY_GCVOTE_PASSWORD, password); + } + + public static ImmutablePair<String, String> getGCvoteLogin() { + final String username = sharedPrefs.getString(KEY_USERNAME, null); + final String password = sharedPrefs.getString(KEY_GCVOTE_PASSWORD, null); + + if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) { + return null; + } + + return new ImmutablePair<String, String>(username, password); + } + + // TODO: remove with SettingsActivity + public static boolean setSignature(final String signature) { + if (StringUtils.isBlank(signature)) { + // erase signature + return remove(KEY_SIGNATURE); + } + // save signature + return putString(KEY_SIGNATURE, signature); + } + + public static String getSignature() { + return sharedPrefs.getString(KEY_SIGNATURE, null); + } + + public static boolean setCookieStore(final String cookies) { + if (StringUtils.isBlank(cookies)) { + // erase cookies + return remove(KEY_COOKIE_STORE); + } + // save cookies + return putString(KEY_COOKIE_STORE, cookies); + } + + public static String getCookieStore() { + return sharedPrefs.getString(KEY_COOKIE_STORE, null); + } + + /** + * @param cacheType + * The cache type used for future filtering + */ + public static void setCacheType(final CacheType cacheType) { + if (cacheType == null) { + remove(KEY_CACHE_TYPE); + } else { + putString(KEY_CACHE_TYPE, cacheType.id); + } + } + + public static int getLastList() { + return sharedPrefs.getInt(KEY_LAST_USED_LIST, StoredList.STANDARD_LIST_ID); + } + + public static void saveLastList(final int listId) { + putInt(KEY_LAST_USED_LIST, listId); + } + + public static void setWebNameCode(final String name, final String code) { + putString(KEY_WEBDEVICE_NAME, name); + putString(KEY_WEB_DEVICE_CODE, code); + } + + public static MapProvider getMapProvider() { + if (mapProvider == null) { + mapProvider = getMapSource().getMapProvider(); + } + return mapProvider; + } + + public static String getMapFile() { + return sharedPrefs.getString(KEY_MAPFILE, null); + } + + public static boolean setMapFile(final String mapFile) { + boolean result = putString(KEY_MAPFILE, mapFile); + if (mapFile != null) { + setMapFileDirectory(new File(mapFile).getParent()); + } + return result; + } + + public static String getMapFileDirectory() { + final String mapDir = sharedPrefs.getString(KEY_MAP_DIRECTORY, 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(KEY_MAP_DIRECTORY, 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(sharedPrefs.getInt(KEY_COORD_INPUT_FORMAT, 0)); + } + + public static void setCoordInputFormat(final coordInputFormatEnum format) { + putInt(KEY_COORD_INPUT_FORMAT, format.ordinal()); + } + + static void setLogOffline(final boolean offline) { + putBoolean(KEY_LOG_OFFLINE, offline); + } + + public static boolean getLogOffline() { + return sharedPrefs.getBoolean(KEY_LOG_OFFLINE, false); + } + + // TODO: remove with SettingsActivity + static void setChooseList(final boolean choose) { + putBoolean(KEY_CHOOSE_LIST, choose); + } + + public static boolean getChooseList() { + return sharedPrefs.getBoolean(KEY_CHOOSE_LIST, false); + } + + // TODO: remove with SettingsActivity + static void setLoadDirImg(final boolean value) { + putBoolean(KEY_LOAD_DIRECTION_IMG, value); + } + + public static boolean getLoadDirImg() { + return !isPremiumMember() && sharedPrefs.getBoolean(KEY_LOAD_DIRECTION_IMG, true); + } + + public static void setGcCustomDate(final String format) { + putString(KEY_GC_CUSTOM_DATE, format); + } + + /** + * @return User selected date format on GC.com + * @see Login#gcCustomDateFormats + */ + public static String getGcCustomDate() { + return sharedPrefs.getString(KEY_GC_CUSTOM_DATE, null); + } + + public static boolean isExcludeMyCaches() { + return sharedPrefs.getBoolean(KEY_EXCLUDE_OWN, false); + } + + // TODO: remove with SettingsActivity + public static void setExcludeMine(final boolean exclude) { + putBoolean(KEY_EXCLUDE_OWN, exclude); + } + + public static void setUseEnglish(final boolean english) { + putBoolean(KEY_USE_ENGLISH, english); + setLanguage(english); + } + + public static boolean isUseEnglish() { + return sharedPrefs.getBoolean(KEY_USE_ENGLISH, false); + } + + public static boolean isShowAddress() { + return sharedPrefs.getBoolean(KEY_SHOW_ADDRESS, true); + } + + // TODO: remove with SettingsActivity + public static void setShowAddress(final boolean showAddress) { + putBoolean(KEY_SHOW_ADDRESS, showAddress); + } + + public static boolean isShowCaptcha() { + return !isPremiumMember() && sharedPrefs.getBoolean(KEY_SHOW_CAPTCHA, false); + } + + // TODO: remove with SettingsActivity + public static void setShowCaptcha(final boolean showCaptcha) { + putBoolean(KEY_SHOW_CAPTCHA, showCaptcha); + } + + public static boolean isExcludeDisabledCaches() { + return sharedPrefs.getBoolean(KEY_EXCLUDE_DISABLED, false); + } + + // TODO: remove with SettingsActivity + public static void setExcludeDisabledCaches(final boolean exclude) { + putBoolean(KEY_EXCLUDE_DISABLED, exclude); + } + + public static boolean isStoreOfflineMaps() { + return sharedPrefs.getBoolean(KEY_USE_OFFLINEMAPS, true); + } + + // TODO: remove with SettingsActivity + public static void setStoreOfflineMaps(final boolean offlineMaps) { + putBoolean(KEY_USE_OFFLINEMAPS, offlineMaps); + } + + public static boolean isStoreOfflineWpMaps() { + return sharedPrefs.getBoolean(KEY_USE_OFFLINEWPMAPS, false); + } + + // TODO: remove with SettingsActivity + public static void setStoreOfflineWpMaps(final boolean offlineMaps) { + putBoolean(KEY_USE_OFFLINEWPMAPS, offlineMaps); + } + + public static boolean isStoreLogImages() { + return sharedPrefs.getBoolean(KEY_STORE_LOG_IMAGES, false); + } + + // TODO: remove with SettingsActivity + public static void setStoreLogImages(final boolean storeLogImages) { + putBoolean(KEY_STORE_LOG_IMAGES, storeLogImages); + } + + public static boolean isAutoLoadDescription() { + return sharedPrefs.getBoolean(KEY_LOAD_DESCRIPTION, true); + } + + // TODO: remove with SettingsActivity + public static void setAutoLoadDesc(final boolean autoLoad) { + putBoolean(KEY_LOAD_DESCRIPTION, autoLoad); + } + + public static boolean isRatingWanted() { + return sharedPrefs.getBoolean(KEY_RATING_WANTED, true); + } + + // TODO: remove with SettingsActivity + public static void setRatingWanted(final boolean ratingWanted) { + putBoolean(KEY_RATING_WANTED, ratingWanted); + } + + public static boolean isElevationWanted() { + return sharedPrefs.getBoolean(KEY_ELEVATION_WANTED, false); + } + + // TODO: remove with SettingsActivity + public static void setElevationWanted(final boolean elevationWanted) { + putBoolean(KEY_ELEVATION_WANTED, elevationWanted); + } + + public static boolean isFriendLogsWanted() { + if (!isLogin()) { + // don't show a friends log if the user is anonymous + return false; + } + return sharedPrefs.getBoolean(KEY_FRIENDLOGS_WANTED, true); + } + + // TODO: remove with SettingsActivity + public static void setFriendLogsWanted(final boolean friendLogsWanted) { + putBoolean(KEY_FRIENDLOGS_WANTED, friendLogsWanted); + } + + public static boolean isLiveList() { + return sharedPrefs.getBoolean(KEY_LIVE_LIST, true); + } + + // TODO: remove with SettingsActivity + public static void setLiveList(final boolean liveList) { + putBoolean(KEY_LIVE_LIST, liveList); + } + + public static boolean isTrackableAutoVisit() { + return sharedPrefs.getBoolean(KEY_AUTO_VISIT_TRACKABLES, false); + } + + // TODO: remove with SettingsActivity + public static void setTrackableAutoVisit(final boolean autoVisit) { + putBoolean(KEY_AUTO_VISIT_TRACKABLES, autoVisit); + } + + public static boolean isAutoInsertSignature() { + return sharedPrefs.getBoolean(KEY_AUTO_INSERT_SIGNATURE, false); + } + + // TODO: remove with SettingsActivity + public static void setAutoInsertSignature(final boolean autoInsert) { + putBoolean(KEY_AUTO_INSERT_SIGNATURE, autoInsert); + } + + public static boolean isUseImperialUnits() { + return sharedPrefs.getBoolean(KEY_IMPERIAL_UNITS, false); + } + + // TODO: remove with SettingsActivity + public static void setUseImperialUnits(final boolean imperial) { + putBoolean(KEY_IMPERIAL_UNITS, imperial); + } + + public static boolean isLiveMap() { + return sharedPrefs.getBoolean(KEY_MAP_LIVE, true); + } + + public static void setLiveMap(final boolean live) { + putBoolean(KEY_MAP_LIVE, live); + } + + public static boolean isMapTrail() { + return sharedPrefs.getBoolean(KEY_MAP_TRAIL, true); + } + + public static void setMapTrail(final boolean showTrail) { + putBoolean(KEY_MAP_TRAIL, showTrail); + } + + public static int getMapZoom() { + return sharedPrefs.getInt(KEY_LAST_MAP_ZOOM, 14); + } + + public static void setMapZoom(final int mapZoomLevel) { + putInt(KEY_LAST_MAP_ZOOM, mapZoomLevel); + } + + public static GeoPointImpl getMapCenter() { + return getMapProvider().getMapItemFactory() + .getGeoPointBase(new Geopoint(sharedPrefs.getInt(KEY_LAST_MAP_LAT, 0) / 1e6, + sharedPrefs.getInt(KEY_LAST_MAP_LON, 0) / 1e6)); + } + + public static void setMapCenter(final GeoPointImpl mapViewCenter) { + putInt(KEY_LAST_MAP_LAT, mapViewCenter.getLatitudeE6()); + putInt(KEY_LAST_MAP_LON, 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(sharedPrefs.getString(KEY_MAP_SOURCE, + 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(KEY_MAP_SOURCE, String.valueOf(newMapSource.getNumericalId())); + if (newMapSource instanceof OfflineMapSource) { + setMapFile(((OfflineMapSource) newMapSource).getFileName()); + } + } + + public static void setAnyCoordinates(final Geopoint coords) { + if (null != coords) { + putFloat(KEY_ANYLATITUDE, (float) coords.getLatitude()); + putFloat(KEY_ANYLONGITUDE, (float) coords.getLongitude()); + } else { + remove(KEY_ANYLATITUDE); + remove(KEY_ANYLONGITUDE); + } + } + + public static Geopoint getAnyCoordinates() { + if (sharedPrefs.contains(KEY_ANYLATITUDE) && sharedPrefs.contains(KEY_ANYLONGITUDE)) { + float lat = sharedPrefs.getFloat(KEY_ANYLATITUDE, 0); + float lon = sharedPrefs.getFloat(KEY_ANYLONGITUDE, 0); + return new Geopoint(lat, lon); + } + return null; + } + + public static boolean isUseCompass() { + return sharedPrefs.getBoolean(KEY_USE_COMPASS, true); + } + + public static void setUseCompass(final boolean useCompass) { + putBoolean(KEY_USE_COMPASS, useCompass); + } + + public static boolean isLightSkin() { + return sharedPrefs.getBoolean(KEY_SKIN, false); + } + + // TODO: remove with SettingsActivity + public static void setLightSkin(final boolean lightSkin) { + putBoolean(KEY_SKIN, lightSkin); + } + + public static String getKeyConsumerPublic() { + return keyConsumerPublic; + } + + public static String getKeyConsumerSecret() { + return keyConsumerSecret; + } + + public static int getAltitudeCorrection() { + return sharedPrefs.getInt(KEY_ALTITUDE_CORRECTION, 0); + } + + // TODO: remove with SettingsActivity + public static boolean setAltitudeCorrection(final int altitude) { + return putInt(KEY_ALTITUDE_CORRECTION, altitude); + } + + public static String getWebDeviceCode() { + return sharedPrefs.getString(KEY_WEB_DEVICE_CODE, null); + } + + public static String getWebDeviceName() { + return sharedPrefs.getString(KEY_WEBDEVICE_NAME, 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(sharedPrefs.getString(KEY_CACHE_TYPE, CacheType.ALL.id)); + } + + /** + * The Threshold for the showing of child waypoints + */ + public static int getWayPointsThreshold() { + return sharedPrefs.getInt(KEY_SHOW_WAYPOINTS_THRESHOLD, SHOW_WP_THRESHOLD_DEFAULT); + } + + // TODO: remove with SettingsActivity + public static void setShowWaypointsThreshold(final int threshold) { + putInt(KEY_SHOW_WAYPOINTS_THRESHOLD, threshold); + } + + public static boolean isUseTwitter() { + return sharedPrefs.getBoolean(KEY_USE_TWITTER, false); + } + + public static void setUseTwitter(final boolean useTwitter) { + putBoolean(KEY_USE_TWITTER, useTwitter); + } + + public static boolean isTwitterLoginValid() { + return !StringUtils.isBlank(getTokenPublic()) + && !StringUtils.isBlank(getTokenSecret()); + } + + public static String getTokenPublic() { + return sharedPrefs.getString(KEY_TWITTER_TOKEN_PUBLIC, null); + } + + public static String getTokenSecret() { + return sharedPrefs.getString(KEY_TWITTER_TOKEN_SECRET, null); + + } + + public static void setTwitterTokens(final String tokenPublic, + final String tokenSecret, boolean enableTwitter) { + putString(KEY_TWITTER_TOKEN_PUBLIC, tokenPublic); + putString(KEY_TWITTER_TOKEN_SECRET, tokenSecret); + if (tokenPublic != null) { + remove(KEY_TEMP_TWITTER_TOKEN_PUBLIC); + remove(KEY_TEMP_TWITTER_TOKEN_SECRET); + } + setUseTwitter(enableTwitter); + } + + public static void setTwitterTempTokens(final String tokenPublic, + final String tokenSecret) { + putString(KEY_TEMP_TWITTER_TOKEN_PUBLIC, tokenPublic); + putString(KEY_TEMP_TWITTER_TOKEN_SECRET, tokenSecret); + } + + public static ImmutablePair<String, String> getTempToken() { + String tokenPublic = sharedPrefs.getString(KEY_TEMP_TWITTER_TOKEN_PUBLIC, null); + String tokenSecret = sharedPrefs.getString(KEY_TEMP_TWITTER_TOKEN_SECRET, null); + return new ImmutablePair<String, String>(tokenPublic, tokenSecret); + } + + public static int getVersion() { + return sharedPrefs.getInt(KEY_VERSION, 0); + } + + public static void setVersion(final int version) { + putInt(KEY_VERSION, version); + } + + public static boolean isOpenLastDetailsPage() { + return sharedPrefs.getBoolean(KEY_OPEN_LAST_DETAILS_PAGE, false); + } + + // TODO: remove with SettingsActivity + public static void setOpenLastDetailsPage(final boolean openLastPage) { + putBoolean(KEY_OPEN_LAST_DETAILS_PAGE, openLastPage); + } + + public static int getLastDetailsPage() { + return sharedPrefs.getInt(KEY_LAST_DETAILS_PAGE, 1); + } + + public static void setLastDetailsPage(final int index) { + putInt(KEY_LAST_DETAILS_PAGE, index); + } + + public static int getDefaultNavigationTool() { + return Integer.parseInt(sharedPrefs.getString( + KEY_DEFAULT_NAVIGATION_TOOL, + String.valueOf(NavigationAppsEnum.COMPASS.id))); + } + + public static void setDefaultNavigationTool(final int defaultNavigationTool) { + putString(KEY_DEFAULT_NAVIGATION_TOOL, + String.valueOf(defaultNavigationTool)); + } + + public static int getDefaultNavigationTool2() { + return Integer.parseInt(sharedPrefs.getString( + KEY_DEFAULT_NAVIGATION_TOOL_2, + String.valueOf(NavigationAppsEnum.INTERNAL_MAP.id))); + } + + public static void setDefaultNavigationTool2(final int defaultNavigationTool) { + putString(KEY_DEFAULT_NAVIGATION_TOOL_2, + String.valueOf(defaultNavigationTool)); + } + + public static Strategy getLiveMapStrategy() { + return Strategy.getById(sharedPrefs.getInt(KEY_LIVE_MAP_STRATEGY, Strategy.AUTO.id)); + } + + public static void setLiveMapStrategy(final Strategy strategy) { + putInt(KEY_LIVE_MAP_STRATEGY, strategy.id); + } + + public static boolean isDebug() { + return Log.isDebug(); + } + + // TODO: remove with SettingsActivity + public static void setDebug(final boolean debug) { + putBoolean(KEY_DEBUG, debug); + Log.setDebug(debug); + } + + public static boolean getHideLiveMapHint() { + return sharedPrefs.getBoolean(KEY_HIDE_LIVE_MAP_HINT, false); + } + + public static void setHideLiveHint(final boolean hide) { + putBoolean(KEY_HIDE_LIVE_MAP_HINT, hide); + } + + public static int getLiveMapHintShowCount() { + return sharedPrefs.getInt(KEY_LIVE_MAP_HINT_SHOW_COUNT, 0); + } + + public static void setLiveMapHintShowCount(final int showCount) { + putInt(KEY_LIVE_MAP_HINT_SHOW_COUNT, showCount); + } + + public static boolean isDbOnSDCard() { + return sharedPrefs.getBoolean(KEY_DB_ON_SDCARD, false); + } + + public static void setDbOnSDCard(final boolean dbOnSDCard) { + putBoolean(KEY_DB_ON_SDCARD, dbOnSDCard); + } + + public static String getGpxExportDir() { + return sharedPrefs.getString(KEY_GPX_EXPORT_DIR, + Environment.getExternalStorageDirectory().getPath() + "/gpx"); + } + + // TODO: remove with SettingsActivity + public static void setGpxExportDir(final String gpxExportDir) { + putString(KEY_GPX_EXPORT_DIR, gpxExportDir); + } + + public static String getGpxImportDir() { + return sharedPrefs.getString(KEY_GPX_IMPORT_DIR, + Environment.getExternalStorageDirectory().getPath() + "/gpx"); + } + + // TODO: remove with SettingsActivity + public static void setGpxImportDir(final String gpxImportDir) { + putString(KEY_GPX_IMPORT_DIR, gpxImportDir); + } + + public static boolean getShareAfterExport() { + return sharedPrefs.getBoolean(KEY_SHARE_AFTER_EXPORT, true); + } + + public static void setShareAfterExport(final boolean shareAfterExport) { + putBoolean(KEY_SHARE_AFTER_EXPORT, shareAfterExport); + } + + public static int getTrackableAction() { + return sharedPrefs.getInt(KEY_LAST_TRACKABLE_ACTION, LogType.RETRIEVED_IT.id); + } + + public static void setTrackableAction(final int trackableAction) { + putInt(KEY_LAST_TRACKABLE_ACTION, trackableAction); + } + + public static String getCustomRenderThemeBaseFolder() { + return sharedPrefs.getString(KEY_RENDER_THEME_BASE_FOLDER, ""); + } + + // TODO: remove with SettingsActivity + public static boolean setCustomRenderThemeBaseFolder(final String folder) { + return putString(KEY_RENDER_THEME_BASE_FOLDER, folder); + } + + public static String getCustomRenderThemeFilePath() { + return sharedPrefs.getString(KEY_RENDER_THEME_FILE_PATH, ""); + } + + public static void setCustomRenderThemeFile(final String customRenderThemeFile) { + putString(KEY_RENDER_THEME_FILE_PATH, 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 sharedPrefs.getBoolean(KEY_PLAIN_LOGS, false); + } + + // TODO: remove with SettingsActivity + public static void setPlainLogs(final boolean plainLogs) { + putBoolean(KEY_PLAIN_LOGS, plainLogs); + } + + public static boolean getUseNativeUa() { + return sharedPrefs.getBoolean(KEY_NATIVE_UA, false); + } + + // TODO: remove with SettingsActivity + public static void setUseNativeUa(final boolean useNativeUa) { + putBoolean(KEY_NATIVE_UA, useNativeUa); + } + + public static String getCacheTwitterMessage() { + // TODO make customizable from UI + return cacheTwitterMessage; + } + + public static String getTrackableTwitterMessage() { + // TODO make customizable from UI + return "I touched [NAME] ([URL])!"; + } + + public static int getLogImageScale() { + return sharedPrefs.getInt(KEY_LOG_IMAGE_SCALE, -1); + } + + public static void setLogImageScale(final int scale) { + putInt(KEY_LOG_IMAGE_SCALE, scale); + } +} diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java new file mode 100644 index 0000000..e8ce1ff --- /dev/null +++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java @@ -0,0 +1,1073 @@ +package cgeo.geocaching.settings; + +import cgeo.geocaching.Intents; +import cgeo.geocaching.R; +import cgeo.geocaching.SelectMapfileActivity; +import cgeo.geocaching.cgData; +import cgeo.geocaching.activity.AbstractActivity; +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.connector.gc.Login; +import cgeo.geocaching.connector.oc.OCAuthorizationActivity; +import cgeo.geocaching.enumerations.StatusCode; +import cgeo.geocaching.files.SimpleDirChooser; +import cgeo.geocaching.maps.MapProviderFactory; +import cgeo.geocaching.maps.interfaces.MapSource; +import cgeo.geocaching.network.Cookies; +import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.twitter.TwitterAuthorizationActivity; +import cgeo.geocaching.ui.Formatter; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.LogTemplateProvider; +import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate; +import cgeo.geocaching.utils.RunnableWithArgument; + +import ch.boye.httpclientandroidlib.HttpResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.openintents.intents.FileManagerIntents; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.TextView; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class SettingsActivity extends AbstractActivity { + + private final static int SELECT_MAPFILE_REQUEST = 1; + private final static int SELECT_GPX_EXPORT_REQUEST = 2; + private final static int SELECT_GPX_IMPORT_REQUEST = 3; + private final static int SELECT_THEMEFOLDER_REQUEST = 4; + + private ProgressDialog loginDialog = null; + private ProgressDialog webDialog = null; + private boolean enableTemplatesMenu = false; + 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)) { + helpDialog(res.getString(R.string.init_login_popup), res.getString(R.string.init_login_popup_ok), + (Drawable) msg.obj); + } else { + helpDialog(res.getString(R.string.init_login_popup), + res.getString(R.string.init_login_popup_failed_reason) + " " + + ((StatusCode) msg.obj).getErrorString(res) + "."); + } + } catch (Exception e) { + showToast(res.getString(R.string.err_login_failed)); + + Log.e("SettingsActivity.logInHandler", e); + } + + if (loginDialog != null && loginDialog.isShowing()) { + loginDialog.dismiss(); + } + + init(); + } + }; + + private Handler webAuthHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + try { + if (webDialog != null && webDialog.isShowing()) { + webDialog.dismiss(); + } + + if (msg.what > 0) { + helpDialog(res.getString(R.string.init_sendToCgeo), res.getString(R.string.init_sendToCgeo_register_ok).replace("####", String.valueOf(msg.what))); + } else { + helpDialog(res.getString(R.string.init_sendToCgeo), res.getString(R.string.init_sendToCgeo_register_fail)); + } + } catch (Exception e) { + showToast(res.getString(R.string.init_sendToCgeo_register_fail)); + + Log.e("SettingsActivity.webHandler", e); + } + + if (webDialog != null && webDialog.isShowing()) { + webDialog.dismiss(); + } + + init(); + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState, R.layout.settings_activity); + + init(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + init(); + } + + @Override + public void onPause() { + saveValues(); + super.onPause(); + } + + @Override + public void onStop() { + saveValues(); + Compatibility.dataChanged(getPackageName()); + super.onStop(); + } + + @Override + public void onDestroy() { + saveValues(); + + super.onDestroy(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.settings_activity_options, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.menu_clear) { + ((EditText) findViewById(R.id.username)).setText(""); + ((EditText) findViewById(R.id.password)).setText(""); + ((EditText) findViewById(R.id.passvote)).setText(""); + + if (saveValues()) { + showToast(res.getString(R.string.init_cleared)); + } else { + showToast(res.getString(R.string.err_init_cleared)); + } + + finish(); + } + + return false; + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + if (enableTemplatesMenu) { + menu.setHeaderTitle(R.string.init_signature_template_button); + for (LogTemplate template : LogTemplateProvider.getTemplates()) { + menu.add(0, template.getItemId(), 0, template.getResourceId()); + } + } + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + LogTemplate template = LogTemplateProvider.getTemplate(item.getItemId()); + if (template != null) { + return insertSignatureTemplate(template); + } + return super.onContextItemSelected(item); + } + + private boolean insertSignatureTemplate(final LogTemplate template) { + EditText sig = (EditText) findViewById(R.id.signature); + String insertText = "[" + template.getTemplateString() + "]"; + ActivityMixin.insertAtPosition(sig, insertText, true); + return true; + } + + public void init() { + + // geocaching.com settings + final CheckBox gcCheck = (CheckBox) findViewById(R.id.gc_option); + gcCheck.setChecked(Settings.isGCConnectorActive()); + gcCheck.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setGCConnectorActive(gcCheck.isChecked()); + } + }); + final ImmutablePair<String, String> login = Settings.getGcLogin(); + if (login != null) { + ((EditText) findViewById(R.id.username)).setText(login.left); + ((EditText) findViewById(R.id.password)).setText(login.right); + } + + Button logMeIn = (Button) findViewById(R.id.log_me_in); + logMeIn.setOnClickListener(new LoginListener()); + + TextView legalNote = (TextView) findViewById(R.id.legal_note); + legalNote.setClickable(true); + legalNote.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View arg0) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/about/termsofuse.aspx"))); + } + }); + + // opencaching.de settings + final CheckBox ocCheck = (CheckBox) findViewById(R.id.oc_option); + ocCheck.setChecked(Settings.isOCConnectorActive()); + ocCheck.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setOCConnectorActive(ocCheck.isChecked()); + } + }); + + Button checkOCUser = (Button) findViewById(R.id.register_oc_de); + checkOCUser.setOnClickListener(new OCDEAuthorizeCgeoListener()); + + // gcvote settings + final ImmutablePair<String, String> gcvoteLogin = Settings.getGCvoteLogin(); + if (null != gcvoteLogin && null != gcvoteLogin.right) { + ((EditText) findViewById(R.id.passvote)).setText(gcvoteLogin.right); + } + + // Twitter settings + Button authorizeTwitter = (Button) findViewById(R.id.authorize_twitter); + authorizeTwitter.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View arg0) { + Intent authIntent = new Intent(SettingsActivity.this, TwitterAuthorizationActivity.class); + startActivity(authIntent); + } + }); + + final CheckBox twitterButton = (CheckBox) findViewById(R.id.twitter_option); + twitterButton.setChecked(Settings.isUseTwitter() && Settings.isTwitterLoginValid()); + twitterButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setUseTwitter(twitterButton.isChecked()); + if (Settings.isUseTwitter() && !Settings.isTwitterLoginValid()) { + Intent authIntent = new Intent(SettingsActivity.this, TwitterAuthorizationActivity.class); + startActivity(authIntent); + } + + twitterButton.setChecked(Settings.isUseTwitter()); + } + }); + + // Signature settings + EditText sigEdit = (EditText) findViewById(R.id.signature); + if (sigEdit.getText().length() == 0) { + sigEdit.setText(Settings.getSignature()); + } + Button sigBtn = (Button) findViewById(R.id.signature_help); + sigBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + helpDialog(res.getString(R.string.init_signature_help_title), res.getString(R.string.init_signature_help_text)); + } + }); + Button templates = (Button) findViewById(R.id.signature_template); + registerForContextMenu(templates); + templates.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + enableTemplatesMenu = true; + openContextMenu(v); + enableTemplatesMenu = false; + } + }); + final CheckBox autoinsertButton = (CheckBox) findViewById(R.id.sigautoinsert); + autoinsertButton.setChecked(Settings.isAutoInsertSignature()); + autoinsertButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setAutoInsertSignature(autoinsertButton.isChecked()); + } + }); + + // Cache details + final CheckBox autoloadButton = (CheckBox) findViewById(R.id.autoload); + autoloadButton.setChecked(Settings.isAutoLoadDescription()); + autoloadButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setAutoLoadDesc(autoloadButton.isChecked()); + } + }); + + final CheckBox ratingWantedButton = (CheckBox) findViewById(R.id.ratingwanted); + ratingWantedButton.setChecked(Settings.isRatingWanted()); + ratingWantedButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setRatingWanted(ratingWantedButton.isChecked()); + } + }); + + final CheckBox elevationWantedButton = (CheckBox) findViewById(R.id.elevationwanted); + elevationWantedButton.setChecked(Settings.isElevationWanted()); + elevationWantedButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setElevationWanted(elevationWantedButton.isChecked()); + } + }); + + final CheckBox friendLogsWantedButton = (CheckBox) findViewById(R.id.friendlogswanted); + friendLogsWantedButton.setChecked(Settings.isFriendLogsWanted()); + friendLogsWantedButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setFriendLogsWanted(friendLogsWantedButton.isChecked()); + } + }); + + final CheckBox openLastDetailsPageButton = (CheckBox) findViewById(R.id.openlastdetailspage); + openLastDetailsPageButton.setChecked(Settings.isOpenLastDetailsPage()); + openLastDetailsPageButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setOpenLastDetailsPage(openLastDetailsPageButton.isChecked()); + } + }); + + // Other settings + final CheckBox skinButton = (CheckBox) findViewById(R.id.skin); + skinButton.setChecked(Settings.isLightSkin()); + skinButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setLightSkin(skinButton.isChecked()); + } + }); + + final CheckBox addressButton = (CheckBox) findViewById(R.id.address); + addressButton.setChecked(Settings.isShowAddress()); + addressButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setShowAddress(addressButton.isChecked()); + } + }); + + final CheckBox captchaButton = (CheckBox) findViewById(R.id.captcha); + captchaButton.setEnabled(!Settings.isPremiumMember()); + captchaButton.setChecked(Settings.isShowCaptcha()); + captchaButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setShowCaptcha(captchaButton.isChecked()); + } + }); + + final CheckBox dirImgButton = (CheckBox) findViewById(R.id.loaddirectionimg); + dirImgButton.setEnabled(!Settings.isPremiumMember()); + dirImgButton.setChecked(Settings.getLoadDirImg()); + dirImgButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setLoadDirImg(!Settings.getLoadDirImg()); + dirImgButton.setChecked(Settings.getLoadDirImg()); + } + }); + + final CheckBox useEnglishButton = (CheckBox) findViewById(R.id.useenglish); + useEnglishButton.setChecked(Settings.isUseEnglish()); + useEnglishButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setUseEnglish(useEnglishButton.isChecked()); + } + }); + + final CheckBox excludeButton = (CheckBox) findViewById(R.id.exclude); + excludeButton.setChecked(Settings.isExcludeMyCaches()); + excludeButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setExcludeMine(excludeButton.isChecked()); + } + }); + + final CheckBox disabledButton = (CheckBox) findViewById(R.id.disabled); + disabledButton.setChecked(Settings.isExcludeDisabledCaches()); + disabledButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setExcludeDisabledCaches(disabledButton.isChecked()); + } + }); + + TextView showWaypointsThreshold = (TextView) findViewById(R.id.showwaypointsthreshold); + showWaypointsThreshold.setText(String.valueOf(Settings.getWayPointsThreshold())); + + final CheckBox autovisitButton = (CheckBox) findViewById(R.id.trackautovisit); + autovisitButton.setChecked(Settings.isTrackableAutoVisit()); + autovisitButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setTrackableAutoVisit(autovisitButton.isChecked()); + } + }); + + final CheckBox offlineButton = (CheckBox) findViewById(R.id.offline); + offlineButton.setChecked(Settings.isStoreOfflineMaps()); + offlineButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setStoreOfflineMaps(offlineButton.isChecked()); + } + }); + + final CheckBox offlineWpButton = (CheckBox) findViewById(R.id.offline_wp); + offlineWpButton.setChecked(Settings.isStoreOfflineWpMaps()); + offlineWpButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setStoreOfflineWpMaps(offlineWpButton.isChecked()); + } + }); + + final CheckBox saveLogImgButton = (CheckBox) findViewById(R.id.save_log_img); + saveLogImgButton.setChecked(Settings.isStoreLogImages()); + saveLogImgButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setStoreLogImages(saveLogImgButton.isChecked()); + } + }); + + final CheckBox livelistButton = (CheckBox) findViewById(R.id.livelist); + livelistButton.setChecked(Settings.isLiveList()); + livelistButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setLiveList(livelistButton.isChecked()); + } + }); + + final CheckBox unitsButton = (CheckBox) findViewById(R.id.units); + unitsButton.setChecked(Settings.isUseImperialUnits()); + unitsButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setUseImperialUnits(unitsButton.isChecked()); + } + }); + + final CheckBox logOffline = (CheckBox) findViewById(R.id.log_offline); + logOffline.setChecked(Settings.getLogOffline()); + logOffline.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setLogOffline(!Settings.getLogOffline()); + logOffline.setChecked(Settings.getLogOffline()); + } + }); + + final CheckBox chooseList = (CheckBox) findViewById(R.id.choose_list); + chooseList.setChecked(Settings.getChooseList()); + chooseList.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setChooseList(!Settings.getChooseList()); + chooseList.setChecked(Settings.getChooseList()); + } + }); + + final CheckBox plainLogs = (CheckBox) findViewById(R.id.plain_logs); + plainLogs.setChecked(Settings.getPlainLogs()); + plainLogs.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setPlainLogs(!Settings.getPlainLogs()); + plainLogs.setChecked(Settings.getPlainLogs()); + } + }); + + // Workaround for cspire customers on mobile connections #1843 + final CheckBox useNativeUserAgent = (CheckBox) findViewById(R.id.use_native_ua); + useNativeUserAgent.setChecked(Settings.getUseNativeUa()); + useNativeUserAgent.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setUseNativeUa(!Settings.getUseNativeUa()); + useNativeUserAgent.setChecked(Settings.getUseNativeUa()); + } + }); + + // Altitude settings + EditText altitudeEdit = (EditText) findViewById(R.id.altitude); + altitudeEdit.setText(String.valueOf(Settings.getAltitudeCorrection())); + + //Send2cgeo settings + String webDeviceName = Settings.getWebDeviceName(); + + ((EditText) findViewById(R.id.webDeviceName)).setText(webDeviceName); + + Button webAuth = (Button) findViewById(R.id.sendToCgeo_register); + webAuth.setOnClickListener(new WebAuthListener()); + + // Map source settings + updateMapSourceMenu(); + + Button selectMapDirectory = (Button) findViewById(R.id.select_map_directory); + selectMapDirectory.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Intent selectIntent = new Intent(SettingsActivity.this, SelectMapfileActivity.class); + startActivityForResult(selectIntent, SELECT_MAPFILE_REQUEST); + } + }); + + // Theme folder settings + initThemefolderEdittext(false); + + Button selectThemefolder = (Button) findViewById(R.id.select_themefolder); + selectThemefolder.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + selectDirectory(Settings.getCustomRenderThemeBaseFolder(), SELECT_THEMEFOLDER_REQUEST); + } + }); + + // GPX Export directory + final EditText gpxExportDir = (EditText) findViewById(R.id.gpx_exportdir); + gpxExportDir.setText(Settings.getGpxExportDir()); + Button selectGpxExportDir = (Button) findViewById(R.id.select_gpx_exportdir); + selectGpxExportDir.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + selectDirectory(Settings.getGpxExportDir(), SELECT_GPX_EXPORT_REQUEST); + } + }); + + // GPX Import directory + final EditText gpxImportDir = (EditText) findViewById(R.id.gpx_importdir); + gpxImportDir.setText(Settings.getGpxImportDir()); + Button selectGpxImportDir = (Button) findViewById(R.id.select_gpx_importdir); + selectGpxImportDir.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + selectDirectory(Settings.getGpxImportDir(), SELECT_GPX_IMPORT_REQUEST); + } + }); + + // Display trail on map + final CheckBox trailButton = (CheckBox) findViewById(R.id.trail); + trailButton.setChecked(Settings.isMapTrail()); + trailButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setMapTrail(trailButton.isChecked()); + } + }); + + // Default navigation tool settings + Spinner defaultNavigationToolSelector = (Spinner) findViewById(R.id.default_navigation_tool); + final List<NavigationAppsEnum> apps = NavigationAppFactory.getInstalledDefaultNavigationApps(); + ArrayAdapter<NavigationAppsEnum> naviAdapter = new ArrayAdapter<NavigationAppsEnum>(this, android.R.layout.simple_spinner_item, apps) { + @Override + public View getView(int position, View convertView, ViewGroup parent) { + TextView textView = (TextView) super.getView(position, convertView, parent); + textView.setText(getItem(position).app.getName()); + return textView; + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + TextView textView = (TextView) super.getDropDownView(position, convertView, parent); + textView.setText(getItem(position).app.getName()); + return textView; + } + }; + naviAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + defaultNavigationToolSelector.setAdapter(naviAdapter); + int defaultNavigationTool = Settings.getDefaultNavigationTool(); + int ordinal = 0; + for (int i = 0; i < apps.size(); i++) { + if (apps.get(i).id == defaultNavigationTool) { + ordinal = i; + break; + } + } + defaultNavigationToolSelector.setSelection(ordinal); + defaultNavigationToolSelector.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + NavigationAppsEnum item = (NavigationAppsEnum) parent.getItemAtPosition(position); + if (item != null) { + Settings.setDefaultNavigationTool(item.id); + } + } + + @Override + public void onNothingSelected(AdapterView<?> arg0) { + // noop + } + }); + + // 2nd Default navigation tool settings + Spinner defaultNavigationTool2Selector = (Spinner) findViewById(R.id.default_navigation_tool_2); + // final List<NavigationAppsEnum> apps = NavigationAppFactory.getInstalledNavigationApps(this); + ArrayAdapter<NavigationAppsEnum> navi2Adapter = new ArrayAdapter<NavigationAppsEnum>(this, android.R.layout.simple_spinner_item, apps) { + @Override + public View getView(int position, View convertView, ViewGroup parent) { + TextView textView = (TextView) super.getView(position, convertView, parent); + textView.setText(getItem(position).app.getName()); + return textView; + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + TextView textView = (TextView) super.getDropDownView(position, convertView, parent); + textView.setText(getItem(position).app.getName()); + return textView; + } + }; + navi2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + defaultNavigationTool2Selector.setAdapter(navi2Adapter); + int defaultNavigationTool2 = Settings.getDefaultNavigationTool2(); + int ordinal2 = 0; + for (int i = 0; i < apps.size(); i++) { + if (apps.get(i).id == defaultNavigationTool2) { + ordinal2 = i; + break; + } + } + defaultNavigationTool2Selector.setSelection(ordinal2); + defaultNavigationTool2Selector.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + NavigationAppsEnum item = (NavigationAppsEnum) parent.getItemAtPosition(position); + if (item != null) { + Settings.setDefaultNavigationTool2(item.id); + } + } + + @Override + public void onNothingSelected(AdapterView<?> arg0) { + // noop + } + }); + + refreshBackupLabel(); + + // Database location + refreshDbOnSDCardSetting(); + + final CheckBox dbOnSDCardButton = (CheckBox) findViewById(R.id.dbonsdcard); + dbOnSDCardButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + app.moveDatabase(SettingsActivity.this); + } + }); + + // Debug settings + final CheckBox debugButton = (CheckBox) findViewById(R.id.debug); + debugButton.setChecked(Settings.isDebug()); + debugButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + Settings.setDebug(!Settings.isDebug()); + debugButton.setChecked(Settings.isDebug()); + } + }); + } + + private void updateMapSourceMenu() { + Collection<String> mapSourceNames = new ArrayList<String>(); + for (MapSource mapSource : MapProviderFactory.getMapSources()) { + mapSourceNames.add(mapSource.getName()); + } + Spinner mapSourceSelector = (Spinner) findViewById(R.id.mapsource); + ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(this, + android.R.layout.simple_spinner_item, + mapSourceNames.toArray(new String[mapSourceNames.size()])); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mapSourceSelector.setAdapter(adapter); + final int index = MapProviderFactory.getMapSources().indexOf(Settings.getMapSource()); + mapSourceSelector.setSelection(index); + mapSourceSelector.setOnItemSelectedListener(new ChangeMapSourceListener()); + + initMapDirectoryEdittext(false); + } + + private void initMapDirectoryEdittext(boolean setFocus) { + final EditText mapDirectoryEdit = (EditText) findViewById(R.id.map_directory); + mapDirectoryEdit.setText(Settings.getMapFileDirectory()); + if (setFocus) { + mapDirectoryEdit.requestFocus(); + } + } + + private void initThemefolderEdittext(boolean setFocus) { + EditText themeFileEdit = (EditText) findViewById(R.id.themefolder); + themeFileEdit.setText(Settings.getCustomRenderThemeBaseFolder()); + if (setFocus) { + themeFileEdit.requestFocus(); + } + } + + /** + * @param view + * unused here but needed since this method is referenced from XML layout + */ + public void backup(View view) { + // avoid overwriting an existing backup with an empty database (can happen directly after reinstalling the app) + if (cgData.getAllCachesCount() == 0) { + helpDialog(res.getString(R.string.init_backup), res.getString(R.string.init_backup_unnecessary)); + return; + } + + final ProgressDialog dialog = ProgressDialog.show(this, res.getString(R.string.init_backup), res.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(); + helpDialog(res.getString(R.string.init_backup_backup), + backupFileName != null ? res.getString(R.string.init_backup_success) + "\n" + backupFileName : res.getString(R.string.init_backup_failed)); + refreshBackupLabel(); + } + }); + } + }.start(); + } + + private void refreshBackupLabel() { + TextView lastBackup = (TextView) findViewById(R.id.backup_last); + File lastBackupFile = cgData.getRestoreFile(); + if (lastBackupFile != null) { + lastBackup.setText(res.getString(R.string.init_backup_last) + " " + Formatter.formatTime(lastBackupFile.lastModified()) + ", " + Formatter.formatDate(lastBackupFile.lastModified())); + } else { + lastBackup.setText(res.getString(R.string.init_backup_last_no)); + } + } + + private void refreshDbOnSDCardSetting() { + final CheckBox dbOnSDCardButton = (CheckBox) findViewById(R.id.dbonsdcard); + dbOnSDCardButton.setChecked(Settings.isDbOnSDCard()); + } + + /** + * @param view + * unused here but needed since this method is referenced from XML layout + */ + public void restore(View view) { + app.restoreDatabase(this); + } + + public boolean saveValues() { + String usernameNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.username)).getText().toString()); + String passwordNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.password)).getText().toString()); + String passvoteNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.passvote)).getText().toString()); + // don't trim signature, user may want to have whitespace at the beginning + String signatureNew = ((EditText) findViewById(R.id.signature)).getText().toString(); + String mapDirectoryNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.map_directory)).getText().toString()); + String themesDirectoryNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.themefolder)).getText().toString()); + + String altitudeNew = StringUtils.trimToNull(((EditText) findViewById(R.id.altitude)).getText().toString()); + int altitudeNewInt = parseNumber(altitudeNew, 0); + + TextView field = (TextView) findViewById(R.id.showwaypointsthreshold); + Settings.setShowWaypointsThreshold(parseNumber(field.getText().toString(), + Settings.SHOW_WP_THRESHOLD_DEFAULT)); + + final boolean status1 = Settings.setLogin(usernameNew, passwordNew); + final boolean status2 = Settings.setGCvoteLogin(passvoteNew); + final boolean status3 = Settings.setSignature(signatureNew); + final boolean status4 = Settings.setAltitudeCorrection(altitudeNewInt); + final boolean status5 = Settings.setMapFileDirectory(mapDirectoryNew); + final boolean status6 = Settings.setCustomRenderThemeBaseFolder(themesDirectoryNew); + + String importNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.gpx_importdir)).getText().toString()); + String exportNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.gpx_exportdir)).getText().toString()); + Settings.setGpxImportDir(importNew); + Settings.setGpxExportDir(exportNew); + + return status1 && status2 && status3 && status4 && status5 && status6; + } + + /** + * Returns the integer value from the string + * + * @param field + * the field to retrieve the integer value from + * @param defaultValue + * the default value + * @return either the field content or the default value + */ + + static private int parseNumber(final String number, int defaultValue) { + try { + return Integer.parseInt(number); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + private static class ChangeMapSourceListener implements OnItemSelectedListener { + + @Override + public void onItemSelected(AdapterView<?> arg0, View arg1, int position, + long arg3) { + Settings.setMapSource(MapProviderFactory.getMapSources().get(position)); + } + + @Override + public void onNothingSelected(AdapterView<?> arg0) { + arg0.setSelection(MapProviderFactory.getMapSources().indexOf(Settings.getMapSource())); + } + } + + private class LoginListener implements View.OnClickListener { + + @Override + public void onClick(View arg0) { + final String username = ((EditText) findViewById(R.id.username)).getText().toString(); + final String password = ((EditText) findViewById(R.id.password)).getText().toString(); + + if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) { + showToast(res.getString(R.string.err_missing_auth)); + return; + } + + loginDialog = ProgressDialog.show(SettingsActivity.this, + res.getString(R.string.init_login_popup), + res.getString(R.string.init_login_popup_working), true); + loginDialog.setCancelable(false); + + Settings.setLogin(username, password); + 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(); + } + } + + private class OCDEAuthorizeCgeoListener implements View.OnClickListener { + + @Override + public void onClick(View v) { + Intent authIntent = new Intent(SettingsActivity.this, OCAuthorizationActivity.class); + startActivity(authIntent); + } + } + + private class WebAuthListener implements View.OnClickListener { + + @Override + public void onClick(View arg0) { + final String deviceName = ((EditText) findViewById(R.id.webDeviceName)).getText().toString(); + final String deviceCode = Settings.getWebDeviceCode(); + + if (StringUtils.isBlank(deviceName)) { + showToast(res.getString(R.string.err_missing_device_name)); + return; + } + + webDialog = ProgressDialog.show(SettingsActivity.this, res.getString(R.string.init_sendToCgeo), res.getString(R.string.init_sendToCgeo_registering), true); + webDialog.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(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, final Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode != RESULT_OK) { + return; + } + + switch (requestCode) { + case SELECT_MAPFILE_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())) { + showToast(res.getString(R.string.warn_invalid_mapfile)); + } + } + updateMapSourceMenu(); + initMapDirectoryEdittext(true); + break; + case SELECT_GPX_EXPORT_REQUEST: + checkDirectory(resultCode, data, R.id.gpx_exportdir, new RunnableWithArgument<String>() { + + @Override + public void run(String directory) { + Settings.setGpxExportDir(directory); + } + }); + break; + case SELECT_GPX_IMPORT_REQUEST: + checkDirectory(resultCode, data, R.id.gpx_importdir, new RunnableWithArgument<String>() { + + @Override + public void run(String directory) { + Settings.setGpxImportDir(directory); + } + }); + break; + case SELECT_THEMEFOLDER_REQUEST: + checkDirectory(resultCode, data, R.id.themefolder, new RunnableWithArgument<String>() { + + @Override + public void run(String directory) { + Settings.setCustomRenderThemeBaseFolder(directory); + } + }); + break; + default: + throw new IllegalArgumentException(); + } + } + + private void checkDirectory(int resultCode, Intent data, int textField, RunnableWithArgument<String> runnableSetDir) { + if (resultCode != RESULT_OK) { + return; + } + final String directory = new File(data.getData().getPath()).getAbsolutePath(); + if (StringUtils.isNotBlank(directory)) { + runnableSetDir.run(directory); + EditText directoryText = (EditText) findViewById(textField); + directoryText.setText(directory); + directoryText.requestFocus(); + } + } + + private void selectDirectory(String startDirectory, int directoryKind) { + 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, res.getString(R.string.simple_dir_chooser_title)); + dirChooser.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, res.getString(android.R.string.ok)); + startActivityForResult(dirChooser, directoryKind); + } 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, directoryKind); + } + } + + public static void startActivity(Context fromActivity) { + final Intent initIntent = new Intent(fromActivity, SettingsActivity.class); + fromActivity.startActivity(initIntent); + } + +} 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; + } + +} |
