diff options
472 files changed, 17334 insertions, 7060 deletions
diff --git a/cgeo-calendar/.classpath b/cgeo-calendar/.classpath index 8191a2e..121b2d4 100644 --- a/cgeo-calendar/.classpath +++ b/cgeo-calendar/.classpath @@ -1,7 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src"/> - <classpathentry kind="src" path="gen"/> + <classpathentry kind="src" path="gen"> + <attributes> + <attribute name="ignore_optional_problems" value="true"/> + </attributes> + </classpathentry> <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> <classpathentry combineaccessrules="false" kind="src" path="/cgeo"/> diff --git a/cgeo-calendar/.settings/org.eclipse.jdt.core.prefs b/cgeo-calendar/.settings/org.eclipse.jdt.core.prefs index 78a085f..e3ed1f9 100644 --- a/cgeo-calendar/.settings/org.eclipse.jdt.core.prefs +++ b/cgeo-calendar/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,9 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve @@ -17,6 +22,7 @@ org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod= org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=warning org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled org.eclipse.jdt.core.compiler.problem.fieldHiding=warning @@ -30,7 +36,9 @@ org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled @@ -39,12 +47,17 @@ org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warni org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning @@ -58,7 +71,8 @@ org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning diff --git a/cgeo-calendar/AndroidManifest.xml b/cgeo-calendar/AndroidManifest.xml index b76a6d4..7c2d3a7 100644 --- a/cgeo-calendar/AndroidManifest.xml +++ b/cgeo-calendar/AndroidManifest.xml @@ -1,11 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - name="c:geo - calendar (add-on)" package="cgeo.calendar" android:versionCode="2" android:versionName="1.1" > - <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="8"/> + <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="13"/> <uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" /> @@ -18,7 +17,7 @@ <application android:icon="@drawable/ic_launcher" - android:label="@string/app_name" > + android:label="@string/app_name" android:allowBackup="false"> <activity android:label="@string/app_name" android:name=".CalendarActivity" diff --git a/cgeo-calendar/lint.xml b/cgeo-calendar/lint.xml new file mode 100644 index 0000000..a846461 --- /dev/null +++ b/cgeo-calendar/lint.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> + <issue id="MissingTranslation" severity="ignore" /> +</lint>
\ No newline at end of file diff --git a/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java b/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java index 99bd6d0..4912844 100644 --- a/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java @@ -16,10 +16,11 @@ abstract class AbstractAddEntry { void addEntryToCalendar() { try { addEntryToCalendarInternal(); + activity.showToast(R.string.event_success); } catch (Exception e) { activity.showToast(R.string.event_fail); - Log.e(CalendarActivity.LOG_TAG, "addToCalendar: " + e.toString()); + Log.e(CalendarActivity.LOG_TAG, "addToCalendar", e); } } diff --git a/cgeo-calendar/src/cgeo/calendar/AddEntry.java b/cgeo-calendar/src/cgeo/calendar/AddEntry.java index 39092cb..b1f97b9 100644 --- a/cgeo-calendar/src/cgeo/calendar/AddEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/AddEntry.java @@ -32,7 +32,7 @@ class AddEntry extends AbstractAddEntry { final ContentValues event = new ContentValues(); event.put("calendar_id", calendarId); if (entry.getStartTimeMinutes() >= 0) { - event.put("dtstart", eventDate.getTime() + entry.getStartTimeMinutes() * 60000); + event.put("dtstart", eventDate.getTime() + entry.getStartTimeMinutes() * 60000L); } else { event.put("dtstart", eventDate.getTime() + 43200000); // noon diff --git a/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java b/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java index 787be73..44453dd 100644 --- a/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java +++ b/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java @@ -35,7 +35,7 @@ class AddEntryLevel14 extends AbstractAddEntry { .putExtra("eventTimezone", "UTC") .putExtra("eventLocation", eventLocation); if (entry.getStartTimeMinutes() >= 0) { - intent.putExtra("beginTime", eventDate.getTime() + entry.getStartTimeMinutes() * 60000); + intent.putExtra("beginTime", eventDate.getTime() + entry.getStartTimeMinutes() * 60000L); } else { intent.putExtra("beginTime", eventDate.getTime() + 43200000); diff --git a/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java b/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java index b1c106d..b56e72f 100644 --- a/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java +++ b/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java @@ -13,7 +13,6 @@ import android.widget.Toast; public final class CalendarActivity extends Activity { static final String LOG_TAG = "cgeo.calendar"; - private Uri uri; /** Called when the activity is first created. */ @Override @@ -21,7 +20,7 @@ public final class CalendarActivity extends Activity { super.onCreate(savedInstanceState); try { - uri = getIntent().getData(); + final Uri uri = getIntent().getData(); if (uri == null) { finish(); return; diff --git a/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java b/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java index 6dddead..e31e054 100644 --- a/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java @@ -1,5 +1,9 @@ package cgeo.calendar; +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.CharEncoding; + import android.net.Uri; import android.text.Html; import android.text.Spanned; @@ -35,6 +39,7 @@ class CalendarEntry { try { this.startTimeMinutes = Integer.valueOf(startTime); } catch (NumberFormatException e) { + Log.e("CalendarEntry creation", e); } } } @@ -45,14 +50,15 @@ class CalendarEntry { if (param == null) { return ""; } - return URLDecoder.decode(param, "UTF-8").trim(); + return URLDecoder.decode(param, CharEncoding.UTF_8).trim(); } catch (UnsupportedEncodingException e) { + Log.e("CalendarEntry.getParameter", e); } return ""; } public boolean isValid() { - return (getName().length() > 0 && getHiddenDate().length() > 0); + return getName().length() > 0 && getHiddenDate().length() > 0; } public String getHiddenDate() { diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml index b07e0e7..d1a1e47 100644 --- a/main/AndroidManifest.xml +++ b/main/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="20121203" package="cgeo.geocaching" android:installLocation="auto"> - <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="8" /> + <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="13" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> @@ -139,8 +139,7 @@ </activity> <activity android:name=".VisitCacheActivity" - android:label="@string/app_name" - android:configChanges="keyboardHidden|orientation" > + android:label="@string/app_name"> </activity> <activity android:name=".LogTrackableActivity" @@ -180,7 +179,7 @@ </intent-filter> </activity> <activity - android:name=".cgeotrackable" + android:name="cgeo.geocaching.TrackableActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" > <intent-filter> @@ -204,8 +203,7 @@ </activity> <activity android:name=".cgeonavigate" - android:label="@string/app_name_compass" - android:screenOrientation="portrait"> + android:label="@string/app_name_compass"> </activity> <activity android:name=".cgeogpxes" diff --git a/main/lint.xml b/main/lint.xml new file mode 100644 index 0000000..dc32e31 --- /dev/null +++ b/main/lint.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> + <issue id="ContentDescription" severity="ignore" /> + <issue id="MissingTranslation" severity="ignore" /> +</lint>
\ No newline at end of file diff --git a/main/project.properties b/main/project.properties index 942b689..a475ee2 100644 --- a/main/project.properties +++ b/main/project.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=Google Inc.:Google APIs:11 +target=Google Inc.:Google APIs:17 diff --git a/main/project/rawimages/c_geo_icon_basic_512.png b/main/project/rawimages/c_geo_icon_basic_512.png Binary files differnew file mode 100644 index 0000000..c4a592f --- /dev/null +++ b/main/project/rawimages/c_geo_icon_basic_512.png diff --git a/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png b/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png Binary files differnew file mode 100644 index 0000000..1fab340 --- /dev/null +++ b/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png diff --git a/main/res/drawable-hdpi/cgeo.png b/main/res/drawable-hdpi/cgeo.png Binary files differindex a7d0d1b..6ac8672 100644 --- a/main/res/drawable-hdpi/cgeo.png +++ b/main/res/drawable-hdpi/cgeo.png diff --git a/main/res/drawable-hdpi/ic_menu_mylocation.png b/main/res/drawable-hdpi/ic_menu_mylocation.png Binary files differdeleted file mode 100644 index 1bcb0cd..0000000 --- a/main/res/drawable-hdpi/ic_menu_mylocation.png +++ /dev/null diff --git a/main/res/drawable-hdpi/marker_disabled_oc.png b/main/res/drawable-hdpi/marker_disabled_oc.png Binary files differnew file mode 100644 index 0000000..b759bbf --- /dev/null +++ b/main/res/drawable-hdpi/marker_disabled_oc.png diff --git a/main/res/drawable-hdpi/marker_disabled_other.png b/main/res/drawable-hdpi/marker_disabled_other.png Binary files differnew file mode 100644 index 0000000..748c3c6 --- /dev/null +++ b/main/res/drawable-hdpi/marker_disabled_other.png diff --git a/main/res/drawable-hdpi/marker_oc.png b/main/res/drawable-hdpi/marker_oc.png Binary files differnew file mode 100644 index 0000000..96f2987 --- /dev/null +++ b/main/res/drawable-hdpi/marker_oc.png diff --git a/main/res/drawable-hdpi/marker_other.png b/main/res/drawable-hdpi/marker_other.png Binary files differnew file mode 100644 index 0000000..94e170b --- /dev/null +++ b/main/res/drawable-hdpi/marker_other.png diff --git a/main/res/drawable-hdpi/marker_personalnote.png b/main/res/drawable-hdpi/marker_personalnote.png Binary files differindex 6014320..c9d7c91 100644 --- a/main/res/drawable-hdpi/marker_personalnote.png +++ b/main/res/drawable-hdpi/marker_personalnote.png diff --git a/main/res/drawable-hdpi/marker_usermodifiedcoords.png b/main/res/drawable-hdpi/marker_usermodifiedcoords.png Binary files differindex d537dfc..08fbf11 100644 --- a/main/res/drawable-hdpi/marker_usermodifiedcoords.png +++ b/main/res/drawable-hdpi/marker_usermodifiedcoords.png diff --git a/main/res/drawable/actionbar_cgeo.png b/main/res/drawable-mdpi/actionbar_cgeo.png Binary files differindex a89abf8..a89abf8 100644 --- a/main/res/drawable/actionbar_cgeo.png +++ b/main/res/drawable-mdpi/actionbar_cgeo.png diff --git a/main/res/drawable/actionbar_compass_dark.png b/main/res/drawable-mdpi/actionbar_compass_dark.png Binary files differindex 2f5c22b..2f5c22b 100644 --- a/main/res/drawable/actionbar_compass_dark.png +++ b/main/res/drawable-mdpi/actionbar_compass_dark.png diff --git a/main/res/drawable/actionbar_compass_light.png b/main/res/drawable-mdpi/actionbar_compass_light.png Binary files differindex fa50d54..fa50d54 100644 --- a/main/res/drawable/actionbar_compass_light.png +++ b/main/res/drawable-mdpi/actionbar_compass_light.png diff --git a/main/res/drawable/actionbar_home.png b/main/res/drawable-mdpi/actionbar_home.png Binary files differindex e109f0a..e109f0a 100644 --- a/main/res/drawable/actionbar_home.png +++ b/main/res/drawable-mdpi/actionbar_home.png diff --git a/main/res/drawable/actionbar_manual.png b/main/res/drawable-mdpi/actionbar_manual.png Binary files differindex a71acb3..a71acb3 100644 --- a/main/res/drawable/actionbar_manual.png +++ b/main/res/drawable-mdpi/actionbar_manual.png diff --git a/main/res/drawable/actionbar_map.png b/main/res/drawable-mdpi/actionbar_map.png Binary files differindex 80287d7..80287d7 100644 --- a/main/res/drawable/actionbar_map.png +++ b/main/res/drawable-mdpi/actionbar_map.png diff --git a/main/res/drawable/actionbar_mylocation_off.png b/main/res/drawable-mdpi/actionbar_mylocation_off.png Binary files differindex 1cdeeba..1cdeeba 100644 --- a/main/res/drawable/actionbar_mylocation_off.png +++ b/main/res/drawable-mdpi/actionbar_mylocation_off.png diff --git a/main/res/drawable/actionbar_mylocation_on.png b/main/res/drawable-mdpi/actionbar_mylocation_on.png Binary files differindex 1d1b625..1d1b625 100644 --- a/main/res/drawable/actionbar_mylocation_on.png +++ b/main/res/drawable-mdpi/actionbar_mylocation_on.png diff --git a/main/res/drawable/actionbar_search.png b/main/res/drawable-mdpi/actionbar_search.png Binary files differindex cce7789..cce7789 100644 --- a/main/res/drawable/actionbar_search.png +++ b/main/res/drawable-mdpi/actionbar_search.png diff --git a/main/res/drawable/attribute__strikethru.png b/main/res/drawable-mdpi/attribute__strikethru.png Binary files differindex 3f00745..3f00745 100644 --- a/main/res/drawable/attribute__strikethru.png +++ b/main/res/drawable-mdpi/attribute__strikethru.png diff --git a/main/res/drawable/attribute_abandonedbuilding.png b/main/res/drawable-mdpi/attribute_abandonedbuilding.png Binary files differindex 20be7ba..20be7ba 100644 --- a/main/res/drawable/attribute_abandonedbuilding.png +++ b/main/res/drawable-mdpi/attribute_abandonedbuilding.png diff --git a/main/res/drawable/attribute_available.png b/main/res/drawable-mdpi/attribute_available.png Binary files differindex c587fa7..c587fa7 100644 --- a/main/res/drawable/attribute_available.png +++ b/main/res/drawable-mdpi/attribute_available.png diff --git a/main/res/drawable/attribute_bicycles.png b/main/res/drawable-mdpi/attribute_bicycles.png Binary files differindex 53ea040..53ea040 100644 --- a/main/res/drawable/attribute_bicycles.png +++ b/main/res/drawable-mdpi/attribute_bicycles.png diff --git a/main/res/drawable/attribute_boat.png b/main/res/drawable-mdpi/attribute_boat.png Binary files differindex f4db083..f4db083 100644 --- a/main/res/drawable/attribute_boat.png +++ b/main/res/drawable-mdpi/attribute_boat.png diff --git a/main/res/drawable/attribute_campfires.png b/main/res/drawable-mdpi/attribute_campfires.png Binary files differindex 229bb40..229bb40 100644 --- a/main/res/drawable/attribute_campfires.png +++ b/main/res/drawable-mdpi/attribute_campfires.png diff --git a/main/res/drawable/attribute_camping.png b/main/res/drawable-mdpi/attribute_camping.png Binary files differindex 15f2891..15f2891 100644 --- a/main/res/drawable/attribute_camping.png +++ b/main/res/drawable-mdpi/attribute_camping.png diff --git a/main/res/drawable/attribute_cliff.png b/main/res/drawable-mdpi/attribute_cliff.png Binary files differindex 31b6921..31b6921 100644 --- a/main/res/drawable/attribute_cliff.png +++ b/main/res/drawable-mdpi/attribute_cliff.png diff --git a/main/res/drawable/attribute_climbing.png b/main/res/drawable-mdpi/attribute_climbing.png Binary files differindex 585b841..585b841 100644 --- a/main/res/drawable/attribute_climbing.png +++ b/main/res/drawable-mdpi/attribute_climbing.png diff --git a/main/res/drawable/attribute_cow.png b/main/res/drawable-mdpi/attribute_cow.png Binary files differindex 2a2a2ce..2a2a2ce 100644 --- a/main/res/drawable/attribute_cow.png +++ b/main/res/drawable-mdpi/attribute_cow.png diff --git a/main/res/drawable/attribute_danger.png b/main/res/drawable-mdpi/attribute_danger.png Binary files differindex 25e0fe0..25e0fe0 100644 --- a/main/res/drawable/attribute_danger.png +++ b/main/res/drawable-mdpi/attribute_danger.png diff --git a/main/res/drawable/attribute_dangerousanimals.png b/main/res/drawable-mdpi/attribute_dangerousanimals.png Binary files differindex 9ba4ea4..9ba4ea4 100644 --- a/main/res/drawable/attribute_dangerousanimals.png +++ b/main/res/drawable-mdpi/attribute_dangerousanimals.png diff --git a/main/res/drawable/attribute_dogs.png b/main/res/drawable-mdpi/attribute_dogs.png Binary files differindex f7f0628..f7f0628 100644 --- a/main/res/drawable/attribute_dogs.png +++ b/main/res/drawable-mdpi/attribute_dogs.png diff --git a/main/res/drawable/attribute_fee.png b/main/res/drawable-mdpi/attribute_fee.png Binary files differindex aa0c950..aa0c950 100644 --- a/main/res/drawable/attribute_fee.png +++ b/main/res/drawable-mdpi/attribute_fee.png diff --git a/main/res/drawable/attribute_field_puzzle.png b/main/res/drawable-mdpi/attribute_field_puzzle.png Binary files differindex e524761..e524761 100644 --- a/main/res/drawable/attribute_field_puzzle.png +++ b/main/res/drawable-mdpi/attribute_field_puzzle.png diff --git a/main/res/drawable/attribute_firstaid.png b/main/res/drawable-mdpi/attribute_firstaid.png Binary files differindex 2c2433f..2c2433f 100644 --- a/main/res/drawable/attribute_firstaid.png +++ b/main/res/drawable-mdpi/attribute_firstaid.png diff --git a/main/res/drawable/attribute_flashlight.png b/main/res/drawable-mdpi/attribute_flashlight.png Binary files differindex c4b68d4..c4b68d4 100644 --- a/main/res/drawable/attribute_flashlight.png +++ b/main/res/drawable-mdpi/attribute_flashlight.png diff --git a/main/res/drawable/attribute_food.png b/main/res/drawable-mdpi/attribute_food.png Binary files differindex d14902c..d14902c 100644 --- a/main/res/drawable/attribute_food.png +++ b/main/res/drawable-mdpi/attribute_food.png diff --git a/main/res/drawable/attribute_frontyard.png b/main/res/drawable-mdpi/attribute_frontyard.png Binary files differindex 40affd2..40affd2 100644 --- a/main/res/drawable/attribute_frontyard.png +++ b/main/res/drawable-mdpi/attribute_frontyard.png diff --git a/main/res/drawable/attribute_fuel.png b/main/res/drawable-mdpi/attribute_fuel.png Binary files differindex 363ea34..363ea34 100644 --- a/main/res/drawable/attribute_fuel.png +++ b/main/res/drawable-mdpi/attribute_fuel.png diff --git a/main/res/drawable/attribute_hike_long.png b/main/res/drawable-mdpi/attribute_hike_long.png Binary files differindex 70ca001..70ca001 100644 --- a/main/res/drawable/attribute_hike_long.png +++ b/main/res/drawable-mdpi/attribute_hike_long.png diff --git a/main/res/drawable/attribute_hike_med.png b/main/res/drawable-mdpi/attribute_hike_med.png Binary files differindex d368721..d368721 100644 --- a/main/res/drawable/attribute_hike_med.png +++ b/main/res/drawable-mdpi/attribute_hike_med.png diff --git a/main/res/drawable/attribute_hike_short.png b/main/res/drawable-mdpi/attribute_hike_short.png Binary files differindex ce421ae..ce421ae 100644 --- a/main/res/drawable/attribute_hike_short.png +++ b/main/res/drawable-mdpi/attribute_hike_short.png diff --git a/main/res/drawable/attribute_hiking.png b/main/res/drawable-mdpi/attribute_hiking.png Binary files differindex 1579be0..1579be0 100644 --- a/main/res/drawable/attribute_hiking.png +++ b/main/res/drawable-mdpi/attribute_hiking.png diff --git a/main/res/drawable/attribute_horses.png b/main/res/drawable-mdpi/attribute_horses.png Binary files differindex 171a70f..171a70f 100644 --- a/main/res/drawable/attribute_horses.png +++ b/main/res/drawable-mdpi/attribute_horses.png diff --git a/main/res/drawable/attribute_hunting.png b/main/res/drawable-mdpi/attribute_hunting.png Binary files differindex 816ad49..816ad49 100644 --- a/main/res/drawable/attribute_hunting.png +++ b/main/res/drawable-mdpi/attribute_hunting.png diff --git a/main/res/drawable/attribute_icon_not_found.png b/main/res/drawable-mdpi/attribute_icon_not_found.png Binary files differindex 33e0ce2..33e0ce2 100644 --- a/main/res/drawable/attribute_icon_not_found.png +++ b/main/res/drawable-mdpi/attribute_icon_not_found.png diff --git a/main/res/drawable/attribute_jeeps.png b/main/res/drawable-mdpi/attribute_jeeps.png Binary files differindex e2cec60..e2cec60 100644 --- a/main/res/drawable/attribute_jeeps.png +++ b/main/res/drawable-mdpi/attribute_jeeps.png diff --git a/main/res/drawable/attribute_kids.png b/main/res/drawable-mdpi/attribute_kids.png Binary files differindex f322f5b..f322f5b 100644 --- a/main/res/drawable/attribute_kids.png +++ b/main/res/drawable-mdpi/attribute_kids.png diff --git a/main/res/drawable/attribute_landf.png b/main/res/drawable-mdpi/attribute_landf.png Binary files differindex 1b27327..1b27327 100644 --- a/main/res/drawable/attribute_landf.png +++ b/main/res/drawable-mdpi/attribute_landf.png diff --git a/main/res/drawable/attribute_mine.png b/main/res/drawable-mdpi/attribute_mine.png Binary files differindex 221e210..221e210 100644 --- a/main/res/drawable/attribute_mine.png +++ b/main/res/drawable-mdpi/attribute_mine.png diff --git a/main/res/drawable/attribute_motorcycles.png b/main/res/drawable-mdpi/attribute_motorcycles.png Binary files differindex adf0abb..adf0abb 100644 --- a/main/res/drawable/attribute_motorcycles.png +++ b/main/res/drawable-mdpi/attribute_motorcycles.png diff --git a/main/res/drawable/attribute_night.png b/main/res/drawable-mdpi/attribute_night.png Binary files differindex 416d965..416d965 100644 --- a/main/res/drawable/attribute_night.png +++ b/main/res/drawable-mdpi/attribute_night.png diff --git a/main/res/drawable/attribute_nightcache.png b/main/res/drawable-mdpi/attribute_nightcache.png Binary files differindex 6163808..6163808 100644 --- a/main/res/drawable/attribute_nightcache.png +++ b/main/res/drawable-mdpi/attribute_nightcache.png diff --git a/main/res/drawable/attribute_onehour.png b/main/res/drawable-mdpi/attribute_onehour.png Binary files differindex eb28014..eb28014 100644 --- a/main/res/drawable/attribute_onehour.png +++ b/main/res/drawable-mdpi/attribute_onehour.png diff --git a/main/res/drawable/attribute_parking.png b/main/res/drawable-mdpi/attribute_parking.png Binary files differindex 26e43cc..26e43cc 100644 --- a/main/res/drawable/attribute_parking.png +++ b/main/res/drawable-mdpi/attribute_parking.png diff --git a/main/res/drawable/attribute_parkngrab.png b/main/res/drawable-mdpi/attribute_parkngrab.png Binary files differindex 8cc4fcc..8cc4fcc 100644 --- a/main/res/drawable/attribute_parkngrab.png +++ b/main/res/drawable-mdpi/attribute_parkngrab.png diff --git a/main/res/drawable/attribute_partnership.png b/main/res/drawable-mdpi/attribute_partnership.png Binary files differindex 228c009..228c009 100644 --- a/main/res/drawable/attribute_partnership.png +++ b/main/res/drawable-mdpi/attribute_partnership.png diff --git a/main/res/drawable/attribute_phone.png b/main/res/drawable-mdpi/attribute_phone.png Binary files differindex 1225f2b..1225f2b 100644 --- a/main/res/drawable/attribute_phone.png +++ b/main/res/drawable-mdpi/attribute_phone.png diff --git a/main/res/drawable/attribute_picnic.png b/main/res/drawable-mdpi/attribute_picnic.png Binary files differindex 88229ea..88229ea 100644 --- a/main/res/drawable/attribute_picnic.png +++ b/main/res/drawable-mdpi/attribute_picnic.png diff --git a/main/res/drawable/attribute_poisonoak.png b/main/res/drawable-mdpi/attribute_poisonoak.png Binary files differindex 7112410..7112410 100644 --- a/main/res/drawable/attribute_poisonoak.png +++ b/main/res/drawable-mdpi/attribute_poisonoak.png diff --git a/main/res/drawable/attribute_public.png b/main/res/drawable-mdpi/attribute_public.png Binary files differindex 5fcf129..5fcf129 100644 --- a/main/res/drawable/attribute_public.png +++ b/main/res/drawable-mdpi/attribute_public.png diff --git a/main/res/drawable/attribute_quads.png b/main/res/drawable-mdpi/attribute_quads.png Binary files differindex 844657c..844657c 100644 --- a/main/res/drawable/attribute_quads.png +++ b/main/res/drawable-mdpi/attribute_quads.png diff --git a/main/res/drawable/attribute_rappelling.png b/main/res/drawable-mdpi/attribute_rappelling.png Binary files differindex c97d891..c97d891 100644 --- a/main/res/drawable/attribute_rappelling.png +++ b/main/res/drawable-mdpi/attribute_rappelling.png diff --git a/main/res/drawable/attribute_restrooms.png b/main/res/drawable-mdpi/attribute_restrooms.png Binary files differindex 0d1a841..0d1a841 100644 --- a/main/res/drawable/attribute_restrooms.png +++ b/main/res/drawable-mdpi/attribute_restrooms.png diff --git a/main/res/drawable/attribute_rv.png b/main/res/drawable-mdpi/attribute_rv.png Binary files differindex c344108..c344108 100644 --- a/main/res/drawable/attribute_rv.png +++ b/main/res/drawable-mdpi/attribute_rv.png diff --git a/main/res/drawable/attribute_s_tool.png b/main/res/drawable-mdpi/attribute_s_tool.png Binary files differindex 5ce3a92..5ce3a92 100644 --- a/main/res/drawable/attribute_s_tool.png +++ b/main/res/drawable-mdpi/attribute_s_tool.png diff --git a/main/res/drawable/attribute_scenic.png b/main/res/drawable-mdpi/attribute_scenic.png Binary files differindex f800b40..f800b40 100644 --- a/main/res/drawable/attribute_scenic.png +++ b/main/res/drawable-mdpi/attribute_scenic.png diff --git a/main/res/drawable/attribute_scuba.png b/main/res/drawable-mdpi/attribute_scuba.png Binary files differindex 2fa5faa..2fa5faa 100644 --- a/main/res/drawable/attribute_scuba.png +++ b/main/res/drawable-mdpi/attribute_scuba.png diff --git a/main/res/drawable/attribute_seasonal.png b/main/res/drawable-mdpi/attribute_seasonal.png Binary files differindex 8046ebf..8046ebf 100644 --- a/main/res/drawable/attribute_seasonal.png +++ b/main/res/drawable-mdpi/attribute_seasonal.png diff --git a/main/res/drawable/attribute_skiis.png b/main/res/drawable-mdpi/attribute_skiis.png Binary files differindex 5589442..5589442 100644 --- a/main/res/drawable/attribute_skiis.png +++ b/main/res/drawable-mdpi/attribute_skiis.png diff --git a/main/res/drawable/attribute_snowmobiles.png b/main/res/drawable-mdpi/attribute_snowmobiles.png Binary files differindex 412046e..412046e 100644 --- a/main/res/drawable/attribute_snowmobiles.png +++ b/main/res/drawable-mdpi/attribute_snowmobiles.png diff --git a/main/res/drawable/attribute_snowshoes.png b/main/res/drawable-mdpi/attribute_snowshoes.png Binary files differindex 1da4519..1da4519 100644 --- a/main/res/drawable/attribute_snowshoes.png +++ b/main/res/drawable-mdpi/attribute_snowshoes.png diff --git a/main/res/drawable/attribute_stealth.png b/main/res/drawable-mdpi/attribute_stealth.png Binary files differindex d6d04e1..d6d04e1 100644 --- a/main/res/drawable/attribute_stealth.png +++ b/main/res/drawable-mdpi/attribute_stealth.png diff --git a/main/res/drawable/attribute_stroller.png b/main/res/drawable-mdpi/attribute_stroller.png Binary files differindex f8309b2..f8309b2 100644 --- a/main/res/drawable/attribute_stroller.png +++ b/main/res/drawable-mdpi/attribute_stroller.png diff --git a/main/res/drawable/attribute_swimming.png b/main/res/drawable-mdpi/attribute_swimming.png Binary files differindex 0768b9e..0768b9e 100644 --- a/main/res/drawable/attribute_swimming.png +++ b/main/res/drawable-mdpi/attribute_swimming.png diff --git a/main/res/drawable/attribute_teamwork.png b/main/res/drawable-mdpi/attribute_teamwork.png Binary files differindex ee0df0b..ee0df0b 100644 --- a/main/res/drawable/attribute_teamwork.png +++ b/main/res/drawable-mdpi/attribute_teamwork.png diff --git a/main/res/drawable/attribute_thorn.png b/main/res/drawable-mdpi/attribute_thorn.png Binary files differindex 1800f87..1800f87 100644 --- a/main/res/drawable/attribute_thorn.png +++ b/main/res/drawable-mdpi/attribute_thorn.png diff --git a/main/res/drawable/attribute_ticks.png b/main/res/drawable-mdpi/attribute_ticks.png Binary files differindex 65108a3..65108a3 100644 --- a/main/res/drawable/attribute_ticks.png +++ b/main/res/drawable-mdpi/attribute_ticks.png diff --git a/main/res/drawable/attribute_touristok.png b/main/res/drawable-mdpi/attribute_touristok.png Binary files differindex f264340..f264340 100644 --- a/main/res/drawable/attribute_touristok.png +++ b/main/res/drawable-mdpi/attribute_touristok.png diff --git a/main/res/drawable/attribute_treeclimbing.png b/main/res/drawable-mdpi/attribute_treeclimbing.png Binary files differindex c2623a3..c2623a3 100644 --- a/main/res/drawable/attribute_treeclimbing.png +++ b/main/res/drawable-mdpi/attribute_treeclimbing.png diff --git a/main/res/drawable/attribute_uv.png b/main/res/drawable-mdpi/attribute_uv.png Binary files differindex 859478e..859478e 100644 --- a/main/res/drawable/attribute_uv.png +++ b/main/res/drawable-mdpi/attribute_uv.png diff --git a/main/res/drawable/attribute_wading.png b/main/res/drawable-mdpi/attribute_wading.png Binary files differindex 653bfdc..653bfdc 100644 --- a/main/res/drawable/attribute_wading.png +++ b/main/res/drawable-mdpi/attribute_wading.png diff --git a/main/res/drawable/attribute_water.png b/main/res/drawable-mdpi/attribute_water.png Binary files differindex 59ba217..59ba217 100644 --- a/main/res/drawable/attribute_water.png +++ b/main/res/drawable-mdpi/attribute_water.png diff --git a/main/res/drawable/attribute_wheelchair.png b/main/res/drawable-mdpi/attribute_wheelchair.png Binary files differindex c6fccd1..c6fccd1 100644 --- a/main/res/drawable/attribute_wheelchair.png +++ b/main/res/drawable-mdpi/attribute_wheelchair.png diff --git a/main/res/drawable/attribute_winter.png b/main/res/drawable-mdpi/attribute_winter.png Binary files differindex 29d7421..29d7421 100644 --- a/main/res/drawable/attribute_winter.png +++ b/main/res/drawable-mdpi/attribute_winter.png diff --git a/main/res/drawable/attribute_wirelessbeacon.png b/main/res/drawable-mdpi/attribute_wirelessbeacon.png Binary files differindex a3b05c1..a3b05c1 100644 --- a/main/res/drawable/attribute_wirelessbeacon.png +++ b/main/res/drawable-mdpi/attribute_wirelessbeacon.png diff --git a/main/res/drawable/cgeo.png b/main/res/drawable-mdpi/cgeo.png Binary files differindex 126feb3..126feb3 100644 --- a/main/res/drawable/cgeo.png +++ b/main/res/drawable-mdpi/cgeo.png diff --git a/main/res/drawable/cgeo_logo.png b/main/res/drawable-mdpi/cgeo_logo.png Binary files differindex 0d8654f..0d8654f 100644 --- a/main/res/drawable/cgeo_logo.png +++ b/main/res/drawable-mdpi/cgeo_logo.png diff --git a/main/res/drawable/compass_arrow.png b/main/res/drawable-mdpi/compass_arrow.png Binary files differindex a6524d9..a6524d9 100644 --- a/main/res/drawable/compass_arrow.png +++ b/main/res/drawable-mdpi/compass_arrow.png diff --git a/main/res/drawable/compass_arrow_mini_black.png b/main/res/drawable-mdpi/compass_arrow_mini_black.png Binary files differindex 682f067..682f067 100644 --- a/main/res/drawable/compass_arrow_mini_black.png +++ b/main/res/drawable-mdpi/compass_arrow_mini_black.png diff --git a/main/res/drawable/compass_arrow_mini_white.png b/main/res/drawable-mdpi/compass_arrow_mini_white.png Binary files differindex 2b11847..2b11847 100644 --- a/main/res/drawable/compass_arrow_mini_white.png +++ b/main/res/drawable-mdpi/compass_arrow_mini_white.png diff --git a/main/res/drawable/compass_overlay.png b/main/res/drawable-mdpi/compass_overlay.png Binary files differindex 98b8fd6..98b8fd6 100644 --- a/main/res/drawable/compass_overlay.png +++ b/main/res/drawable-mdpi/compass_overlay.png diff --git a/main/res/drawable/compass_rose.png b/main/res/drawable-mdpi/compass_rose.png Binary files differindex 08e2c8c..08e2c8c 100644 --- a/main/res/drawable/compass_rose.png +++ b/main/res/drawable-mdpi/compass_rose.png diff --git a/main/res/drawable/compass_underlay.png b/main/res/drawable-mdpi/compass_underlay.png Binary files differindex 7b19442..7b19442 100644 --- a/main/res/drawable/compass_underlay.png +++ b/main/res/drawable-mdpi/compass_underlay.png diff --git a/main/res/drawable/helper_barcode.png b/main/res/drawable-mdpi/helper_barcode.png Binary files differindex 0b56af3..0b56af3 100644 --- a/main/res/drawable/helper_barcode.png +++ b/main/res/drawable-mdpi/helper_barcode.png diff --git a/main/res/drawable/helper_bluetoothgps.png b/main/res/drawable-mdpi/helper_bluetoothgps.png Binary files differindex ecae5ee..ecae5ee 100644 --- a/main/res/drawable/helper_bluetoothgps.png +++ b/main/res/drawable-mdpi/helper_bluetoothgps.png diff --git a/main/res/drawable/helper_gpsstatus.png b/main/res/drawable-mdpi/helper_gpsstatus.png Binary files differindex 07c6419..07c6419 100644 --- a/main/res/drawable/helper_gpsstatus.png +++ b/main/res/drawable-mdpi/helper_gpsstatus.png diff --git a/main/res/drawable/helper_locus.png b/main/res/drawable-mdpi/helper_locus.png Binary files differindex 836bb4e..836bb4e 100644 --- a/main/res/drawable/helper_locus.png +++ b/main/res/drawable-mdpi/helper_locus.png diff --git a/main/res/drawable/helper_manual.png b/main/res/drawable-mdpi/helper_manual.png Binary files differindex c3c43db..c3c43db 100644 --- a/main/res/drawable/helper_manual.png +++ b/main/res/drawable-mdpi/helper_manual.png diff --git a/main/res/drawable/ic_menu_add.png b/main/res/drawable-mdpi/ic_menu_add.png Binary files differindex 6752bfd..6752bfd 100644 --- a/main/res/drawable/ic_menu_add.png +++ b/main/res/drawable-mdpi/ic_menu_add.png diff --git a/main/res/drawable/ic_menu_agenda.png b/main/res/drawable-mdpi/ic_menu_agenda.png Binary files differindex 9f2c1dc..9f2c1dc 100644 --- a/main/res/drawable/ic_menu_agenda.png +++ b/main/res/drawable-mdpi/ic_menu_agenda.png diff --git a/main/res/drawable/ic_menu_barcode.png b/main/res/drawable-mdpi/ic_menu_barcode.png Binary files differindex abc13cc..abc13cc 100644 --- a/main/res/drawable/ic_menu_barcode.png +++ b/main/res/drawable-mdpi/ic_menu_barcode.png diff --git a/main/res/drawable/ic_menu_circle.png b/main/res/drawable-mdpi/ic_menu_circle.png Binary files differindex a3a26f9..a3a26f9 100644 --- a/main/res/drawable/ic_menu_circle.png +++ b/main/res/drawable-mdpi/ic_menu_circle.png diff --git a/main/res/drawable/ic_menu_clear_playlist.png b/main/res/drawable-mdpi/ic_menu_clear_playlist.png Binary files differindex 750db62..750db62 100644 --- a/main/res/drawable/ic_menu_clear_playlist.png +++ b/main/res/drawable-mdpi/ic_menu_clear_playlist.png diff --git a/main/res/drawable/ic_menu_compass.png b/main/res/drawable-mdpi/ic_menu_compass.png Binary files differindex 7717dde..7717dde 100644 --- a/main/res/drawable/ic_menu_compass.png +++ b/main/res/drawable-mdpi/ic_menu_compass.png diff --git a/main/res/drawable/ic_menu_delete.png b/main/res/drawable-mdpi/ic_menu_delete.png Binary files differindex 7d95494..7d95494 100644 --- a/main/res/drawable/ic_menu_delete.png +++ b/main/res/drawable-mdpi/ic_menu_delete.png diff --git a/main/res/drawable/ic_menu_edit.png b/main/res/drawable-mdpi/ic_menu_edit.png Binary files differindex 41a9c2e..41a9c2e 100644 --- a/main/res/drawable/ic_menu_edit.png +++ b/main/res/drawable-mdpi/ic_menu_edit.png diff --git a/main/res/drawable/ic_menu_emoticons.png b/main/res/drawable-mdpi/ic_menu_emoticons.png Binary files differindex 765000b..765000b 100644 --- a/main/res/drawable/ic_menu_emoticons.png +++ b/main/res/drawable-mdpi/ic_menu_emoticons.png diff --git a/main/res/drawable/ic_menu_filter.png b/main/res/drawable-mdpi/ic_menu_filter.png Binary files differindex 84176c5..84176c5 100644 --- a/main/res/drawable/ic_menu_filter.png +++ b/main/res/drawable-mdpi/ic_menu_filter.png diff --git a/main/res/drawable/ic_menu_globe.png b/main/res/drawable-mdpi/ic_menu_globe.png Binary files differindex cd283ab..cd283ab 100644 --- a/main/res/drawable/ic_menu_globe.png +++ b/main/res/drawable-mdpi/ic_menu_globe.png diff --git a/main/res/drawable/ic_menu_info_details.png b/main/res/drawable-mdpi/ic_menu_info_details.png Binary files differindex 1786d1e..1786d1e 100644 --- a/main/res/drawable/ic_menu_info_details.png +++ b/main/res/drawable-mdpi/ic_menu_info_details.png diff --git a/main/res/drawable/ic_menu_mapmode.png b/main/res/drawable-mdpi/ic_menu_mapmode.png Binary files differindex d85cab5..d85cab5 100644 --- a/main/res/drawable/ic_menu_mapmode.png +++ b/main/res/drawable-mdpi/ic_menu_mapmode.png diff --git a/main/res/drawable/ic_menu_mark.png b/main/res/drawable-mdpi/ic_menu_mark.png Binary files differindex 5e95da7..5e95da7 100644 --- a/main/res/drawable/ic_menu_mark.png +++ b/main/res/drawable-mdpi/ic_menu_mark.png diff --git a/main/res/drawable/ic_menu_myplaces.png b/main/res/drawable-mdpi/ic_menu_myplaces.png Binary files differindex 06f11ba..06f11ba 100644 --- a/main/res/drawable/ic_menu_myplaces.png +++ b/main/res/drawable-mdpi/ic_menu_myplaces.png diff --git a/main/res/drawable/ic_menu_preferences.png b/main/res/drawable-mdpi/ic_menu_preferences.png Binary files differindex 60dbff6..60dbff6 100644 --- a/main/res/drawable/ic_menu_preferences.png +++ b/main/res/drawable-mdpi/ic_menu_preferences.png diff --git a/main/res/drawable/ic_menu_recent_history.png b/main/res/drawable-mdpi/ic_menu_recent_history.png Binary files differindex 4ccae5d..4ccae5d 100644 --- a/main/res/drawable/ic_menu_recent_history.png +++ b/main/res/drawable-mdpi/ic_menu_recent_history.png diff --git a/main/res/drawable/ic_menu_refresh.png b/main/res/drawable-mdpi/ic_menu_refresh.png Binary files differindex 77d70dd..77d70dd 100644 --- a/main/res/drawable/ic_menu_refresh.png +++ b/main/res/drawable-mdpi/ic_menu_refresh.png diff --git a/main/res/drawable/ic_menu_rotate.png b/main/res/drawable-mdpi/ic_menu_rotate.png Binary files differindex 27368b2..27368b2 100644 --- a/main/res/drawable/ic_menu_rotate.png +++ b/main/res/drawable-mdpi/ic_menu_rotate.png diff --git a/main/res/drawable/ic_menu_save.png b/main/res/drawable-mdpi/ic_menu_save.png Binary files differindex 36d50b3..36d50b3 100644 --- a/main/res/drawable/ic_menu_save.png +++ b/main/res/drawable-mdpi/ic_menu_save.png diff --git a/main/res/drawable/ic_menu_set_as.png b/main/res/drawable-mdpi/ic_menu_set_as.png Binary files differindex cb9dc49..cb9dc49 100644 --- a/main/res/drawable/ic_menu_set_as.png +++ b/main/res/drawable-mdpi/ic_menu_set_as.png diff --git a/main/res/drawable/ic_menu_share.png b/main/res/drawable-mdpi/ic_menu_share.png Binary files differindex 44db9b1..44db9b1 100644 --- a/main/res/drawable/ic_menu_share.png +++ b/main/res/drawable-mdpi/ic_menu_share.png diff --git a/main/res/drawable/ic_menu_shopping.png b/main/res/drawable-mdpi/ic_menu_shopping.png Binary files differindex 7088155..7088155 100644 --- a/main/res/drawable/ic_menu_shopping.png +++ b/main/res/drawable-mdpi/ic_menu_shopping.png diff --git a/main/res/drawable/ic_menu_sort_alphabetically.png b/main/res/drawable-mdpi/ic_menu_sort_alphabetically.png Binary files differindex 2583eb8..2583eb8 100644 --- a/main/res/drawable/ic_menu_sort_alphabetically.png +++ b/main/res/drawable-mdpi/ic_menu_sort_alphabetically.png diff --git a/main/res/drawable/ic_menu_sort_by_size.png b/main/res/drawable-mdpi/ic_menu_sort_by_size.png Binary files differindex 65e2786..65e2786 100644 --- a/main/res/drawable/ic_menu_sort_by_size.png +++ b/main/res/drawable-mdpi/ic_menu_sort_by_size.png diff --git a/main/res/drawable/ic_menu_trail.png b/main/res/drawable-mdpi/ic_menu_trail.png Binary files differindex 34abeab..34abeab 100644 --- a/main/res/drawable/ic_menu_trail.png +++ b/main/res/drawable-mdpi/ic_menu_trail.png diff --git a/main/res/drawable/image_no_placement.png b/main/res/drawable-mdpi/image_no_placement.png Binary files differindex d73f7c7..d73f7c7 100644 --- a/main/res/drawable/image_no_placement.png +++ b/main/res/drawable-mdpi/image_no_placement.png diff --git a/main/res/drawable/image_not_loaded.png b/main/res/drawable-mdpi/image_not_loaded.png Binary files differindex ce7c6d8..ce7c6d8 100644 --- a/main/res/drawable/image_not_loaded.png +++ b/main/res/drawable-mdpi/image_not_loaded.png diff --git a/main/res/drawable/log_img_dark.png b/main/res/drawable-mdpi/log_img_dark.png Binary files differindex b30db2c..b30db2c 100644 --- a/main/res/drawable/log_img_dark.png +++ b/main/res/drawable-mdpi/log_img_dark.png diff --git a/main/res/drawable/log_img_light.png b/main/res/drawable-mdpi/log_img_light.png Binary files differindex a4ad4dd..a4ad4dd 100644 --- a/main/res/drawable/log_img_light.png +++ b/main/res/drawable-mdpi/log_img_light.png diff --git a/main/res/drawable/main_any_default.png b/main/res/drawable-mdpi/main_any_default.png Binary files differindex cea3288..cea3288 100644 --- a/main/res/drawable/main_any_default.png +++ b/main/res/drawable-mdpi/main_any_default.png diff --git a/main/res/drawable/main_filter_default.png b/main/res/drawable-mdpi/main_filter_default.png Binary files differindex 996d15b..996d15b 100644 --- a/main/res/drawable/main_filter_default.png +++ b/main/res/drawable-mdpi/main_filter_default.png diff --git a/main/res/drawable/main_live_default.png b/main/res/drawable-mdpi/main_live_default.png Binary files differindex f2cc262..f2cc262 100644 --- a/main/res/drawable/main_live_default.png +++ b/main/res/drawable-mdpi/main_live_default.png diff --git a/main/res/drawable/main_nearby_default.png b/main/res/drawable-mdpi/main_nearby_default.png Binary files differindex 9166267..9166267 100644 --- a/main/res/drawable/main_nearby_default.png +++ b/main/res/drawable-mdpi/main_nearby_default.png diff --git a/main/res/drawable/main_nearby_disabled.png b/main/res/drawable-mdpi/main_nearby_disabled.png Binary files differindex 8980b9f..8980b9f 100644 --- a/main/res/drawable/main_nearby_disabled.png +++ b/main/res/drawable-mdpi/main_nearby_disabled.png diff --git a/main/res/drawable/main_search_default.png b/main/res/drawable-mdpi/main_search_default.png Binary files differindex c3c1fdc..c3c1fdc 100644 --- a/main/res/drawable/main_search_default.png +++ b/main/res/drawable-mdpi/main_search_default.png diff --git a/main/res/drawable/main_stored_default.png b/main/res/drawable-mdpi/main_stored_default.png Binary files differindex b595723..b595723 100644 --- a/main/res/drawable/main_stored_default.png +++ b/main/res/drawable-mdpi/main_stored_default.png diff --git a/main/res/drawable/marker.png b/main/res/drawable-mdpi/marker.png Binary files differindex f6e0e10..f6e0e10 100644 --- a/main/res/drawable/marker.png +++ b/main/res/drawable-mdpi/marker.png diff --git a/main/res/drawable/marker_disabled.png b/main/res/drawable-mdpi/marker_disabled.png Binary files differindex 6e1c17b..6e1c17b 100644 --- a/main/res/drawable/marker_disabled.png +++ b/main/res/drawable-mdpi/marker_disabled.png diff --git a/main/res/drawable-mdpi/marker_disabled_oc.png b/main/res/drawable-mdpi/marker_disabled_oc.png Binary files differnew file mode 100644 index 0000000..36f2d5b --- /dev/null +++ b/main/res/drawable-mdpi/marker_disabled_oc.png diff --git a/main/res/drawable-mdpi/marker_disabled_other.png b/main/res/drawable-mdpi/marker_disabled_other.png Binary files differnew file mode 100644 index 0000000..52ae651 --- /dev/null +++ b/main/res/drawable-mdpi/marker_disabled_other.png diff --git a/main/res/drawable/marker_found.png b/main/res/drawable-mdpi/marker_found.png Binary files differindex aa8b154..aa8b154 100644 --- a/main/res/drawable/marker_found.png +++ b/main/res/drawable-mdpi/marker_found.png diff --git a/main/res/drawable/marker_found_offline.png b/main/res/drawable-mdpi/marker_found_offline.png Binary files differindex 823e972..823e972 100644 --- a/main/res/drawable/marker_found_offline.png +++ b/main/res/drawable-mdpi/marker_found_offline.png diff --git a/main/res/drawable/marker_notreliable.png b/main/res/drawable-mdpi/marker_notreliable.png Binary files differindex fced841..fced841 100644 --- a/main/res/drawable/marker_notreliable.png +++ b/main/res/drawable-mdpi/marker_notreliable.png diff --git a/main/res/drawable-mdpi/marker_oc.png b/main/res/drawable-mdpi/marker_oc.png Binary files differnew file mode 100644 index 0000000..03e1fe7 --- /dev/null +++ b/main/res/drawable-mdpi/marker_oc.png diff --git a/main/res/drawable-mdpi/marker_other.png b/main/res/drawable-mdpi/marker_other.png Binary files differnew file mode 100644 index 0000000..2456d82 --- /dev/null +++ b/main/res/drawable-mdpi/marker_other.png diff --git a/main/res/drawable/marker_own.png b/main/res/drawable-mdpi/marker_own.png Binary files differindex b091cf3..b091cf3 100644 --- a/main/res/drawable/marker_own.png +++ b/main/res/drawable-mdpi/marker_own.png diff --git a/main/res/drawable/marker_personalnote.png b/main/res/drawable-mdpi/marker_personalnote.png Binary files differindex 70ef9f1..70ef9f1 100644 --- a/main/res/drawable/marker_personalnote.png +++ b/main/res/drawable-mdpi/marker_personalnote.png diff --git a/main/res/drawable/marker_stored.png b/main/res/drawable-mdpi/marker_stored.png Binary files differindex 6689e26..6689e26 100644 --- a/main/res/drawable/marker_stored.png +++ b/main/res/drawable-mdpi/marker_stored.png diff --git a/main/res/drawable/marker_usermodifiedcoords.png b/main/res/drawable-mdpi/marker_usermodifiedcoords.png Binary files differindex f174a17..f174a17 100644 --- a/main/res/drawable/marker_usermodifiedcoords.png +++ b/main/res/drawable-mdpi/marker_usermodifiedcoords.png diff --git a/main/res/drawable/my_location_chevron.png b/main/res/drawable-mdpi/my_location_chevron.png Binary files differindex 67b863f..67b863f 100644 --- a/main/res/drawable/my_location_chevron.png +++ b/main/res/drawable-mdpi/my_location_chevron.png diff --git a/main/res/drawable/star_half.png b/main/res/drawable-mdpi/star_half.png Binary files differindex 1ea9152..1ea9152 100644 --- a/main/res/drawable/star_half.png +++ b/main/res/drawable-mdpi/star_half.png diff --git a/main/res/drawable/star_off.png b/main/res/drawable-mdpi/star_off.png Binary files differindex 126815f..126815f 100644 --- a/main/res/drawable/star_off.png +++ b/main/res/drawable-mdpi/star_off.png diff --git a/main/res/drawable/star_on.png b/main/res/drawable-mdpi/star_on.png Binary files differindex 801928a..801928a 100644 --- a/main/res/drawable/star_on.png +++ b/main/res/drawable-mdpi/star_on.png diff --git a/main/res/drawable/trackable_all.png b/main/res/drawable-mdpi/trackable_all.png Binary files differindex 8c830d4..8c830d4 100644 --- a/main/res/drawable/trackable_all.png +++ b/main/res/drawable-mdpi/trackable_all.png diff --git a/main/res/drawable/type_ape.png b/main/res/drawable-mdpi/type_ape.png Binary files differindex 3487013..3487013 100644 --- a/main/res/drawable/type_ape.png +++ b/main/res/drawable-mdpi/type_ape.png diff --git a/main/res/drawable/type_cito.png b/main/res/drawable-mdpi/type_cito.png Binary files differindex 56f0e5f..56f0e5f 100644 --- a/main/res/drawable/type_cito.png +++ b/main/res/drawable-mdpi/type_cito.png diff --git a/main/res/drawable/type_earth.png b/main/res/drawable-mdpi/type_earth.png Binary files differindex 356b3b8..356b3b8 100644 --- a/main/res/drawable/type_earth.png +++ b/main/res/drawable-mdpi/type_earth.png diff --git a/main/res/drawable/type_event.png b/main/res/drawable-mdpi/type_event.png Binary files differindex 93b60fe..93b60fe 100644 --- a/main/res/drawable/type_event.png +++ b/main/res/drawable-mdpi/type_event.png diff --git a/main/res/drawable/type_hq.png b/main/res/drawable-mdpi/type_hq.png Binary files differindex e4f700a..e4f700a 100644 --- a/main/res/drawable/type_hq.png +++ b/main/res/drawable-mdpi/type_hq.png diff --git a/main/res/drawable/type_letterbox.png b/main/res/drawable-mdpi/type_letterbox.png Binary files differindex 52348f2..52348f2 100644 --- a/main/res/drawable/type_letterbox.png +++ b/main/res/drawable-mdpi/type_letterbox.png diff --git a/main/res/drawable/type_mega.png b/main/res/drawable-mdpi/type_mega.png Binary files differindex 9551892..9551892 100644 --- a/main/res/drawable/type_mega.png +++ b/main/res/drawable-mdpi/type_mega.png diff --git a/main/res/drawable/type_multi.png b/main/res/drawable-mdpi/type_multi.png Binary files differindex 5bcfd31..5bcfd31 100644 --- a/main/res/drawable/type_multi.png +++ b/main/res/drawable-mdpi/type_multi.png diff --git a/main/res/drawable/type_mystery.png b/main/res/drawable-mdpi/type_mystery.png Binary files differindex f462d5d..f462d5d 100644 --- a/main/res/drawable/type_mystery.png +++ b/main/res/drawable-mdpi/type_mystery.png diff --git a/main/res/drawable/type_traditional.png b/main/res/drawable-mdpi/type_traditional.png Binary files differindex e3e1a4b..e3e1a4b 100644 --- a/main/res/drawable/type_traditional.png +++ b/main/res/drawable-mdpi/type_traditional.png diff --git a/main/res/drawable/type_unknown.png b/main/res/drawable-mdpi/type_unknown.png Binary files differindex 67e0dd9..67e0dd9 100644 --- a/main/res/drawable/type_unknown.png +++ b/main/res/drawable-mdpi/type_unknown.png diff --git a/main/res/drawable/type_virtual.png b/main/res/drawable-mdpi/type_virtual.png Binary files differindex 14bc704..14bc704 100644 --- a/main/res/drawable/type_virtual.png +++ b/main/res/drawable-mdpi/type_virtual.png diff --git a/main/res/drawable/type_webcam.png b/main/res/drawable-mdpi/type_webcam.png Binary files differindex 922fddd..922fddd 100644 --- a/main/res/drawable/type_webcam.png +++ b/main/res/drawable-mdpi/type_webcam.png diff --git a/main/res/drawable/type_wherigo.png b/main/res/drawable-mdpi/type_wherigo.png Binary files differindex 96318f6..96318f6 100644 --- a/main/res/drawable/type_wherigo.png +++ b/main/res/drawable-mdpi/type_wherigo.png diff --git a/main/res/drawable/waypoint_flag.png b/main/res/drawable-mdpi/waypoint_flag.png Binary files differindex 123ec84..123ec84 100644 --- a/main/res/drawable/waypoint_flag.png +++ b/main/res/drawable-mdpi/waypoint_flag.png diff --git a/main/res/drawable/waypoint_pkg.png b/main/res/drawable-mdpi/waypoint_pkg.png Binary files differindex 1a901f0..1a901f0 100644 --- a/main/res/drawable/waypoint_pkg.png +++ b/main/res/drawable-mdpi/waypoint_pkg.png diff --git a/main/res/drawable/waypoint_puzzle.png b/main/res/drawable-mdpi/waypoint_puzzle.png Binary files differindex a659f36..a659f36 100644 --- a/main/res/drawable/waypoint_puzzle.png +++ b/main/res/drawable-mdpi/waypoint_puzzle.png diff --git a/main/res/drawable/waypoint_stage.png b/main/res/drawable-mdpi/waypoint_stage.png Binary files differindex 52e0481..52e0481 100644 --- a/main/res/drawable/waypoint_stage.png +++ b/main/res/drawable-mdpi/waypoint_stage.png diff --git a/main/res/drawable/waypoint_trailhead.png b/main/res/drawable-mdpi/waypoint_trailhead.png Binary files differindex 1aca26f..1aca26f 100644 --- a/main/res/drawable/waypoint_trailhead.png +++ b/main/res/drawable-mdpi/waypoint_trailhead.png diff --git a/main/res/drawable/waypoint_waypoint.png b/main/res/drawable-mdpi/waypoint_waypoint.png Binary files differindex 91b69a9..91b69a9 100644 --- a/main/res/drawable/waypoint_waypoint.png +++ b/main/res/drawable-mdpi/waypoint_waypoint.png diff --git a/main/res/drawable/action_button_dark_dialog.xml b/main/res/drawable/action_button_dark_dialog.xml deleted file mode 100644 index 17db3fb..0000000 --- a/main/res/drawable/action_button_dark_dialog.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <stroke - android:color="#66FFFFFF" - android:width="1px" /> - <solid - android:color="#FF080808" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/action_button_light_dialog.xml b/main/res/drawable/action_button_light_dialog.xml deleted file mode 100644 index e17a55a..0000000 --- a/main/res/drawable/action_button_light_dialog.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <stroke - android:color="#66000000" - android:width="1px" /> - <solid - android:color="#FFEEEEEE" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/bcg_dark.xml b/main/res/drawable/bcg_dark.xml deleted file mode 100644 index 0acf0e0..0000000 --- a/main/res/drawable/bcg_dark.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid - android:color="@color/background_dark" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/bcg_dialog_dark.xml b/main/res/drawable/bcg_dialog_dark.xml deleted file mode 100644 index 73b2276..0000000 --- a/main/res/drawable/bcg_dialog_dark.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid - android:color="#11FFFFFF" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/bcg_dialog_light.xml b/main/res/drawable/bcg_dialog_light.xml deleted file mode 100644 index b89730f..0000000 --- a/main/res/drawable/bcg_dialog_light.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid - android:color="#11000000" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/bcg_light.xml b/main/res/drawable/bcg_light.xml deleted file mode 100644 index 0acf0e0..0000000 --- a/main/res/drawable/bcg_light.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid - android:color="@color/background_dark" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/cache_dark.xml b/main/res/drawable/cache_dark.xml deleted file mode 100644 index 7e87cd7..0000000 --- a/main/res/drawable/cache_dark.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/cache_dark_pressed" /> - <item android:state_focused="true" android:drawable="@drawable/cache_dark_pressed" /> - <item android:drawable="@drawable/bcg_dark" /> -</selector>
\ No newline at end of file diff --git a/main/res/drawable/cache_light.xml b/main/res/drawable/cache_light.xml deleted file mode 100644 index b2c669a..0000000 --- a/main/res/drawable/cache_light.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/cache_light_pressed" /> - <item android:state_focused="true" android:drawable="@drawable/cache_light_pressed" /> - <item android:drawable="@drawable/bcg_light" /> -</selector>
\ No newline at end of file diff --git a/main/res/drawable/cache_light_pressed.xml b/main/res/drawable/cache_light_pressed.xml deleted file mode 100644 index 411f915..0000000 --- a/main/res/drawable/cache_light_pressed.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid - android:color="#44000000" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/client_cgeo.png b/main/res/drawable/client_cgeo.png Binary files differdeleted file mode 100644 index 119f0dd..0000000 --- a/main/res/drawable/client_cgeo.png +++ /dev/null diff --git a/main/res/drawable/client_handygeocaching.png b/main/res/drawable/client_handygeocaching.png Binary files differdeleted file mode 100644 index a842cb5..0000000 --- a/main/res/drawable/client_handygeocaching.png +++ /dev/null diff --git a/main/res/drawable/client_precaching.png b/main/res/drawable/client_precaching.png Binary files differdeleted file mode 100644 index 5fd95d6..0000000 --- a/main/res/drawable/client_precaching.png +++ /dev/null diff --git a/main/res/drawable/dialog_button_dark.xml b/main/res/drawable/dialog_button_dark.xml deleted file mode 100644 index e36438b..0000000 --- a/main/res/drawable/dialog_button_dark.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/action_button_dark_pressed" /> - <item android:state_focused="true" android:drawable="@drawable/action_button_dark_pressed" /> - <item android:drawable="@drawable/action_button_dark_dialog" /> -</selector>
\ No newline at end of file diff --git a/main/res/drawable/dialog_button_light.xml b/main/res/drawable/dialog_button_light.xml deleted file mode 100644 index 95414ff..0000000 --- a/main/res/drawable/dialog_button_light.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/action_button_light_pressed" /> - <item android:state_focused="true" android:drawable="@drawable/action_button_light_pressed" /> - <item android:drawable="@drawable/action_button_light_dialog" /> -</selector>
\ No newline at end of file diff --git a/main/res/drawable/ic_menu_mylocation.png b/main/res/drawable/ic_menu_mylocation.png Binary files differdeleted file mode 100644 index fdbd5ca..0000000 --- a/main/res/drawable/ic_menu_mylocation.png +++ /dev/null diff --git a/main/res/drawable/icon_big.png b/main/res/drawable/icon_big.png Binary files differdeleted file mode 100644 index a7d0d1b..0000000 --- a/main/res/drawable/icon_big.png +++ /dev/null diff --git a/main/res/drawable/map_status_dark.xml b/main/res/drawable/map_status_dark.xml deleted file mode 100644 index bc257ff..0000000 --- a/main/res/drawable/map_status_dark.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <gradient - android:startColor="#00000000" - android:centerColor="#66000000" - android:endColor="#88000000" - android:angle="90" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/map_status_light.xml b/main/res/drawable/map_status_light.xml deleted file mode 100644 index a6ae801..0000000 --- a/main/res/drawable/map_status_light.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <gradient - android:startColor="#00FFFFFF" - android:centerColor="#66FFFFFF" - android:endColor="#88FFFFFF" - android:angle="90" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/cache_dark_pressed.xml b/main/res/drawable/mark_gray.xml index 593caea..239739e 100644 --- a/main/res/drawable/cache_dark_pressed.xml +++ b/main/res/drawable/mark_gray.xml @@ -2,5 +2,5 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid - android:color="#44FFFFFF" /> + android:color="#77777777" /> </shape>
\ No newline at end of file diff --git a/main/res/drawable/separator_dark.xml b/main/res/drawable/separator_dark.xml deleted file mode 100644 index ece89e1..0000000 --- a/main/res/drawable/separator_dark.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid - android:color="#22FFFFFF" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/separator_light.xml b/main/res/drawable/separator_light.xml deleted file mode 100644 index f57780a..0000000 --- a/main/res/drawable/separator_light.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid - android:color="#22000000" /> -</shape>
\ No newline at end of file diff --git a/main/res/drawable/user_location.png b/main/res/drawable/user_location.png Binary files differdeleted file mode 100644 index e1bde6e..0000000 --- a/main/res/drawable/user_location.png +++ /dev/null diff --git a/main/res/drawable/user_location_active.png b/main/res/drawable/user_location_active.png Binary files differdeleted file mode 100644 index d7d22d2..0000000 --- a/main/res/drawable/user_location_active.png +++ /dev/null diff --git a/main/res/layout-land/coords.xml b/main/res/layout-land/coords.xml index c2dc9c5..aa09600 100644 --- a/main/res/layout-land/coords.xml +++ b/main/res/layout-land/coords.xml @@ -1,127 +1,191 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/linearLayout1" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:background="?background_color"> - <LinearLayout style="@style/action_bar"> - <TextView style="@style/action_bar_title" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/linearLayout1" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="?background_color" + android:orientation="vertical" > + + <LinearLayout style="@style/action_bar" > + + <TextView + style="@style/action_bar_title" android:text="@string/cache_coordinates" /> + <View style="@style/action_bar_separator" /> - <ImageView android:id="@+id/actionBarManualbutton" + + <ImageView + android:id="@+id/actionBarManualbutton" style="@style/action_bar_action" android:src="@drawable/actionbar_manual" /> </LinearLayout> - <ScrollView android:id="@+id/scroller" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:fillViewport="true" > - <LinearLayout android:id="@+id/scroller_child" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - <Spinner android:id="@+id/spinnerCoordinateFormats" - android:layout_width="fill_parent" - android:layout_height="wrap_content" /> - <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/coordTable" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:stretchColumns="0,1,3,5,7" - android:layout_weight="1"> - <TableRow android:id="@+id/tableRow1"> - <Button android:id="@+id/ButtonLat" - style="@style/button_full"/> - <EditText style="@style/edittext_full" - android:id="@+id/EditTextLatDeg" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LatSeparator1" - android:text="°" /> - <EditText android:id="@+id/EditTextLatMin" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LatSeparator2" - android:text="," /> - <EditText android:id="@+id/EditTextLatSec" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LatSeparator3" - android:text="," /> - <EditText android:id="@+id/EditTextLatSecFrac" - style="@style/edittext_full" - android:inputType="number" - android:selectAllOnFocus="true" /> - </TableRow> - <TableRow android:id="@+id/tableRow2"> - <Button android:id="@+id/ButtonLon" - style="@style/button_full"/> - <EditText android:id="@+id/EditTextLonDeg" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LonSeparator1" - android:text="°" /> - <EditText android:id="@+id/EditTextLonMin" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LonSeparator2" - android:text="," /> - <EditText android:id="@+id/EditTextLonSec" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LonSeparator3" - android:text="," /> - <EditText android:id="@+id/EditTextLonSecFrac" - style="@style/edittext_full" - android:inputType="number" - android:selectAllOnFocus="true" /> - </TableRow> - </TableLayout> - <EditText - android:id="@+id/latitude" - style="@style/edittext_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:hint="@string/latitude" /> - <EditText - android:id="@+id/longitude" - style="@style/edittext_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:hint="@string/longitude" /> - <LinearLayout - android:id="@+id/linearLayout2" - android:layout_width="fill_parent" - android:layout_height="wrap_content" > - <Button style="@style/button_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:id="@+id/current" - android:layout_weight="1" - android:text="@string/waypoint_my_coordinates" /> - <Button style="@style/button_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:id="@+id/cache" - android:layout_weight="1" - android:text="@string/waypoint_cache_coordinates" /> - </LinearLayout> - <Button style="@style/button_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:id="@+id/done" - android:text="@string/waypoint_done" /> - </LinearLayout> + + <ScrollView + android:id="@+id/scroller" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:fillViewport="true" > + + <LinearLayout + android:id="@+id/scroller_child" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <Spinner + android:id="@+id/spinnerCoordinateFormats" + android:layout_width="fill_parent" + android:layout_height="wrap_content" /> + + <TableLayout + android:id="@+id/coordTable" + android:layout_width="fill_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:stretchColumns="0,1,3,5,7" > + + <TableRow android:id="@+id/tableRow1" > + + <Button + android:id="@+id/ButtonLat" + style="@style/button_full" /> + + <EditText + android:id="@+id/EditTextLatDeg" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LatSeparator1" + android:text="°" + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLatMin" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LatSeparator2" + android:text="," + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLatSec" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LatSeparator3" + android:text="," + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLatSecFrac" + style="@style/edittext_full" + android:inputType="number" + android:selectAllOnFocus="true" /> + </TableRow> + + <TableRow android:id="@+id/tableRow2" > + + <Button + android:id="@+id/ButtonLon" + style="@style/button_full" /> + + <EditText + android:id="@+id/EditTextLonDeg" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LonSeparator1" + android:text="°" + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLonMin" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LonSeparator2" + android:text="," + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLonSec" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LonSeparator3" + android:text="," + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLonSecFrac" + style="@style/edittext_full" + android:inputType="number" + android:selectAllOnFocus="true" /> + </TableRow> + </TableLayout> + + <EditText + android:id="@+id/latitude" + style="@style/edittext_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:hint="@string/latitude" /> + + <EditText + android:id="@+id/longitude" + style="@style/edittext_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:hint="@string/longitude" /> + + <LinearLayout + android:id="@+id/linearLayout2" + android:layout_width="fill_parent" + android:layout_height="wrap_content" > + + <Button + android:id="@+id/current" + style="@style/button_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/waypoint_my_coordinates" /> + + <Button + android:id="@+id/cache" + style="@style/button_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/waypoint_cache_coordinates" /> + </LinearLayout> + + <Button + android:id="@+id/done" + style="@style/button_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/waypoint_done" /> + </LinearLayout> </ScrollView> -</LinearLayout> + +</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout-land/navigate.xml b/main/res/layout-land/navigate.xml new file mode 100644 index 0000000..0beffb4 --- /dev/null +++ b/main/res/layout-land/navigate.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:background="?background_color" > + <LinearLayout style="@style/action_bar"> + <ImageView style="@style/action_bar_action" + android:onClick="goHome" /> + <View style="@style/action_bar_separator" /> + <TextView style="@style/action_bar_title" /> + <View style="@style/action_bar_separator" /> + <ImageView style="@style/action_bar_action" + android:src="@drawable/actionbar_manual" + android:onClick="goManual" /> + </LinearLayout> + <LinearLayout + android:orientation="horizontal" + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" android:layout_weight="1"> + <TextView android:id="@+id/destination" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_gravity="center" + android:textSize="14dip" + android:textColor="?text_color" android:layout_alignParentLeft="false" + android:layout_alignParentTop="true" + android:gravity="center_horizontal"/> + <TextView android:id="@+id/cacheinfo" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_gravity="center" + android:textSize="14dip" + android:textColor="?text_color" android:layout_alignParentLeft="false" + android:layout_alignParentTop="false" + android:layout_below="@+id/destination" android:gravity="center_horizontal"/> + <TextView android:id="@+id/heading" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="3dip" + android:layout_alignParentLeft="true" + android:layout_gravity="left" + android:textSize="26dip" + android:textColor="?text_color" + android:text="@null" android:layout_centerVertical="true"/> + <TextView android:id="@+id/distance" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="3dip" + android:layout_alignParentRight="true" + android:layout_gravity="right" + android:textSize="26dip" + android:textColor="?text_color" + android:text="@null" android:layout_centerVertical="true"/> + <TextView android:id="@+id/nav_location" + style="@style/location_current" + android:layout_above="@id/status" + android:text="@string/loc_trying" android:layout_alignParentLeft="false" + android:layout_marginLeft="0dp" android:layout_alignParentTop="false" + android:layout_marginTop="95dp" android:layout_alignParentBottom="false" + /> + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="16dip" android:longClickable="true" + android:layout_alignParentLeft="false" + android:layout_alignParentTop="false" + android:layout_alignParentBottom="true" android:id="@+id/status"> + <TextView android:id="@+id/nav_type" + style="@style/location_current_type" + android:textColor="?text_color_grey" /> + <TextView android:id="@+id/nav_accuracy" + style="@style/location_current_accuracy" + android:textColor="?text_color_grey" /> + <TextView android:id="@+id/nav_satellites" + style="@style/location_current_satellites" + android:textColor="?text_color_grey" /> + </RelativeLayout> + </RelativeLayout> + <view class="cgeo.geocaching.ui.CompassView" + android:id="@+id/rose" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layout_marginTop="6dip" + android:layout_marginBottom="1dip" + android:layout_marginRight="1dip" + android:layout_marginLeft="1dip" + android:layout_gravity="center_vertical" + android:layout_centerInParent="true" + android:keepScreenOn="true" + android:gravity="center" + android:padding="4dip" + android:layout_weight="1"/> + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/about.xml b/main/res/layout/about.xml index 13d7c04..39ad8ff 100644 --- a/main/res/layout/about.xml +++ b/main/res/layout/about.xml @@ -17,7 +17,7 @@ android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:layout_marginTop="10dip" android:orientation="vertical" > <LinearLayout diff --git a/main/res/layout/auth.xml b/main/res/layout/auth.xml index d94b08a..ea06d9c 100644 --- a/main/res/layout/auth.xml +++ b/main/res/layout/auth.xml @@ -1,82 +1,85 @@ <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" - android:background="?background_color" > - <LinearLayout style="@style/action_bar"> - <ImageView style="@style/action_bar_action" - android:onClick="goHome" /> - <View style="@style/action_bar_separator" /> - <TextView style="@style/action_bar_title" /> - </LinearLayout> - <ScrollView - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:padding="4dip" - android:orientation="vertical" > - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:layout_marginTop="10dip" - android:orientation="vertical" > - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:padding="7dip" > - <ImageView - android:layout_width="64dip" - android:layout_height="64dip" - android:maxWidth="64dip" - android:maxHeight="64dip" - android:scaleType="fitXY" - android:layout_marginTop="7dip" - android:layout_marginBottom="7dip" - android:layout_marginLeft="7dip" - android:layout_marginRight="7dip" - android:src="@drawable/icon_big" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:layout_marginBottom="5dip" - android:layout_gravity="left|center_vertical" - android:gravity="left|center_vertical" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/about_auth_1" /> - </LinearLayout> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:layout_marginBottom="5dip" - android:layout_gravity="left|center_vertical" - android:gravity="left|center_vertical" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/about_auth_2" /> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:padding="7dip" > - <Button style="@style/button_full" - android:id="@+id/start" - android:text="@string/auth_authorize" /> - <EditText style="@style/edittext_full" - android:id="@+id/pin" - android:visibility="gone" - android:inputType="number" - android:hint="@string/auth_pin_hint" /> - <Button style="@style/button_full" - android:id="@+id/pin_button" - android:visibility="gone" - android:text="@string/auth_finish" /> - </LinearLayout> - </LinearLayout> - </ScrollView> + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:background="?background_color" + android:orientation="vertical" + android:visibility="visible" > + + <LinearLayout style="@style/action_bar" > + + <ImageView + style="@style/action_bar_action" + android:onClick="goHome"/> + + <View style="@style/action_bar_separator" /> + + <TextView style="@style/action_bar_title" /> + </LinearLayout> + + <ScrollView + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:padding="4dip" > + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dip" + android:orientation="vertical" > + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_gravity="left|center_vertical" + android:layout_marginBottom="20dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:drawableLeft="@drawable/cgeo" + android:drawablePadding="15dip" + android:gravity="left|center_vertical" + android:text="@string/about_auth_1" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left|center_vertical" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:gravity="left|center_vertical" + android:text="@string/about_auth_2" + android:textColor="?text_color" + android:textSize="14sp" /> + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="7dip" > + + <Button + android:id="@+id/start" + style="@style/button_full" + android:text="@string/auth_authorize" /> + + <EditText + android:id="@+id/pin" + style="@style/edittext_full" + android:hint="@string/auth_pin_hint" + android:inputType="number" + android:visibility="gone" /> + + <Button + android:id="@+id/pin_button" + style="@style/button_full" + android:text="@string/auth_finish" + android:visibility="visible" /> + </LinearLayout> + </LinearLayout> + </ScrollView> + </LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/cache_item.xml b/main/res/layout/cache_item.xml deleted file mode 100644 index 6de416e..0000000 --- a/main/res/layout/cache_item.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="3dip" > - <TextView android:id="@+id/name" - android:layout_width="80dip" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true" - android:layout_gravity="left|top" - android:layout_marginRight="4dip" - android:gravity="right" - android:lines="1" - android:singleLine="true" - android:scrollHorizontally="true" - android:ellipsize="end" - android:textSize="12dip" - android:textColor="?text_color_headline" - android:text="@null" /> - <TextView android:id="@+id/value" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true" - android:layout_alignBaseline="@id/name" - android:layout_marginTop="2dip" - android:layout_marginLeft="83dip" - android:layout_marginRight="6dip" - android:layout_gravity="left|top" - android:textSize="14dip" - android:textColor="?text_color" - android:linksClickable="true" - android:textColorLink="?text_color_link" /> -</RelativeLayout>
\ No newline at end of file diff --git a/main/res/layout/cache_layout.xml b/main/res/layout/cache_layout.xml index 59507eb..256026c 100644 --- a/main/res/layout/cache_layout.xml +++ b/main/res/layout/cache_layout.xml @@ -6,7 +6,7 @@ <TextView android:id="@+id/name" android:layout_width="80dip" android:layout_height="wrap_content" - android:layout_alignParentTop="true" + android:layout_alignParentTop="false" android:layout_alignParentLeft="true" android:layout_gravity="left|top" android:layout_marginRight="4dip" @@ -17,29 +17,27 @@ android:ellipsize="end" android:textSize="12dip" android:textColor="?text_color_headline" - android:text="@null" /> - <LinearLayout android:id="@+id/stars" - android:orientation="horizontal" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true" - android:layout_marginTop="2dip" - android:layout_marginLeft="83dip" - android:layout_marginRight="6dip" - android:layout_gravity="left|top" > - <TextView android:id="@+id/value" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginRight="5dip" - android:textSize="14dip" - android:textColor="?text_color" /> - <TextView android:id="@+id/addition" - android:visibility="gone" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="5dip" - android:textSize="11dip" - android:textColor="?text_color_grey" /> - </LinearLayout> + android:text="@null" android:layout_centerVertical="true"/> + <TextView android:id="@+id/value" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="5dip" + android:textSize="14dip" + android:textColor="?text_color" android:gravity="center_vertical" android:layout_toRightOf="@+id/name" + android:layout_centerVertical="true"/> + <LinearLayout + android:orientation="horizontal" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:id="@+id/stars" android:layout_toRightOf="@+id/value" + android:layout_centerVertical="true" android:visibility="gone" android:baselineAligned="false" + android:gravity="center_vertical"> + </LinearLayout> + <TextView android:id="@+id/addition" + android:visibility="gone" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="5dip" + android:textSize="11dip" + android:textColor="?text_color_grey" android:gravity="center_vertical" + android:layout_centerVertical="true" android:layout_toRightOf="@+id/stars"/> </RelativeLayout>
\ No newline at end of file diff --git a/main/res/layout/cacheview.xml b/main/res/layout/cacheview.xml index 2f6f155..89d7152 100644 --- a/main/res/layout/cacheview.xml +++ b/main/res/layout/cacheview.xml @@ -21,9 +21,9 @@ <ImageView
android:id="@+id/defaultNavigation"
style="@style/action_bar_action"
+ android:longClickable="true"
android:onClick="startDefaultNavigation"
- android:src="@drawable/actionbar_compass_dark"
- android:longClickable="true" />
+ android:src="@drawable/actionbar_compass_dark" />
<View style="@style/action_bar_separator" />
@@ -36,7 +36,7 @@ <android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
+ android:layout_height="0dp"
android:layout_weight="1" />
<com.viewpagerindicator.TitlePageIndicator
diff --git a/main/res/layout/cacheview_description.xml b/main/res/layout/cacheview_description.xml index 60e70e7..044329b 100644 --- a/main/res/layout/cacheview_description.xml +++ b/main/res/layout/cacheview_description.xml @@ -5,7 +5,7 @@ <LinearLayout
android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="4dip" >
diff --git a/main/res/layout/cacheview_details.xml b/main/res/layout/cacheview_details.xml index 2598fdd..62ee2af 100644 --- a/main/res/layout/cacheview_details.xml +++ b/main/res/layout/cacheview_details.xml @@ -6,7 +6,7 @@ <LinearLayout
android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="4dip" >
diff --git a/main/res/layout/cacheview_waypoints.xml b/main/res/layout/cacheview_waypoints.xml index faf90f5..fc990d5 100644 --- a/main/res/layout/cacheview_waypoints.xml +++ b/main/res/layout/cacheview_waypoints.xml @@ -5,7 +5,7 @@ <LinearLayout
android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="4dip" >
diff --git a/main/res/layout/coords.xml b/main/res/layout/coords.xml index 3adcb2a..5720fa8 100644 --- a/main/res/layout/coords.xml +++ b/main/res/layout/coords.xml @@ -1,118 +1,183 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/linearLayout1" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:background="?background_color"> - <LinearLayout style="@style/action_bar"> - <TextView style="@style/action_bar_title" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/linearLayout1" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="?background_color" + android:orientation="vertical" > + + <LinearLayout style="@style/action_bar" > + + <TextView + style="@style/action_bar_title" android:text="@string/cache_coordinates" /> + <View style="@style/action_bar_separator" /> - <ImageView android:id="@+id/actionBarManualbutton" + + <ImageView + android:id="@+id/actionBarManualbutton" style="@style/action_bar_action" android:src="@drawable/actionbar_manual" /> </LinearLayout> - <ScrollView android:id="@+id/scroller" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:fillViewport="true" > - <LinearLayout android:id="@+id/scroller_child" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - <Spinner android:id="@+id/spinnerCoordinateFormats" - android:layout_width="fill_parent" - android:layout_height="wrap_content" /> - <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/coordTable" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:stretchColumns="0,1,3,5,7" - android:layout_weight="1"> - <TableRow android:id="@+id/tableRow1"> - <Button android:id="@+id/ButtonLat" - style="@style/button_full"/> - <EditText style="@style/edittext_full" - android:id="@+id/EditTextLatDeg" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LatSeparator1" - android:text="°" /> - <EditText android:id="@+id/EditTextLatMin" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LatSeparator2" - android:text="," /> - <EditText android:id="@+id/EditTextLatSec" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LatSeparator3" - android:text="," /> - <EditText android:id="@+id/EditTextLatSecFrac" - style="@style/edittext_full" - android:inputType="number" - android:selectAllOnFocus="true" /> - </TableRow> - <TableRow android:id="@+id/tableRow2"> - <Button android:id="@+id/ButtonLon" - style="@style/button_full"/> - <EditText android:id="@+id/EditTextLonDeg" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LonSeparator1" - android:text="°" /> - <EditText android:id="@+id/EditTextLonMin" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LonSeparator2" - android:text="," /> - <EditText android:id="@+id/EditTextLonSec" - style="@style/edittext_full" - android:gravity="right" - android:inputType="number" - android:selectAllOnFocus="true" /> - <TextView android:id="@+id/LonSeparator3" - android:text="," /> - <EditText android:id="@+id/EditTextLonSecFrac" - style="@style/edittext_full" - android:inputType="number" - android:selectAllOnFocus="true" /> - </TableRow> - </TableLayout> - <EditText style="@style/edittext_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:id="@+id/latitude" - android:hint="@string/latitude" /> - <EditText style="@style/edittext_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:id="@+id/longitude" - android:hint="@string/longitude" /> - <Button style="@style/button_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:id="@+id/current" - android:text="@string/waypoint_my_coordinates" /> - <Button style="@style/button_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:id="@+id/cache" - android:text="@string/waypoint_cache_coordinates" /> - <Button style="@style/button_full" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:id="@+id/done" - android:text="@string/waypoint_done" /> - </LinearLayout> + + <ScrollView + android:id="@+id/scroller" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:fillViewport="true" > + + <LinearLayout + android:id="@+id/scroller_child" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <Spinner + android:id="@+id/spinnerCoordinateFormats" + android:layout_width="fill_parent" + android:layout_height="wrap_content" /> + + <TableLayout + android:id="@+id/coordTable" + android:layout_width="fill_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:stretchColumns="0,1,3,5,7" > + + <TableRow android:id="@+id/tableRow1" > + + <Button + android:id="@+id/ButtonLat" + style="@style/button_full" /> + + <EditText + android:id="@+id/EditTextLatDeg" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LatSeparator1" + android:text="°" + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLatMin" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LatSeparator2" + android:text="," + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLatSec" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LatSeparator3" + android:text="," + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLatSecFrac" + style="@style/edittext_full" + android:inputType="number" + android:selectAllOnFocus="true" /> + </TableRow> + + <TableRow android:id="@+id/tableRow2" > + + <Button + android:id="@+id/ButtonLon" + style="@style/button_full" /> + + <EditText + android:id="@+id/EditTextLonDeg" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LonSeparator1" + android:text="°" + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLonMin" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LonSeparator2" + android:text="," + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLonSec" + style="@style/edittext_full" + android:gravity="right" + android:inputType="number" + android:selectAllOnFocus="true" /> + + <TextView + android:id="@+id/LonSeparator3" + android:text="," + tools:ignore="HardcodedText" /> + + <EditText + android:id="@+id/EditTextLonSecFrac" + style="@style/edittext_full" + android:inputType="number" + android:selectAllOnFocus="true" /> + </TableRow> + </TableLayout> + + <EditText + android:id="@+id/latitude" + style="@style/edittext_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:hint="@string/latitude" /> + + <EditText + android:id="@+id/longitude" + style="@style/edittext_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:hint="@string/longitude" /> + + <Button + android:id="@+id/current" + style="@style/button_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/waypoint_my_coordinates" /> + + <Button + android:id="@+id/cache" + style="@style/button_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/waypoint_cache_coordinates" /> + + <Button + android:id="@+id/done" + style="@style/button_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/waypoint_done" /> + </LinearLayout> </ScrollView> -</LinearLayout> + +</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/waypoint_new.xml b/main/res/layout/edit_waypoint_activity.xml index dfe79fc..46134a0 100644 --- a/main/res/layout/waypoint_new.xml +++ b/main/res/layout/edit_waypoint_activity.xml @@ -51,45 +51,69 @@ android:hint="@string/waypoint_bearing" android:inputType="numberDecimal" /> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > - - <EditText - android:id="@+id/distance" - style="@style/edittext_full" - android:hint="@string/waypoint_distance" - android:inputType="numberDecimal" - android:layout_width="0dip" - android:layout_weight="1" /> - - <Spinner - android:id="@+id/distanceUnit" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:entries="@array/distance_units" /> - </LinearLayout> - - <AutoCompleteTextView + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" > + + <EditText + android:id="@+id/distance" + style="@style/edittext_full" + android:layout_width="0dip" + android:layout_weight="1" + android:hint="@string/waypoint_distance" + android:inputType="numberDecimal" /> + + <Spinner + android:id="@+id/distanceUnit" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:entries="@array/distance_units" /> + </LinearLayout> + + <AutoCompleteTextView android:id="@+id/name" style="@style/edittext_full" android:hint="@string/waypoint_name" /> - - <Spinner + + <Spinner android:id="@+id/type" android:layout_width="fill_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" /> <EditText android:id="@+id/note" style="@style/edittext_full" android:layout_height="wrap_content" - android:inputType="textMultiLine|textCapSentences" android:hint="@string/waypoint_note" + android:inputType="textMultiLine|textCapSentences" android:minLines="5" android:singleLine="false" /> + <RadioGroup + android:id="@+id/modify_cache_coordinates_group" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" > + + <RadioButton + android:id="@+id/modify_cache_coordinates_nothing" + style="@style/radiobutton_wrap" + android:checked="true" + android:text="@string/waypoint_do_not_touch_cache_coordinates" /> + + <RadioButton + android:id="@+id/modify_cache_coordinates_local" + style="@style/radiobutton_wrap" + android:text="@string/waypoint_set_as_cache_coords" /> + + <RadioButton + android:id="@+id/modify_cache_coordinates_local_and_remote" + style="@style/radiobutton_wrap" + android:text="@string/waypoint_save_and_modify_on_website" + android:visibility="gone" /> + </RadioGroup> + <Button android:id="@+id/add_waypoint" style="@style/button_full" diff --git a/main/res/layout/editor.xml b/main/res/layout/editor.xml index 88b1b10..e07d31f 100644 --- a/main/res/layout/editor.xml +++ b/main/res/layout/editor.xml @@ -8,7 +8,7 @@ <EditText android:id="@+id/editorEditText" android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="0dp" android:layout_weight="1" android:inputType="textMultiLine" android:scrollbars="vertical" > diff --git a/main/res/layout/fieldnote_export_dialog.xml b/main/res/layout/fieldnote_export_dialog.xml index a83fc67..ca0b01d 100644 --- a/main/res/layout/fieldnote_export_dialog.xml +++ b/main/res/layout/fieldnote_export_dialog.xml @@ -2,32 +2,30 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="?background_color"
android:orientation="vertical"
android:padding="3dip" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:textColor="?text_color"
android:text="@string/export_fieldnotes_info" />
<CheckBox
android:id="@+id/upload"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ style="@style/checkbox_full"
android:text="@string/export_fieldnotes_upload" />
<CheckBox
android:id="@+id/onlynew"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ style="@style/checkbox_full"
android:enabled="false"
android:text="@string/export_fieldnotes_onlynew" />
<Button
android:id="@+id/export"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_margin="3dip"
+ style="@style/button_full"
android:text="@string/export" />
</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/filter_bar.xml b/main/res/layout/filter_bar.xml index 35ee929..9df8f84 100644 --- a/main/res/layout/filter_bar.xml +++ b/main/res/layout/filter_bar.xml @@ -1,10 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/filter_bar" - style="@style/filter_bar" - android:visibility="gone"> - <ImageView style="@style/filter_bar_image" - android:src="@drawable/main_filter_default"></ImageView> - <TextView android:id="@+id/filter_text" - style="@style/filter_bar_text"/> + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/filter_bar" + style="@style/filter_bar" + android:onClick="showFilterMenu" + android:visibility="gone" + tools:ignore="UseCompoundDrawables" > <!-- This cannot be done with a compound drawable as there is no easy way to set the size of the image in XML --> + + <ImageView + style="@style/filter_bar_image" + android:src="@drawable/main_filter_default" > + </ImageView> + + <TextView + android:id="@+id/filter_text" + style="@style/filter_bar_text" /> + </LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/gpx_export_dialog.xml b/main/res/layout/gpx_export_dialog.xml index 7c9345f..a997d6b 100644 --- a/main/res/layout/gpx_export_dialog.xml +++ b/main/res/layout/gpx_export_dialog.xml @@ -2,6 +2,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="?background_color"
android:orientation="vertical"
android:padding="3dip" >
@@ -9,19 +10,17 @@ android:id="@id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:textColor="?text_color"
android:text="@string/export_gpx_info" />
<CheckBox
android:id="@+id/share"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ style="@style/checkbox_full"
android:text="@string/init_share_after_export" />
<Button
android:id="@+id/export"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_margin="3dip"
+ style="@style/button_full"
android:text="@string/export" />
</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/init.xml b/main/res/layout/init.xml index 8450ff8..28e0a3c 100644 --- a/main/res/layout/init.xml +++ b/main/res/layout/init.xml @@ -21,7 +21,7 @@ android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:layout_marginTop="10dip" android:orientation="vertical" > <!-- ** --> @@ -60,6 +60,28 @@ <RelativeLayout style="@style/separator_horizontal_layout" > <View style="@style/separator_horizontal" /> <TextView style="@style/separator_horizontal_headline" + android:text="@string/init_oc" /> + </RelativeLayout> + <CheckBox android:id="@+id/oc_option" + style="@style/checkbox_full" + android:text="@string/init_oc_activate" /> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:layout_marginBottom="5dip" + android:padding="3dip" + android:textSize="14sp" + android:textColor="?text_color" + android:text="@string/init_oc_username_description" /> + <EditText style="@style/edittext_full" + android:id="@+id/oc_username" + android:hint="@string/init_oc_username" /> +<!-- ** --> + <RelativeLayout style="@style/separator_horizontal_layout" > + <View style="@style/separator_horizontal" /> + <TextView style="@style/separator_horizontal_headline" android:text="@string/init_gcvote" /> </RelativeLayout> <EditText style="@style/edittext_full" @@ -88,29 +110,10 @@ <Button style="@style/button_full" android:id="@+id/authorize_twitter" android:text="@string/init_twitter_authorize" /> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_margin="3dip" - android:orientation="horizontal" - android:padding="3dip" > <CheckBox android:id="@+id/twitter_option" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" + style="@style/checkbox_full" android:text="@string/init_twitter_publish" /> - </LinearLayout> -<!-- ** --> + <RelativeLayout style="@style/separator_horizontal_layout" > <View style="@style/separator_horizontal" /> <TextView style="@style/separator_horizontal_headline" @@ -139,28 +142,9 @@ android:textSize="14dip" android:text="@string/init_signature_help_button" /> </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_margin="3dip" - android:orientation="horizontal" - android:padding="3dip" > - <CheckBox android:id="@+id/sigautoinsert" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_sigautoinsert" /> - </LinearLayout> + <CheckBox android:id="@+id/sigautoinsert" + style="@style/checkbox_full" + android:text="@string/init_sigautoinsert" /> <RelativeLayout style="@style/separator_horizontal_layout" > <View style="@style/separator_horizontal" /> <TextView style="@style/separator_horizontal_headline" @@ -168,168 +152,30 @@ </RelativeLayout> <LinearLayout android:layout_margin="3dip" android:padding="3dip" android:layout_width="fill_parent" android:orientation="vertical" android:layout_height="fill_parent"> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > <CheckBox android:id="@+id/autoload" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_autoload" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_autoload" /> <CheckBox android:id="@+id/ratingwanted" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_ratingwanted" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_ratingwanted" /> <CheckBox android:id="@+id/elevationwanted" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_elevationwanted" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > - <CheckBox - android:id="@+id/friendlogswanted" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:gravity="center" - android:padding="1px" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:text="@string/init_friendlogswanted" - android:textColor="?text_color" - android:textSize="14dip" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_elevationwanted" /> + <CheckBox android:id="@+id/friendlogswanted" + style="@style/checkbox_full" + android:text="@string/init_friendlogswanted" /> <CheckBox android:id="@+id/openlastdetailspage" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_openlastdetailspage" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_openlastdetailspage" /> <CheckBox android:id="@+id/offline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_offline" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_offline" /> <CheckBox android:id="@+id/offline_wp" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_offline_wp" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_offline_wp" /> <CheckBox android:id="@+id/save_log_img" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_save_log_img" /> - </LinearLayout> + style="@style/checkbox_full" + android:text="@string/init_save_log_img" /> </LinearLayout> <!-- ** --> <RelativeLayout style="@style/separator_horizontal_layout" > @@ -343,306 +189,48 @@ android:layout_margin="3dip" android:orientation="vertical" android:padding="3dip" > - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > <CheckBox android:id="@+id/skin" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_skin" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_skin" /> <CheckBox android:id="@+id/address" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_address" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_address" /> <CheckBox android:id="@+id/captcha" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_captcha" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_captcha" /> <CheckBox android:id="@+id/loaddirectionimg" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_loaddirectionimg" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_loaddirectionimg" /> <CheckBox android:id="@+id/useenglish" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_useenglish" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_useenglish" /> <CheckBox android:id="@+id/exclude" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_exclude" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_exclude" /> <CheckBox android:id="@+id/disabled" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_disabled" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_disabled" /> <CheckBox android:id="@+id/trackautovisit" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_trackautovisit" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_trackautovisit" /> <CheckBox android:id="@+id/units" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_units" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > - <CheckBox android:id="@+id/gnav" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_nav" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_units" /> <CheckBox android:id="@+id/livelist" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_livelist" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_livelist" /> <CheckBox android:id="@+id/log_offline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_log_offline" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_log_offline" /> <CheckBox android:id="@+id/trail" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_maptrail" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_maptrail" /> <CheckBox android:id="@+id/plain_logs" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_plain_logs" /> - </LinearLayout> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > + style="@style/checkbox_full" + android:text="@string/init_plain_logs" /> <CheckBox android:id="@+id/use_native_ua" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_use_native_ua" /> - </LinearLayout> + style="@style/checkbox_full" + android:text="@string/init_use_native_ua" /> </LinearLayout> <!-- ** --> <RelativeLayout style="@style/separator_horizontal_layout" > @@ -1001,26 +589,9 @@ android:textColorLink="?text_color_link" android:linksClickable="true" android:text="@string/init_dbonsdcard_note" /> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > <CheckBox android:id="@+id/dbonsdcard" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" - android:text="@string/init_dbonsdcard" /> - </LinearLayout> + style="@style/checkbox_full" + android:text="@string/init_dbonsdcard" /> <!-- ** --> <RelativeLayout style="@style/separator_horizontal_layout" > <View style="@style/separator_horizontal" /> @@ -1041,26 +612,9 @@ android:textColorLink="?text_color_link" android:linksClickable="true" android:text="@string/init_debug_note" /> - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > <CheckBox android:id="@+id/debug" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:padding="1px" - android:gravity="center" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" + style="@style/checkbox_full" android:text="@string/init_debug" /> - </LinearLayout> </LinearLayout> </ScrollView> </LinearLayout> diff --git a/main/res/layout/main.xml b/main/res/layout/main.xml index 1341821..575fe1f 100644 --- a/main/res/layout/main.xml +++ b/main/res/layout/main.xml @@ -17,31 +17,15 @@ android:src="@drawable/actionbar_manual" android:onClick="goManual" /> </LinearLayout> - <RelativeLayout android:id="@+id/status" - android:visibility="gone" + <fragment android:id="@+id/status" + android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginLeft="16dip" android:layout_marginRight="16dip" android:layout_marginTop="60dip" - android:background="@drawable/helper_bcg" > - <ImageView android:id="@+id/status_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_centerVertical="true" - android:layout_margin="4dip" /> - <TextView android:id="@+id/status_message" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/status_icon" - android:layout_centerVertical="true" - android:gravity="center" - android:padding="4dip" - android:textSize="14dip" - android:textColor="@color/text_icon" /> - </RelativeLayout> + android:name="cgeo.geocaching.StatusFragment" /> <!-- ** --> <LinearLayout android:layout_width="fill_parent" diff --git a/main/res/layout/navigate.xml b/main/res/layout/navigate.xml index 94ed7bc..61cfe2a 100644 --- a/main/res/layout/navigate.xml +++ b/main/res/layout/navigate.xml @@ -24,14 +24,12 @@ <TextView android:id="@+id/destination" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_centerHorizontal="true" android:layout_gravity="center" android:textSize="14dip" android:textColor="?text_color"/> <TextView android:id="@+id/cacheinfo" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_centerHorizontal="true" android:layout_gravity="center" android:textSize="14dip" android:textColor="?text_color"/> diff --git a/main/res/layout/popup.xml b/main/res/layout/popup.xml index 9a33c55..201b9e6 100644 --- a/main/res/layout/popup.xml +++ b/main/res/layout/popup.xml @@ -26,55 +26,45 @@ android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:orientation="vertical" > <LinearLayout android:id="@+id/details_list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > </LinearLayout> - <LinearLayout android:id="@+id/more_details_box" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - <Button style="@style/button_small" - android:id="@+id/more_details" - android:text="@string/popup_more" /> - </LinearLayout> - <LinearLayout android:id="@+id/offline_box" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - </RelativeLayout> - <RelativeLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" > - <TextView android:id="@+id/offline_text" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="6dip" - android:layout_marginRight="130dip" - android:layout_alignParentLeft="true" - android:layout_gravity="left" - android:paddingRight="3dip" - android:textSize="14dip" - android:textColor="?text_color" /> - <Button style="@style/button_small" - android:id="@+id/offline_refresh" - android:visibility="gone" - android:layout_width="60dip" - android:layout_marginRight="71dip" - android:layout_alignParentRight="true" - android:text="@string/cache_offline_refresh" /> - <Button style="@style/button_small" - android:id="@+id/offline_store" - android:layout_width="60dip" - android:layout_alignParentRight="true" - android:text="@string/cache_offline_store" /> - </RelativeLayout> - </LinearLayout> + <Button style="@style/button_small" android:id="@+id/more_details" android:text="@string/popup_more" + android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_gravity="center_horizontal"/> + <RelativeLayout style="@style/separator_horizontal_layout" > + <View style="@style/separator_horizontal" /> + </RelativeLayout> + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" > + <TextView android:id="@+id/offline_text" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="6dip" + android:layout_marginRight="130dip" + android:layout_alignParentLeft="true" + android:layout_gravity="left" + android:paddingRight="3dip" + android:textSize="14dip" + android:textColor="?text_color" /> + <Button style="@style/button_small" + android:id="@+id/offline_refresh" + android:visibility="gone" + android:layout_width="60dip" + android:layout_marginRight="71dip" + android:layout_alignParentRight="true" + android:text="@string/cache_offline_refresh" /> + <Button style="@style/button_small" + android:id="@+id/offline_store" + android:layout_width="60dip" + android:layout_alignParentRight="true" + android:text="@string/cache_offline_store" /> + </RelativeLayout> </LinearLayout> </ScrollView> </LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/reset_cache_coords_dialog.xml b/main/res/layout/reset_cache_coords_dialog.xml new file mode 100644 index 0000000..67ffda3 --- /dev/null +++ b/main/res/layout/reset_cache_coords_dialog.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?background_color"
+ android:orientation="vertical"
+ android:padding="3dip" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?text_color"
+ android:text="@string/waypoint_reset_cache_coords_info" />
+
+ <RadioGroup
+ android:id="@+id/modify_cache_coordinates_group"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <RadioButton
+ android:id="@+id/reset_cache_coordinates_local"
+ style="@style/radiobutton_wrap"
+ android:checked="true"
+ android:text="@string/waypoint_localy_reset_cache_coords" />
+
+ <RadioButton
+ android:id="@+id/reset_cache_coordinates_local_and_remote"
+ style="@style/radiobutton_wrap"
+ android:text="@string/waypoint_reset_local_and_remote_cache_coords"
+ android:visibility="gone" />
+ </RadioGroup>
+
+ <Button
+ android:id="@+id/reset"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="3dip"
+ android:text="@string/waypoint_reset" />
+
+</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/search.xml b/main/res/layout/search.xml index 9848609..5869962 100644 --- a/main/res/layout/search.xml +++ b/main/res/layout/search.xml @@ -1,125 +1,196 @@ <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" - android:background="?background_color" > - <LinearLayout style="@style/action_bar"> - <ImageView style="@style/action_bar_action" - android:onClick="goHome" /> - <View style="@style/action_bar_separator" /> - <TextView style="@style/action_bar_title" /> - <View style="@style/action_bar_separator" /> - <ImageView style="@style/action_bar_action" - android:src="@drawable/actionbar_manual" - android:onClick="goManual" /> - </LinearLayout> - <ScrollView - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:padding="4dip" - android:orientation="vertical" > - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" - android:orientation="vertical" > - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/search_coordinates" /> - </RelativeLayout> - <Button style="@style/button_full" - android:hint="@string/latitude" - android:id="@+id/buttonLatitude"/> - <Button style="@style/button_full" - android:hint="@string/longitude" - android:id="@+id/buttonLongitude"/> - <Button style="@style/button_full" - android:id="@+id/search_coordinates" - android:text="@string/search_coordinates_button" /> -<!-- ** --> - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/search_address" /> - </RelativeLayout> - <EditText style="@style/edittext_full" - android:id="@+id/address" - android:hint="@string/search_address" - android:imeOptions="actionGo" /> - <Button style="@style/button_full" - android:id="@+id/search_address" - android:text="@string/search_address_button" /> -<!-- ** --> - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/search_gc" /> - </RelativeLayout> - <AutoCompleteTextView style="@style/edittext_full" - android:id="@+id/geocode" - android:hint="@string/search_gc" - android:imeOptions="actionGo" - android:text="GC" - android:inputType="textCapCharacters" /> - <Button style="@style/button_full" - android:id="@+id/display_geocode" - android:text="@string/search_gc_button" /> -<!-- ** --> - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/search_kw" /> - </RelativeLayout> - <EditText style="@style/edittext_full" - android:id="@+id/keyword" - android:hint="@string/search_kw_prefill" - android:imeOptions="actionGo" /> - <Button style="@style/button_full" - android:id="@+id/search_keyword" - android:text="@string/search_kw_button" /> -<!-- ** --> - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/search_fbu" /> - </RelativeLayout> - <EditText style="@style/edittext_full" - android:id="@+id/username" - android:hint="@string/search_fbu_prefill" - android:imeOptions="actionGo" /> - <Button style="@style/button_full" - android:id="@+id/search_username" - android:text="@string/search_fbu_button" /> -<!-- ** --> - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/search_hbu" /> - </RelativeLayout> - <EditText style="@style/edittext_full" - android:id="@+id/owner" - android:hint="@string/search_hbu_prefill" - android:imeOptions="actionGo" /> - <Button style="@style/button_full" - android:id="@+id/search_owner" - android:text="@string/search_hbu_button" /> -<!-- ** --> - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/search_tb" /> - </RelativeLayout> - <AutoCompleteTextView style="@style/edittext_full" - android:id="@+id/trackable" - android:hint="@string/search_tb_hint" - android:imeOptions="actionGo" - android:inputType="textCapCharacters" /> - <Button style="@style/button_full" - android:id="@+id/display_trackable" - android:text="@string/search_tb_button" /> - </LinearLayout> - </ScrollView> -</LinearLayout> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:background="?background_color" + android:orientation="vertical" > + + <LinearLayout style="@style/action_bar" > + + <ImageView + style="@style/action_bar_action" + android:onClick="goHome" /> + + <View style="@style/action_bar_separator" /> + + <TextView style="@style/action_bar_title" /> + + <View style="@style/action_bar_separator" /> + + <ImageView + style="@style/action_bar_action" + android:onClick="goManual" + android:src="@drawable/actionbar_manual" /> + </LinearLayout> + + <ScrollView + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:padding="4dip" > + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="10dip" + android:layout_marginTop="10dip" + android:orientation="vertical" > + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/search_coordinates" /> + </RelativeLayout> + + <Button + android:id="@+id/buttonLatitude" + style="@style/button_full" + android:hint="@string/latitude" /> + + <Button + android:id="@+id/buttonLongitude" + style="@style/button_full" + android:hint="@string/longitude" /> + + <Button + android:id="@+id/search_coordinates" + style="@style/button_full" + android:text="@string/search_coordinates_button" /> + <!-- ** --> + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/search_address" /> + </RelativeLayout> + + <EditText + android:id="@+id/address" + style="@style/edittext_full" + android:hint="@string/search_address" + android:imeOptions="actionGo" /> + + <Button + android:id="@+id/search_address" + style="@style/button_full" + android:text="@string/search_address_button" /> + <!-- ** --> + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/search_gc" /> + </RelativeLayout> + + <AutoCompleteTextView + android:id="@+id/geocode" + style="@style/edittext_full" + android:hint="@string/search_gc" + android:imeOptions="actionGo" + android:inputType="textCapCharacters" + android:text="GC" + tools:ignore="HardcodedText" /> + + <Button + android:id="@+id/display_geocode" + style="@style/button_full" + android:text="@string/search_gc_button" /> + <!-- ** --> + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/search_kw" /> + </RelativeLayout> + + <EditText + android:id="@+id/keyword" + style="@style/edittext_full" + android:hint="@string/search_kw_prefill" + android:imeOptions="actionGo" /> + + <Button + android:id="@+id/search_keyword" + style="@style/button_full" + android:text="@string/search_kw_button" /> + <!-- ** --> + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/search_fbu" /> + </RelativeLayout> + + <EditText + android:id="@+id/username" + style="@style/edittext_full" + android:hint="@string/search_fbu_prefill" + android:imeOptions="actionGo" /> + + <Button + android:id="@+id/search_username" + style="@style/button_full" + android:text="@string/search_fbu_button" /> + <!-- ** --> + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/search_hbu" /> + </RelativeLayout> + + <EditText + android:id="@+id/owner" + style="@style/edittext_full" + android:hint="@string/search_hbu_prefill" + android:imeOptions="actionGo" /> + + <Button + android:id="@+id/search_owner" + style="@style/button_full" + android:text="@string/search_hbu_button" /> + <!-- ** --> + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/search_tb" /> + </RelativeLayout> + + <AutoCompleteTextView + android:id="@+id/trackable" + style="@style/edittext_full" + android:hint="@string/search_tb_hint" + android:imeOptions="actionGo" + android:inputType="textCapCharacters" /> + + <Button + android:id="@+id/display_trackable" + style="@style/button_full" + android:text="@string/search_tb_button" /> + </LinearLayout> + </ScrollView> + +</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/status.xml b/main/res/layout/status.xml new file mode 100644 index 0000000..6d9aba3 --- /dev/null +++ b/main/res/layout/status.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/status" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:background="@drawable/helper_bcg" > + <ImageView android:id="@+id/status_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_centerVertical="true" + android:layout_margin="4dip" /> + <TextView android:id="@+id/status_message" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_toRightOf="@id/status_icon" + android:layout_centerVertical="true" + android:gravity="center" + android:padding="4dip" + android:textSize="14dip" + android:textColor="@color/text_icon" /> +</RelativeLayout>
\ No newline at end of file diff --git a/main/res/layout/trackable_activity.xml b/main/res/layout/trackable_activity.xml new file mode 100644 index 0000000..fe61409 --- /dev/null +++ b/main/res/layout/trackable_activity.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res/cgeo.geocaching"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="?background_color"
+ android:orientation="vertical" >
+
+ <LinearLayout style="@style/action_bar" >
+
+ <ImageView
+ style="@style/action_bar_action"
+ android:onClick="goHome" />
+
+ <View style="@style/action_bar_separator" />
+
+ <TextView style="@style/action_bar_title" />
+
+ <View style="@style/action_bar_separator" />
+
+ <ImageView
+ style="@style/action_bar_action"
+ android:onClick="goManual"
+ android:src="@drawable/actionbar_manual" />
+ </LinearLayout>
+
+ <android.support.v4.view.ViewPager
+ android:id="@+id/viewpager"
+ android:layout_width="fill_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <com.viewpagerindicator.TitlePageIndicator
+ android:id="@+id/pager_indicator"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/actionbar_background"
+ app:footerColor="#ff888888"
+ app:footerIndicatorHeight="3dp"
+ app:footerIndicatorStyle="underline"
+ app:textSize="16dp" />
+
+</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/trackable_detail.xml b/main/res/layout/trackable_detail.xml deleted file mode 100644 index 9ffd5cb..0000000 --- a/main/res/layout/trackable_detail.xml +++ /dev/null @@ -1,108 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" - android:background="?background_color" > - <LinearLayout style="@style/action_bar"> - <ImageView style="@style/action_bar_action" - android:onClick="goHome" /> - <View style="@style/action_bar_separator" /> - <TextView style="@style/action_bar_title" /> - <View style="@style/action_bar_separator" /> - <ImageView style="@style/action_bar_action" - android:src="@drawable/actionbar_manual" - android:onClick="goManual" /> - </LinearLayout> - <ScrollView android:id="@+id/details_list_box" - android:visibility="gone" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:padding="4dip" - android:orientation="vertical" > - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" > - <LinearLayout android:id="@+id/details_list" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - </LinearLayout> - <LinearLayout android:id="@+id/goal_box" - android:visibility="gone" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/trackable_goal" /> - </RelativeLayout> - <TextView android:id="@+id/goal" - android:visibility="gone" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="10dip" - android:textSize="14dip" - android:textColor="?text_color" - android:linksClickable="true" - android:textColorLink="?text_color_link" /> - </LinearLayout> - <LinearLayout android:id="@+id/details_box" - android:visibility="gone" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/trackable_details" /> - </RelativeLayout> - <TextView android:id="@+id/details" - android:visibility="gone" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="10dip" - android:textSize="14dip" - android:textColor="?text_color" - android:linksClickable="true" - android:textColorLink="?text_color_link" /> - </LinearLayout> - <LinearLayout android:id="@+id/image_box" - android:visibility="gone" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/trackable_image" /> - </RelativeLayout> - <LinearLayout android:id="@+id/image" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginTop="24dip" - android:padding="3dip" - android:orientation="vertical" > - </LinearLayout> - </LinearLayout> - <LinearLayout android:id="@+id/log_box" - android:visibility="gone" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" > - <RelativeLayout style="@style/separator_horizontal_layout" > - <View style="@style/separator_horizontal" /> - <TextView style="@style/separator_horizontal_headline" - android:text="@string/cache_logs" /> - </RelativeLayout> - <LinearLayout android:id="@+id/log_list" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - </LinearLayout> - </LinearLayout> - </LinearLayout> - </ScrollView> -</LinearLayout> diff --git a/main/res/layout/trackable_details_view.xml b/main/res/layout/trackable_details_view.xml new file mode 100644 index 0000000..7213171 --- /dev/null +++ b/main/res/layout/trackable_details_view.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="utf-8"?> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:padding="4dip"> + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <LinearLayout + android:id="@+id/details_list" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + </LinearLayout> + + <LinearLayout + android:id="@+id/goal_box" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:visibility="gone" > + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/trackable_goal" /> + </RelativeLayout> + + <TextView + android:id="@+id/goal" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="10dip" + android:linksClickable="true" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14dip" + android:visibility="gone" /> + </LinearLayout> + + <LinearLayout + android:id="@+id/details_box" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:visibility="gone" > + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/trackable_details" /> + </RelativeLayout> + + <TextView + android:id="@+id/details" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="10dip" + android:linksClickable="true" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14dip" + android:visibility="gone" /> + </LinearLayout> + + <LinearLayout + android:id="@+id/image_box" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:visibility="gone" > + + <RelativeLayout style="@style/separator_horizontal_layout" > + + <View style="@style/separator_horizontal" /> + + <TextView + style="@style/separator_horizontal_headline" + android:text="@string/trackable_image" /> + </RelativeLayout> + + <LinearLayout + android:id="@+id/image" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="24dip" + android:orientation="vertical" + android:padding="3dip" > + </LinearLayout> + </LinearLayout> + </LinearLayout> + +</ScrollView>
\ No newline at end of file diff --git a/main/res/layout/trackable_logs_item.xml b/main/res/layout/trackable_logs_item.xml index d13416a..77f057e 100644 --- a/main/res/layout/trackable_logs_item.xml +++ b/main/res/layout/trackable_logs_item.xml @@ -2,7 +2,8 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:padding="3dip" > + android:paddingTop="3dip" + android:paddingBottom="3dip" > <TextView android:id="@+id/author" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -62,9 +63,16 @@ android:ellipsize="marquee" android:textSize="14dip" android:textColor="?text_color_headline" /> - </LinearLayout> - </LinearLayout> - <LinearLayout android:id="@+id/log_layout" + </LinearLayout> + <ImageView android:id="@+id/log_mark" + android:layout_width="2dip" + android:layout_height="fill_parent" + android:layout_marginTop="2dip" + android:layout_marginBottom="2dip" + android:scaleType="fitXY" + android:src="@drawable/mark_green" /> + </LinearLayout> + <LinearLayout android:id="@+id/log_layout" android:layout_height="wrap_content" android:layout_width="fill_parent" android:orientation="vertical" diff --git a/main/res/layout/trackable_logs_view.xml b/main/res/layout/trackable_logs_view.xml new file mode 100644 index 0000000..0f89c31 --- /dev/null +++ b/main/res/layout/trackable_logs_view.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<ListView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:cacheColorHint="?background_color" + android:divider="?background_color" + android:fastScrollEnabled="true" + android:focusable="false" + android:footerDividersEnabled="false" + android:headerDividersEnabled="false" + android:listSelector="?background_color" > + +</ListView>
\ No newline at end of file diff --git a/main/res/layout/useful_apps.xml b/main/res/layout/useful_apps.xml index d9dbd62..1d7aecd 100644 --- a/main/res/layout/useful_apps.xml +++ b/main/res/layout/useful_apps.xml @@ -18,7 +18,7 @@ <LinearLayout android:id="@+id/parent" android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:orientation="vertical" > </LinearLayout> </ScrollView> diff --git a/main/res/layout/visit.xml b/main/res/layout/visit.xml index 8e2f06b..e88c21b 100644 --- a/main/res/layout/visit.xml +++ b/main/res/layout/visit.xml @@ -23,7 +23,7 @@ android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:layout_marginTop="10dip" android:orientation="vertical" > <LinearLayout @@ -131,7 +131,8 @@ android:layout_marginBottom="5dip" android:gravity="right" android:textSize="14dip" - android:text="@string/log_tb_changeall" /> + android:text="@string/log_tb_changeall" + android:layout_height="0dp"/> </LinearLayout> </LinearLayout> </LinearLayout> diff --git a/main/res/menu/main_options.xml b/main/res/menu/main_options.xml new file mode 100644 index 0000000..e06e948 --- /dev/null +++ b/main/res/menu/main_options.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_settings"
+ android:icon="@drawable/ic_menu_preferences"
+ android:title="@string/menu_settings">
+ </item>
+ <item
+ android:id="@+id/menu_history"
+ android:icon="@drawable/ic_menu_recent_history"
+ android:title="@string/menu_history">
+ </item>
+ <item
+ android:id="@+id/menu_helpers"
+ android:icon="@drawable/ic_menu_shopping"
+ android:title="@string/menu_helpers">
+ </item>
+ <item
+ android:id="@+id/menu_scan"
+ android:icon="@drawable/ic_menu_barcode"
+ android:title="@string/menu_scan_geo">
+ </item>
+ <item
+ android:id="@+id/menu_about"
+ android:icon="@drawable/ic_menu_info_details"
+ android:title="@string/menu_about">
+ </item>
+
+</menu>
\ No newline at end of file diff --git a/main/res/values-cs/strings.xml b/main/res/values-cs/strings.xml index bf43a6e..52ebed5 100644 --- a/main/res/values-cs/strings.xml +++ b/main/res/values-cs/strings.xml @@ -72,9 +72,6 @@ <string name="log_post_rate">Odeslat log a hlasovat</string> <string name="log_post_no_rate">Odeslat log a nehlasovat</string> <string name="log_add">Přidat</string> - <string name="log_date">Datum</string> - <string name="log_time">Čas</string> - <string name="log_date_time">Datum a čas</string> <string name="log_rating">Hlasovat</string> <string name="log_no_rating">Nehlasovat</string> <string name="log_stars_1">1 hvězdička</string> @@ -111,8 +108,6 @@ <string name="err_missing_auth">nevyplněné uživatelské jméno a/nebo heslo.</string> <string name="err_wrong">uložené přihlašovací údaje jsou špatné</string> <string name="err_license">uživatel nepotvrdil souhlas s licenčním ujednáním serveru Geocaching.com</string> - <string name="err_store">c:geo nemůže uložit keš.</string> - <string name="err_drop">c:geo nemůže smazat keš.</string> <string name="err_detail_open">c:geo nedokáže načíst detaily keše.</string> <string name="err_detail_cache">c:geo nedokáže načíst detaily keše. Je to opravdu keš?</string> <string name="err_detail_cache_find">c:geo nemůže najít keš</string> @@ -123,31 +118,22 @@ <string name="err_detail_cache_forgot_visit">c:geo zapomělo, jakou keš jste pohlížel.</string> <string name="err_detail_no_spoiler">c:geo nenašlo žádný obrázek pro tuto keš.</string> <string name="err_detail_no_map_static">c:geo nenašlo žádnou statickou mapu pro tuto keš.</string> - <string name="err_navigation_no">c:geo nemůže najít žádnou podporovanou navigaci.</string> <string name="err_application_no">c:geo nemůže najít žádnou použitelnou aplikaci.</string> <string name="err_auth_initialize">c:geo nedokázalo zahájit autorizaci.</string> <string name="err_auth_process">Autorizace selhala.</string> <string name="err_cannot_log_visit">c:geo nemá dostatek informací pro zapsání návštěvy. Prosím udělejte to z kompletního detailu keše.</string> <string name="err_init_cleared">c:geo nedokázalo smazat přihlašovací údaje.</string> <string name="err_download_fail">c:geo nemůže načíst keši, protože</string> - <string name="err_list_load_fail">c:geo nemůže načíst seznam keší</string> - <string name="err_store_failed">c:geo nemůže uložit keš</string> - <string name="err_refresh_failed">c:geo nemůže obnovit keš</string> <string name="err_dwld_details_failed">c:geo nemůže stáhnout detaily keše</string> <string name="err_load_descr_failed">c:geo nemůže stáhnout popis keše.</string> <string name="err_location_unknown">c:geo nezná souřadnice keše</string> <string name="err_tb_display">"C:geo nemůže zobrazit trackable. Je to opravdu trackable?</string> <string name="err_tb_details_open">C:geo nemůže otevřít podrobnosti k trackable.</string> - <string name="err_tb_details_download">C:geo nemůže stáhnout podronsti k trackable z důvodu</string> - <string name="err_tb_forgot">C:geo zapomělo, který trackable jste chtěli.</string> <string name="err_tb_forgot_saw">C:geo zapomělo, který trackable jste prohlíželi.</string> <string name="err_tb_find">c:geo nemůže najít trackable.</string> <string name="err_tb_find_that">c:geo nemůže najít toto trackable.</string> <string name="err_waypoint_cache_unknown">c:geo neví k jeké keši chcete přidat bod trasy.</string> - <string name="err_waypoint_unknown">c:geo zapomělo jaký bod trasy chcete zobrazit.</string> <string name="err_waypoint_add_failed">c:geo nemůže přidat bod trasy.</string> - <string name="err_waypoint_load_failed">c:geo nemůže načíst bod trasy.</string> - <string name="err_waypoint_delete_failed">c:geo nemůže smazat bod trasy.</string> <string name="err_point_unknown_position">c:geo neví kde jste.</string> <string name="err_point_no_position_given_title">popis je požadovaný</string> <string name="err_point_no_position_given">Vyplňte alespoň šířku nebo délku nebo vzdálenost a směr. Můžete také vyplnit všechny čtyři pole.</string> @@ -160,7 +146,6 @@ <string name="err_log_load_data_still">c:geo stále načítá data potřebná pro zalogování návštěvy. Prosím počkejte chvilku.</string> <string name="err_log_failed_server">c:geo nemohlo odeslat log, protože server neodpovídá.</string> <string name="err_log_post_failed">c:geo nemohlo odeslat log.</string> - <string name="err_search_address_no_match">c:geo nenašlo žádné odpovídající místo</string> <string name="err_search_address_forgot">c:geo zapomělo adresu, kterou se pokoušíte najít.</string> <string name="err_parse_lat">c:geo nemůže dopočítat šířku.</string> <string name="err_parse_lon">c:geo nemůže dopočítat délku.</string> @@ -267,10 +252,7 @@ <string name="caches_filter_type">Typ</string> <string name="caches_filter_track">Se sledovatelnými předměty</string> <string name="caches_filter_clear">Vymaž filtry</string> - <string name="caches_filter_size_title">Vyber velikost</string> - <string name="caches_filter_type_title">Vyber typ</string> <string name="caches_filter_modified">S upravenými souřadnicemi</string> - <string name="caches_exporting_fieldnote">Exportuji jako Field Notes…</string> <string name="caches_removing_from_history">Mažu z Historie…</string> <!-- caches lists --> @@ -347,7 +329,6 @@ <string name="init_offline_wp">Ukládat statické mapy k waypointům pro offline použití</string> <string name="init_save_log_img">Ulož obrázky z logů</string> <string name="init_units">Používat imperiální jednotky vzdálenosti</string> - <string name="init_nav">Používat Google Navigaci</string> <string name="init_log_offline">Offline logování\n(Při logování nezobrazovat online logovací obrazovku a neodesílat log na server)</string> <string name="init_livelist">Zobrazovat směr v seznamu keší</string> <string name="init_altitude">Výšková korekce</string> @@ -430,7 +411,6 @@ <string name="cache_offline_time_days">dny</string> <string name="cache_premium">placený účet</string> <string name="cache_attributes">atributy</string> - <string name="cache_attributes_no_icons">(obnov cache ke zobrazení atributů)</string> <string name="cache_inventory">Inventář</string> <string name="cache_log_offline">offline log</string> <string name="cache_log_images_loading">Načítám obrázky z logů…</string> @@ -440,7 +420,6 @@ <string name="cache_description">Popis</string> <string name="cache_description_long">Dlouhý popis</string> <string name="cache_description_table_note">Popis obsahuje tabulkové formátování, které je pravděpodobně nutné prohlížet na geocaching.com, aby bylo správně zobrazené.</string> - <string name="cache_watchlist">Watchlist</string> <string name="cache_watchlist_on">Tato je ve vašem watchlistu.</string> <string name="cache_watchlist_not_on">Tato keš není ve vašem watchlistu.</string> <string name="cache_watchlist_add">Přidej na Watchlist</string> @@ -467,7 +446,6 @@ <string name="cache_dialog_refresh_title">Aktualizace</string> <string name="cache_dialog_refresh_message">Aktualizuji detaily keše…</string> <string name="cache_menu_navigate">Navigovat</string> - <string name="cache_menu_tbt">Turn-by-turn</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Zobrazit na mapě</string> <string name="cache_menu_map_ext">Zobrazit na jiné mapě</string> @@ -503,7 +481,6 @@ <string name="gpx_import_loading_caches">nahrávání keší z .gpx souboru</string> <string name="gpx_import_loading_waypoints">Načítám soubor s waypointy</string> <string name="gpx_import_store_static_maps">Ukládám statické mapy</string> - <string name="gpx_import_storing">Zapisuji keše do databáze</string> <string name="gpx_import_caches_imported">keše importovány</string> <string name="gpx_import_static_maps_skipped">Stažení statických map zrušeno</string> <string name="gpx_import_title_static_maps">Ulož statické mapy</string> @@ -521,7 +498,6 @@ <string name="map_file_select_title">Vyber mapový soubor</string> <!-- import --> - <string name="import_title">Import…</string> <string name="web_import_title">Import z webu</string> <string name="web_import_waiting">Čekám na nové keše z webu…</string> <string name="web_downloading">Stahuji</string> @@ -531,7 +507,6 @@ <string name="popup_more">více detailů</string> <!-- waypoint --> - <string name="waypoint_title">Bod trasy</string> <string name="waypoint_custom">vlastní</string> <string name="waypoint_my_coordinates">Aktuální poloha</string> <string name="waypoint_bearing">Směr</string> @@ -544,6 +519,19 @@ <string name="waypoint_note">Poznámka</string> <string name="waypoint_save">Uložit</string> <string name="waypoint_loading">Načítání bodu trasy…</string> + <string name="waypoint_set_as_cache_coords">Nastavit jako souřadnice keše</string> + <string name="waypoint_reset_cache_coords">Obnovit původní souřadnice keše</string> + <string name="waypoint_coordinates_has_been_reset_on_website">Souřadnice keše byly obnoveny na webu.</string> + <string name="waypoint_coordinates_being_reset_on_website">Souřadnice keše se obnovují na webu.</string> + <string name="waypoint_reset_cache_coords_info">Možnosti obnovy</string> + <string name="waypoint_reset">Obnova</string> + <string name="waypoint_localy_reset_cache_coords">Obnovit souřadnice keše v zařízení</string> + <string name="waypoint_coordinates_couldnt_be_modified_on_website">Souřadnice keše nemohou být změněny na webu.</string> + <string name="waypoint_coordinates_upload_error">Při nahrávání souřadnic na web se vyskytla chyba.</string> + <string name="waypoint_coordinates_uploading_to_website">Nahrávám %s na web</string> + <string name="waypoint_coordinates_reseting_on_website">Obnovuji původní souřadnice keše na webu.</string> + <string name="waypoint_coordinates_has_been_modified_on_website">Souřadnice keše na webu byly změněny na %s.</string> + <string name="waypoint_coordinates_has_been_set_as_cache_coordinates">Souřadnice keše byly v zařízení změněny na: %s.</string> <!-- visit --> <string name="visit_tweet">informovat o nálezu na twitteru</string> diff --git a/main/res/values-da/strings.xml b/main/res/values-da/strings.xml index 7ff7408..d98a7fe 100644 --- a/main/res/values-da/strings.xml +++ b/main/res/values-da/strings.xml @@ -73,8 +73,6 @@ <string name="err_comm">Ukendt forbindelsesfejl</string> <string name="err_wrong">Fejl i login</string> <string name="err_license">Bruger accepterer betingelser på Geocaching.com</string> - <string name="err_store">Beklager, c:geo kan ikke gemme cachen.</string> - <string name="err_drop">Beklager, c:geo kan ikke slette cachen.</string> <string name="err_detail_open">Beklager, c:geo kan ikke indlæse cachedetaljer.</string> <string name="err_detail_cache">Beklager, c:geo kan ikke vise denne cache.</string> <string name="err_detail_cache_find">Beklager, c:geo kan ikke vise denne cache</string> @@ -82,7 +80,6 @@ <string name="err_detail_cache_forgot">Beklager, c:geo husker ikke hvilken cache du ønskede.</string> <string name="err_detail_no_spoiler">c:geo fandt ingen spoilerbilleder til denne cache.</string> <string name="err_detail_no_map_static">c:geo fandt ingen statiske kort til denne cache.</string> - <string name="err_navigation_no">c:geo kan ikke finde understøttet navigation.</string> <string name="err_application_no">c:geo kan ikke finde en passende applikation.</string> <string name="err_auth_initialize">Beklager, c:geo kan ikke gennemføre godkendelsen.</string> <string name="err_auth_process">Godkendelse fejlede.</string> @@ -150,7 +147,6 @@ <string name="init_disabled">Udelad deaktiverede cacher</string> <string name="init_offline">Gem kort til offlinebrug</string> <string name="init_units">Benyt britiske afstandsmål</string> - <string name="init_nav">Benyt Google Navigation</string> <string name="init_autoload">Auto-indlæs lang cachebeskrivelse</string> <string name="init_livelist">Vis retning til cacher i lister</string> <string name="init_cleared">c:geo slettede login-informationer.</string> @@ -202,7 +198,6 @@ <string name="cache_dialog_refresh_title">Genindlæs</string> <string name="cache_dialog_refresh_message">Genindlæser cachedetaljer…</string> <string name="cache_menu_navigate">Naviger</string> - <string name="cache_menu_tbt">Vejvisning</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Vis på kort</string> <string name="cache_menu_map_ext">Vis på ext. kort</string> diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml index d563608..73298f1 100644 --- a/main/res/values-de/strings.xml +++ b/main/res/values-de/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo Kompass</string> @@ -75,6 +75,8 @@ <string name="log_needs_archived">Sollte archiviert werden</string> <string name="log_discovered">Gesehen</string> <string name="log_reviewer">Review(er)-Anmerkung</string> + <string name="log_retractlisting">Listing zurückgezogen</string> + <string name="log_marked_missing">Als verloren gemeldet</string> <string name="log_tb_nothing">Keine Aktion</string> <string name="log_tb_visit">Besucht</string> <string name="log_tb_drop">Ablegen</string> @@ -87,9 +89,6 @@ <string name="log_post_no_rate">Loggen ohne Bewertung</string> <string name="log_post_not_possible">Lade Log-Seite…</string> <string name="log_add">Hinzufügen</string> - <string name="log_date">Datum</string> - <string name="log_time">Uhrzeit</string> - <string name="log_date_time">Datum & Uhrzeit</string> <string name="log_rating">Bewertung</string> <string name="log_no_rating">Keine Bewertung</string> <string name="log_stars_1">1 Stern</string> @@ -139,8 +138,6 @@ <string name="err_license">Die Geocaching.com Nutzungsbedingungen wurden nicht akzeptiert. c:geo kann deshalb keine Koordinaten laden.</string> <string name="err_unpublished">Der aufgerufene Cache ist noch nicht veröffentlicht</string> <string name="err_premium_only">Der Cache ist nur für Premium Mitglieder von Geocaching.com verfügbar</string> - <string name="err_store">c:geo konnte den Cache nicht speichern.</string> - <string name="err_drop">c:geo konnte den Cache nicht löschen.</string> <string name="err_detail_open">c:geo konnte die Cache-Details nicht öffnen.</string> <string name="err_detail_cache">c:geo konnte diesen Cache nicht darstellen. Ist es wirklich ein Cache?</string> <string name="err_detail_cache_find">c:geo konnte keinen Cache finden.</string> @@ -153,20 +150,15 @@ <string name="err_detail_no_spoiler">c:geo hat kein Hinweisbild für diesen Cache gefunden.</string> <string name="err_detail_no_map_static">c:geo hat keine statische Karte für diesen Cache gefunden.</string> <string name="err_detail_not_load_map_static">c:geo konnte die statische Karte nicht laden.</string> - <string name="err_detail_ask_store_map_static">c:geo konnte die statische Karte nicht laden. Jetzt speichern?</string> <string name="err_detail_still_working">Arbeite noch an anderer Aufgabe.</string> <string name="err_watchlist_still_managing">c:geo versucht noch immer die Watchlist zu aktualisieren.</string> <string name="err_watchlist_failed">Ändern der Watchlist nicht erfolgreich.</string> - <string name="err_navigation_no">c:geo konnte keine unterstützte Art der Navigation finden.</string> <string name="err_application_no">c:geo konnte keine passende Anwendung finden.</string> <string name="err_auth_initialize">c:geo konnte die Autorisierung nicht initialisieren.</string> <string name="err_auth_process">Autorisierung fehlgeschlagen.</string> <string name="err_cannot_log_visit">c:geo hat nicht genügend Informationen um den Besuch zu loggen. Bitte über die Cache-Details versuchen.</string> <string name="err_init_cleared">c:geo konnte die Anmeldedaten nicht entfernen.</string> <string name="err_download_fail">c:geo konnte keine Caches laden, weil </string> - <string name="err_list_load_fail">Laden der Cacheliste fehlgeschlagen.</string> - <string name="err_store_failed">Speichern des Caches fehlgeschlagen.</string> - <string name="err_refresh_failed">Aktualisierung fehlgeschlagen.</string> <string name="err_dwld_details_failed">Download der Cache-Details fehlgeschlagen.</string> <string name="err_load_descr_failed">Laden der Cachebeschreibung fehlgeschlagen.</string> <string name="err_location_unknown">c:geo erkennt die Position des Caches nicht.</string> @@ -174,18 +166,12 @@ <string name="err_tb_display">"c:geo kann den gewünschten Trackable nicht anzeigen. Ist es wirklich einer?</string> <string name="err_tb_details_open">c:geo konnte die Details des Trackables nicht öffnen.</string> - <string name="err_tb_details_download">c:geo konnte die Details des Trackables nicht laden, weil</string> - <string name="err_tb_forgot">c:geo hat vergessen, welcher Trackable geöffnet werden sollte.</string> <string name="err_tb_forgot_saw">c:geo hat vergessen, welcher Trackable gesehen wurde.</string> <string name="err_tb_find">c:geo findet den Trackable nicht</string> <string name="err_tb_find_that">c:geo konnte diesen Trackable nicht finden.</string> <string name="err_waypoint_cache_unknown">c:geo weiß nicht, zu welchem Cache der Wegpunkt hinzugefügt werden soll.</string> - <string name="err_waypoint_unknown">c:geo hat vergessen, welcher Wegpunkt angesehen werden sollte.</string> <string name="err_waypoint_add_failed">c:geo konnte den Wegpunkt nicht hinzufügen.</string> - <string name="err_waypoint_load_failed">c:geo konnte den Wegpunkt nicht laden.</string> - <string name="err_waypoint_delete_failed">c:geo konnte den Wegpunkt nicht löschen.</string> - <string name="err_waypoint_open_cache_failed">c:geo konnte die Cachedetails nicht laden.</string> <string name="err_point_unknown_position">c:geo konnte den aktuellen Standort nicht bestimmen.</string> <string name="err_point_no_position_given_title">Info benötigt</string> <string name="err_point_no_position_given">Mindestens Längen- und Breitengrad oder Entfernung und Richtung angeben. Auch alle Angaben sind möglich.</string> @@ -200,15 +186,12 @@ <string name="err_log_failed_server">c:geo konnte Log nicht senden, weil der Server nicht antwortete.</string> <string name="err_log_post_failed">c:geo konnte Log nicht absenden.</string> - <string name="err_search_address_no_match">Keinen passenden Ort gefunden.</string> <string name="err_search_address_forgot">c:geo hat die Adresse vergessen, die gesucht wurde.</string> <string name="err_parse_lat">c:geo konnte den Breitengrad nicht verarbeiten.</string> <string name="err_parse_lon">c:geo konnte den Längengrad nicht verarbeiten.</string> <string name="err_parse_dist">c:geo konnte die Entfernung nicht verarbeiten.</string> <string name="err_parse_lat_lon">c:geo konnte den Breiten- oder Längengrad nicht verarbeiten.</string> - <string name="err_fieldnotes_export_failed">Exportieren der Field-Notes fehlgeschlagen.</string> - <string name="warn_save_nothing">Es gibt nichts zum Speichern.</string> <string name="warn_no_cache_coord">Es gibt hier keinen Cache mit Koordinaten.</string> <string name="warn_no_coordinates">Keine Koordinaten angegeben.</string> @@ -232,7 +215,6 @@ <string name="info_log_cleared">Log wurde geleert.</string> <string name="info_log_type_changed">Logtyp wurde verändert!</string> - <string name="info_fieldnotes_exported_to">Field-Notes exportiert nach</string> <string name="info_storing_static_maps">Versuche, statische Karten zu speichern</string> <!-- location service --> @@ -306,6 +288,7 @@ <string name="caches_drop_stored">Gespeicherte löschen</string> <string name="caches_drop_progress">Entferne Caches…</string> <string name="caches_drop_all_and_list">Alle und Liste löschen</string> + <string name="caches_delete_events">Vergangene Events löschen</string> <string name="caches_refresh_selected">Ausgewählte aktualisieren</string> <string name="caches_refresh_all">Alle aktualisieren</string> <string name="caches_move_selected">Ausgewählte verschieben</string> @@ -322,10 +305,7 @@ <string name="caches_filter_type">Typ</string> <string name="caches_filter_track">Mit Trackables</string> <string name="caches_filter_clear">Filter zurücksetzen</string> - <string name="caches_filter_size_title">Größe wählen</string> - <string name="caches_filter_type_title">Typ wählen</string> <string name="caches_filter_modified">Mit geänderten Koordinaten</string> - <string name="caches_exporting_fieldnote">Exportiere als Field-Notes…</string> <string name="caches_removing_from_history">Lösche aus Verlauf…</string> <!-- caches lists --> @@ -361,6 +341,10 @@ <!-- init --> <string name="init_geocaching">Geocaching.com</string> + <string name="init_oc">opencaching.de</string> + <string name="init_oc_activate">Opencaching.de auf Live-Karte und für die Suche aktivieren</string> + <string name="init_oc_username_description">Benutzername für opencaching.de eingeben damit gefundene Caches markiert werden können.</string> + <string name="init_oc_username">Benutzername</string> <string name="init_gcvote">GCvote.com</string> <string name="init_twitter">Twitter</string> <string name="init_username">Benutzername</string> @@ -403,7 +387,6 @@ <string name="init_offline_wp">Statische Karten zu Wegpunkten für Offline-Verwendung speichern</string> <string name="init_save_log_img">Logbilder abspeichern</string> <string name="init_units">Imperiale Einheiten (Meilen/Fuß)</string> - <string name="init_nav">Google Navigation verwenden</string> <string name="init_log_offline">Offline loggen (Dialog für Online-Log nicht anzeigen)</string> <string name="init_livelist">Richtung zum Cache in der Cache-Liste anzeigen</string> <string name="init_altitude">Höhenkorrektur</string> @@ -427,16 +410,11 @@ <string name="init_mapsources">Kartenherkunft</string> <string name="init_mapsources_description">Hier kann die Quelle der benutzten Karte gewählt werden. Alternativ zu Google Maps stehen verschiedene OpenStreetMap-Stile zur Verfügung und daneben auch Karten-Dateien für die Offline-Nutzung (siehe http://code.google.com/p/mapsforge/ für die Details).\nWeiterhin werden verschiedene Darstellungen(Themes) für Offline-Karten unterstützt.</string> <string name="init_mapsource_select">Kartenquelle wählen</string> - <string name="init_select_themefolder">…</string> - <string name="init_select_gpx_exportdir">…</string> - <string name="init_select_gpx_importdir">…</string> <string name="init_map_directory_description">Verzeichnis mit Offline-Karten</string> <string name="init_gpx_exportdir">Verzeichnis für GPX-Exporte</string> <string name="init_gpx_importdir">Verzeichnis für GPX-Importe</string> <string name="init_gpx_exportdir_description">Hier kann das Verzeichnis für GPX-Exporte gewählt werden.</string> <string name="init_gpx_importdir_description">Hier kann das Verzeichnis für GPX-Importe gewählt werden.</string> - <string name="init_gpx_exportdir_select">Wähle Verzeichnis für GPX-Exporte</string> - <string name="init_gpx_importdir_select">Wähle Verzeichnis für GPX-Importe</string> <string name="init_maptrail">Zeige Spur auf Karte</string> <string name="init_share_after_export">Weiterleiten nach dem Export</string> <string name="init_trackautovisit">Trackables automatisch auf \"besuchen\" setzen</string> @@ -452,7 +430,6 @@ <string name="init_dbonsdcard_title">Datenspeicherung</string> <string name="init_dbonsdcard_note">Die Datenbank von c:geo kann auf eine externe Speicherkarte verschoben werden. Hiermit kann interner Speicher gespart werden, allerdings wird sich die Leistung etwas reduzieren und c:geo funktioniert nicht mehr ohne verfügbare Speicherkarte.</string> <string name="init_dbonsdcard">Datenbank auf externer Karte</string> - <string name="init_dbmove">Verschiebe Datenbank</string> <string name="init_dbmove_dbmove">Verschiebe Datenbank</string> <string name="init_dbmove_running">Verschiebe Datenbank</string> <string name="init_dbmove_success">Die Datenbank wurde erfolgreich verschoben.</string> @@ -510,7 +487,6 @@ <string name="cache_offline_time_days">Tagen</string> <string name="cache_premium">Premium</string> <string name="cache_attributes">Attribute</string> - <string name="cache_attributes_no_icons">(aktualisiere den Cache um die Attribut-Icons anzuzeigen)</string> <string name="cache_inventory">Inventar</string> <string name="cache_log_offline">Offline-Log</string> <string name="cache_log_images_loading">Lade Logbild…</string> @@ -521,7 +497,6 @@ <string name="cache_description">Beschreibung</string> <string name="cache_description_long">Ausführliche Beschreibung</string> <string name="cache_description_table_note">Diese Beschreibung enthält Tabellenelemente, die evtl. nur auf Geocaching.com korrekt angezeigt werden.</string> - <string name="cache_watchlist">Watchlist</string> <string name="cache_watchlist_on">Dieser Cache ist auf deiner Watchlist.</string> <string name="cache_watchlist_not_on">Dieser Cache ist nicht auf deiner Watchlist.</string> <string name="cache_watchlist_add">Hinzufügen</string> @@ -562,7 +537,9 @@ <string name="cache_dialog_watchlist_remove_title">Watchlist</string> <string name="cache_dialog_watchlist_remove_message">Entferne den Cache von deiner Watchlist…</string> <string name="cache_menu_navigate">Navigieren</string> - <string name="cache_menu_tbt">Google Maps Navigation</string> + <string name="cache_menu_navigation_drive">Navigation (Fahren)</string> + <string name="cache_menu_navigation_walk">Navigation (Gehen)</string> + <string name="cache_menu_maps_directions">Google Maps Route</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Karte</string> <string name="cache_menu_map_static">Statische Karten</string> @@ -610,7 +587,6 @@ <string name="cache_spoiler_images_loading">Lade Hinweisbilder…</string> <string name="cache_log_types">Logs</string> <string name="cache_coordinates_no">Dieser Cache hat keine Koordinaten.</string> - <string name="cache_export_fieldnote">Exportiere als Field-Notes</string> <string name="cache_clear_history">Verlauf leeren</string> <string name="cache_remove_from_history">Aus Verlauf löschen</string> <string name="cache_license">Lizenz</string> @@ -638,7 +614,6 @@ <string name="gpx_import_loading_caches">Lade Caches aus GPX-Datei</string> <string name="gpx_import_loading_waypoints">Lade Wegpunkte aus GPX-Datei</string> <string name="gpx_import_store_static_maps">Schreibe statische Karten</string> - <string name="gpx_import_storing">Schreibe Caches in Datenbank</string> <string name="gpx_import_caches_imported">Caches importiert</string> <string name="gpx_import_static_maps_skipped">Download statischer Karten abgebrochen</string> <string name="gpx_import_title_static_maps">Speichern statischer Karten</string> @@ -658,10 +633,7 @@ <string name="map_file_select_title">Kartendatei wählen</string> <!-- theme file select --> - <string name="theme_file_select_title">Karten-Theme wählen</string> - <!-- import --> - <string name="import_title">Importiere…</string> <string name="web_import_title">Aus dem Internet importieren</string> <string name="web_import_waiting">Warte auf neue Caches aus dem Internet…</string> <string name="web_downloading">Lade herunter</string> @@ -672,8 +644,7 @@ <!-- waypoint --> <string name="waypoint">Wegpunkt</string> - <string name="waypoint_title">Wegpunkt</string> - <string name="waypoint_cache_coordinates">Cache Koordinaten</string> + <string name="waypoint_cache_coordinates">Cache-Koordinaten</string> <string name="waypoint_custom">Benutzerdefiniert</string> <string name="waypoint_my_coordinates">Meine Koordinaten</string> <string name="waypoint_bearing">Richtung in °</string> @@ -686,11 +657,22 @@ <string name="waypoint_note">Notiz</string> <string name="waypoint_save">Speichern</string> <string name="waypoint_loading">Lade Wegpunkt…</string> - <string name="waypoint_unknown_coordinates">Unbekannte Koordinaten</string> + <string name="waypoint_set_as_cache_coords">Als Cache-Koordinaten lokal setzen</string> + <string name="waypoint_reset_cache_coords">Zurücksetzen</string> + <string name="waypoint_coordinates_has_been_reset_on_website">Koordinaten auf Webseite zurückgesetzt</string> + <string name="waypoint_coordinates_being_reset_on_website">Koordinaten werden zurückgesetzt</string> + <string name="waypoint_reset_cache_coords_info">Rücksetz-Optionen</string> + <string name="waypoint_reset">Zurücksetzen</string> + <string name="waypoint_localy_reset_cache_coords">Koodinaten lokal zurücksetzen</string> + <string name="waypoint_coordinates_couldnt_be_modified_on_website">Cache-Koordinaten auf der Webseite konnten nicht zurückgesetzt werden</string> + <string name="waypoint_coordinates_upload_error">Fehler beim Hochladen der Koordinaten zur Webseite</string> + <string name="waypoint_coordinates_uploading_to_website">Setze %s auf der Webseite</string> + <string name="waypoint_coordinates_reseting_on_website">Setze Koordinaten auf der Webseite zurück</string> + <string name="waypoint_coordinates_has_been_modified_on_website">Koordinaten wurden auf der Webseite geändert: %s</string> + <string name="waypoint_coordinates_has_been_set_as_cache_coordinates">Koordinaten wurden lokal geändert: %s</string> <string name="waypoint_done">Fertig</string> <string name="waypoint_duplicate">Duplizieren</string> <string name="waypoint_copy_of">Kopie von</string> - <string name="waypoint_menu_open_cache">Cache öffnen</string> <string name="search_history">Verlauf</string> <string name="search_history_empty">Keine Ziele bisher</string> <string name="search_remove_destination">Ziel gelöscht</string> @@ -828,7 +810,6 @@ <!-- export --> <string name="export">Exportieren</string> - <string name="export_as">Exportieren als…</string> <string name="export_exportedto">exportiert nach</string> <string name="export_failed">Exportieren fehlgeschlagen</string> <string name="export_fieldnotes">Field Notes</string> @@ -1000,11 +981,11 @@ <string name="about_auth_2">Ein Klick auf \"Starte Autorisierung\" öffnet eine Twitter-Seite in einem Browserfenster. Durch die Anmeldung und die Bestätigung wird <b>c:geo</b> ermöglicht, auf den persönlichen Twitter-Account zuzugreifen. Wird dies bestätigt, nennt Twitter eine numerische PIN, diese muss kopiert und in <b>c:geo</b> eingefügt werden. Das ist alles.</string> <!-- status --> - <string name="status_new_release">Neuer Release verfügbar.\nKlicken zum Installieren.</string> - <string name="status_new_nightly">Neuer Nightly Build verfügbar.\nKlicken zum Installieren.</string> - <string name="status_new_rc">Neuer Release Candidate verfügbar.\nKlicken zum Installieren.</string> - <string name="status_geocaching_change">Änderungen auf geocaching.com führen zu Problemen mit c:geo.\nWir arbeiten daran.</string> - <string name="status_geocaching_livemap">Änderungen auf geocaching.com führen zu Problemen mit der Live Map.\nWir arbeiten daran.</string> + <string name="status_new_release" tools:ignore="UnusedResources">Neuer Release verfügbar.\nKlicken zum Installieren.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">Neuer Nightly Build verfügbar.\nKlicken zum Installieren.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">Neuer Release Candidate verfügbar.\nKlicken zum Installieren.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">Änderungen auf geocaching.com führen zu Problemen mit c:geo.\nWir arbeiten daran.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Änderungen auf geocaching.com führen zu Problemen mit der Live Map.\nWir arbeiten daran.</string> <string name="clipboard_copy_ok">In Zwischenablage kopiert</string> <plurals name="days_ago"> diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml index 4fd9a29..f0fe8e1 100644 --- a/main/res/values-es/strings.xml +++ b/main/res/values-es/strings.xml @@ -81,9 +81,6 @@ <string name="log_post_rate">Enviar registro y puntuación</string> <string name="log_post_no_rate">Enviar registro sin puntuar</string> <string name="log_add">Añadir</string> - <string name="log_date">Fecha</string> - <string name="log_time">Hora</string> - <string name="log_date_time">Fecha y hora</string> <string name="log_rating">Puntuación</string> <string name="log_no_rating">Sin puntuación</string> <string name="log_stars_1">1 estrella</string> @@ -121,8 +118,6 @@ <string name="err_missing_auth">Falta nombre de usuario o contraseña.</string> <string name="err_wrong">Información de acceso errónea</string> <string name="err_license">El usuario no ha aceptado las condiciones de Geocaching.com license agreement, por lo que c:geo no puede cargar las coordenadas de los escondites.</string> - <string name="err_store">Lo siento, c:geo no puede almacenar el escondite.</string> - <string name="err_drop">Lo siento, c:geo no puede omitir el escondite.</string> <string name="err_detail_open">Lo siento, c:geo no puede abrir los detalles del escondite.</string> <string name="err_detail_cache">Lo siento, c:geo no puee mostrar el escondite que quieres. ¿Segur que es un geocache?</string> <string name="err_detail_cache_find">Lo siento, c:geo no puede encontrar escondites</string> @@ -136,16 +131,12 @@ <string name="err_detail_not_load_map_static">Lo siento, c:geo no ha podido cargar mapas estáticos.</string> <string name="err_watchlist_still_managing">Seguir gestionando tu lista de seguimiento.</string> <string name="err_watchlist_failed">Error al cambiar la lista de seguimiento.</string> - <string name="err_navigation_no">c:geo no encuentra ninguna navegación soportada.</string> <string name="err_application_no">c:geo no encuentra ninguna aplicación válida.</string> <string name="err_auth_initialize">Lo siento, c:geo no ha podido iniciar el proceso de autorización.</string> <string name="err_auth_process">El proceso de autorización ha fallado.</string> <string name="err_cannot_log_visit">c:geo no tiene información suficiente para registrar la visita. Inténtalo de nuevo con más detalles sobre el escondite.</string> <string name="err_init_cleared">Lo siento, c:geo no puede borrar la información registrada.</string> <string name="err_download_fail">Lo siento, c:geo no ha podido descargar escondites a causa de </string> - <string name="err_list_load_fail">Lo siento, c:geo no ha podido cargar la lista de escondites.</string> - <string name="err_store_failed">Lo siento, c:geo no puede guardar el escondite.</string> - <string name="err_refresh_failed">Lo siento, c:geo no puede actualizar el escondite.</string> <string name="err_dwld_details_failed">Lo siento, c:geo no ha podido descargar los detalles del escondite.</string> <string name="err_load_descr_failed">Lo siento, c:geo no ha podido cargar la descripción.</string> <string name="err_location_unknown">c:geo no conoce la ubicación del escondite.</string> @@ -153,17 +144,12 @@ <string name="err_tb_display">"Lo siento, c:geo no puede mostrar el rastreable que buscas. ¿Es realmente rastreable?</string> <string name="err_tb_details_open">Lo siento, c:geo no puede abrir los detalles del rastreable.</string> - <string name="err_tb_details_download">Lo siento, c:geo no ha podido descargar los detalles del rastreable a causa de</string> - <string name="err_tb_forgot">Lo siento, c:geo ha olvidado qué rastreable quieres.</string> <string name="err_tb_forgot_saw">Lo siento, c:geo ha olvidado qué rastreable has visto.</string> <string name="err_tb_find">Lo siento, c:geo no encuentra el rasteable</string> <string name="err_tb_find_that">Lo siento, c:geo no encuentra ese rastreable.</string> <string name="err_waypoint_cache_unknown">Lo siento, c:geo no sabe a qué escondite quieres añadir un punto de referencia.</string> - <string name="err_waypoint_unknown">Lo siento, c:geo ha olvidado qué punto de referencia quieres visualizar.</string> <string name="err_waypoint_add_failed">Lo siento, c:geo no ha podido añadir tu punto de referencia.</string> - <string name="err_waypoint_load_failed">Lo siento, c:geo no ha podido cargar el punto de referencia.</string> - <string name="err_waypoint_delete_failed">Lo siento, c:geo no puede borrar el punto de referencia.</string> <string name="err_point_unknown_position">Lo siento, c:geo n puedo identificar donde estás.</string> <string name="err_point_no_position_given_title">Información obligatoria</string> <string name="err_point_no_position_given">Rellena como mínimo latitud y longitud o distancia y orientación. También puedes rellenar los cuatro campos.</string> @@ -179,14 +165,11 @@ <string name="err_log_failed_server">Lo siento, c:geo no ha podido enviar el registro porque el servidor no responde.</string> <string name="err_log_post_failed">Lo siento, c:geo no ha podido enviar el registro.</string> - <string name="err_search_address_no_match">Lo siento, c:geo no encuentra ningún lugar coincidente.</string> <string name="err_search_address_forgot">Lo siento, c:geo ha olvidado la dirección que buscabas.</string> <string name="err_parse_lat">Lo siento, c:geo no puede procesar la latitud.</string> <string name="err_parse_lon">Lo siento, c:geo no puede procesar la longitud.</string> <string name="err_parse_dist">Lo siento, c:geo can\'t no puede procesar la distancia.</string> - <string name="err_fieldnotes_export_failed">Eror al exportar notas de campo.</string> - <string name="warn_save_nothing">No hay nada para guardar.</string> <string name="warn_no_cache_coord">No hay escondite con coordenadas.</string> <string name="warn_no_coordinates">No se han dado coordenadas.</string> @@ -208,8 +191,6 @@ <string name="info_log_cleared">Registro borrado.</string> <string name="info_log_type_changed">¡El tipo de registro ha sido cambiado!</string> - <string name="info_fieldnotes_exported_to">Notas de campo exportadas a</string> - <!-- location service --> <string name="loc_last">Última conocida</string> <string name="loc_net">Red</string> @@ -287,9 +268,6 @@ <string name="caches_filter_type">tipo</string> <string name="caches_filter_track">con rastreables</string> <string name="caches_filter_clear">limpiar filtros</string> - <string name="caches_filter_size_title">Indica tamaño</string> - <string name="caches_filter_type_title">Indica tipo</string> - <string name="caches_exporting_fieldnote">Exportando como Notas de campo…</string> <string name="caches_removing_from_history">Borrando del historial…</string> <!-- caches lists --> @@ -351,7 +329,6 @@ <string name="init_offline">Guardar mapas para usar sin conexión</string> <string name="init_save_log_img">Guardar imágenes de los registros</string> <string name="init_units">Usar millas/pies (unidades imperiales)</string> - <string name="init_nav">Usar Google Navigation</string> <string name="init_autoload">Autocargar descripción larga</string> <string name="init_livelist">Mostrar dirección a los escondites en su listado</string> <string name="init_altitude">Corrección de altitud</string> @@ -430,7 +407,6 @@ <string name="cache_log_image_default_title">Foto</string> <string name="cache_personal_note">Nota personal</string> <string name="cache_description">Descripción</string> - <string name="cache_watchlist">Lista de seguimiento</string> <string name="cache_watchlist_on">Este escondite está en tu Lista de seguimiento.</string> <string name="cache_watchlist_not_on">Este escondite no está en tu Lista de seguimiento.</string> <string name="cache_watchlist_add">Añadir a Lista de seguimiento</string> @@ -452,7 +428,6 @@ <string name="cache_dialog_watchlist_remove_title">Lista de seguimiento</string> <string name="cache_dialog_watchlist_remove_message">Borrando escondite de tu Lista de seguimiento…</string> <string name="cache_menu_navigate">Navegar</string> - <string name="cache_menu_tbt">Paso a paso</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Ver en mapa</string> <string name="cache_menu_map_static">Mapas estáticos</string> @@ -493,7 +468,6 @@ <string name="cache_spoiler_images_loading">Cargando imágenes reveladoras…</string> <string name="cache_log_types">Tipos de registro</string> <string name="cache_coordinates_no">Este escondite no tiene coordenadas.</string> - <string name="cache_export_fieldnote">Exportar como Notas de campo</string> <string name="cache_clear_history">Borrar historial</string> <string name="cache_remove_from_history">Borrar del historial</string> @@ -514,7 +488,6 @@ <string name="map_file_select_title">Selecciona un mapa</string> <!-- import --> - <string name="import_title">Importar…</string> <string name="web_import_title">Importar de la web</string> <string name="web_import_waiting">Esperando por nuevos escondites desde la web…</string> <string name="web_downloading">Descargando</string> @@ -524,7 +497,6 @@ <string name="popup_more">Más detalles</string> <!-- waypoint --> - <string name="waypoint_title">Punto de referencia</string> <string name="waypoint_custom">A medida</string> <string name="waypoint_my_coordinates">Mis coordenadas</string> <string name="waypoint_bearing">Orientación</string> @@ -537,7 +509,6 @@ <string name="waypoint_note">Nota</string> <string name="waypoint_save">Guardar</string> <string name="waypoint_loading">Cargando punto de referencia…</string> - <string name="waypoint_unknown_coordinates">Coordenadas desconocidas</string> <string name="search_history">Historial</string> <string name="search_history_empty">No hay destinos anteriores</string> <string name="search_remove_destination">Destino borrado</string> diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml index 35e2d8f..d75d8b4 100644 --- a/main/res/values-fr/strings.xml +++ b/main/res/values-fr/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">boussole c:geo</string> @@ -88,9 +88,6 @@ <string name="log_post_no_rate">Envoyer & ne pas noter</string> <string name="log_post_not_possible">Chargement de la page…</string> <string name="log_add">Ajouter</string> - <string name="log_date">Date</string> - <string name="log_time">Heure</string> - <string name="log_date_time">Date & heure</string> <string name="log_rating">Note</string> <string name="log_no_rating">Pas de note</string> <string name="log_stars_1">1 étoile</string> @@ -139,8 +136,6 @@ <string name="err_license">L\'utilisateur n\'a pas accepté les termes et les conditions d\'utilisation de Geocaching.com</string> <string name="err_unpublished">La cache a été retirée de la publication</string> <string name="err_premium_only">La cache est réservée aux membres Premium de Geocaching.com</string> - <string name="err_store">c:geo ne peut pas enregister la cache.</string> - <string name="err_drop">c:geo ne peut pas effacer la cache.</string> <string name="err_detail_open">c:geo ne peut pas ouvrir le détail de la cache.</string> <string name="err_detail_cache">c:geo ne peut pas afficher cette cache. Est-ce vraiment une géocache?</string> <string name="err_detail_cache_find">c:geo ne peut pas trouver de caches</string> @@ -153,20 +148,15 @@ <string name="err_detail_no_spoiler">c:geo n\'a pas trouvé d\'image indice pour cette cache.</string> <string name="err_detail_no_map_static">c:geo n\'a pas trouvé de cartes statiques pour cette cache.</string> <string name="err_detail_not_load_map_static">c:geo n\'a pas réussi à charger les cartes statiques.</string> - <string name="err_detail_ask_store_map_static">c:geo n\'a pas réussi à charger les cartes statiques. Les stocker maintenant ?</string> <string name="err_detail_still_working">Autre tâche déjà en cours.</string> <string name="err_watchlist_still_managing">Liste de suivi toujours en traitement.</string> <string name="err_watchlist_failed">Échec lors du changement de votre liste de suivi.</string> - <string name="err_navigation_no">c:geo ne trouve pas de navigation supportée.</string> <string name="err_application_no">c:geo ne trouve pas d\'application conforme.</string> <string name="err_auth_initialize">c:geo a échoué dans la demande d\'autorisation.</string> <string name="err_auth_process">Échec de la demande d\'autorisation.</string> <string name="err_cannot_log_visit">c:geo n\'a pas assez d\'information pour logger votre visite. Faites le depuis le détail de la cache, s\'il vous plait!</string> <string name="err_init_cleared">c:geo ne peux pas effacer votre nom d\'utilisateur.</string> <string name="err_download_fail">c:geo n\'a pas réussi à télécharger les caches car </string> - <string name="err_list_load_fail">c:geo n\'a pas réussi à charger la liste des caches.</string> - <string name="err_store_failed">c:geo ne peut pas enregistrer la cache.</string> - <string name="err_refresh_failed">c:geo ne peut pas rafraîchir la cache.</string> <string name="err_dwld_details_failed">c:geo n\'a pas réussi à télécharger les détails de la cache.</string> <string name="err_load_descr_failed">c:geo ne peut pas charger la description.</string> <string name="err_location_unknown">c:geo ne connait pas la position de la cache.</string> @@ -174,18 +164,12 @@ <string name="err_tb_display">"c:geo ne peut pas afficher l\'objet voyageur demandé. Est-ce vraiment un objet voyageur?</string> <string name="err_tb_details_open">c:geo ne peut pas ouvrir le détail de l\'objet voyageur.</string> - <string name="err_tb_details_download">c:geo ne peut pas télécharger le détail de l\'objet voyageur car </string> - <string name="err_tb_forgot">c:geo a oublié quel objet voyageur vous vouliez.</string> <string name="err_tb_forgot_saw">c:geo a oublié quel objet voyageur vous avez vu.</string> <string name="err_tb_find">c:geo ne peut pas trouver d\'objet voyageur.</string> <string name="err_tb_find_that">c:geo ne peut pas trouver cet objet voyageur.</string> <string name="err_waypoint_cache_unknown">c:geo ne sait pas à quel cache vous voulez ajouter une étape.</string> - <string name="err_waypoint_unknown">c:geo a oublié quel étape vous vouliez afficher.</string> <string name="err_waypoint_add_failed">c:geo n\'a pas réussi à afficher l\'étape.</string> - <string name="err_waypoint_load_failed">c:geo n\'arrive pas à charger l\'étape.</string> - <string name="err_waypoint_delete_failed">c:geo ne peut pas effacer l\'étape.</string> - <string name="err_waypoint_open_cache_failed">c:geo n\'a pas réussi à obtenir les détails de la cache.</string> <string name="err_point_unknown_position">c:geo ne peut pas savoir où vous êtes.</string> <string name="err_point_no_position_given_title">Information obligatoire</string> <string name="err_point_no_position_given">Remplissez au moins la latitude ou la longitude ou la distance et le relèvement. Vous pouvez aussi remplir tous les champs.</string> @@ -200,15 +184,12 @@ <string name="err_log_failed_server">c:geo n\'a pas réussi à charger les données pour enregistrer votre visite car le serveur ne répond pas.</string> <string name="err_log_post_failed">Il semble que votre visite n\'a pas été enregistrée. Veuillez vérifier sur le site geocaching.com.</string> - <string name="err_search_address_no_match">c:geo n\'a pas trouvé de lieu correspondant.</string> <string name="err_search_address_forgot">c:geo a oublié l\'adresse recherchée.</string> <string name="err_parse_lat">c:geo n\'arrive pas à lire la latitude.</string> <string name="err_parse_lon">c:geo n\'arrive pas à lire la longitude.</string> <string name="err_parse_dist">c:geo n\'arrive pas à lire la distance.</string> <string name="err_parse_lat_lon">c:geo n\'arrive pas à lire la latitude ou la longitude.</string> - <string name="err_fieldnotes_export_failed">L\'export du champ Notes a échoué.</string> - <string name="warn_save_nothing">Il n\'y a rien à sauver.</string> <string name="warn_no_cache_coord">Il n\'y pas de caches avec les coordonnées associées.</string> <string name="warn_no_coordinates">Aucune coordonnée associée.</string> @@ -231,7 +212,6 @@ <string name="info_log_cleared">La visite a été effacée.</string> <string name="info_log_type_changed">Le type de visite a changé!</string> - <string name="info_fieldnotes_exported_to">Notes exporté vers</string> <string name="info_storing_static_maps">Sauvegarde des cartes statiques</string> <!-- location service --> @@ -319,10 +299,7 @@ <string name="caches_filter_type">type</string> <string name="caches_filter_track">avec des trackables</string> <string name="caches_filter_clear">effacer les filtres</string> - <string name="caches_filter_size_title">Choisir la taille</string> - <string name="caches_filter_type_title">Choisir le type</string> <string name="caches_filter_modified">Avec les coordonnées modifiées</string> - <string name="caches_exporting_fieldnote">Exporter commme notes de terrain…</string> <string name="caches_removing_from_history">Effacer de l\'historique…</string> <!-- caches lists --> @@ -400,7 +377,6 @@ <string name="init_offline_wp">Enregistrer les cartes autour des points intermédiaires pour une utilisation hors ligne</string> <string name="init_save_log_img">Sauver les images des visites</string> <string name="init_units">Utiliser des unités de distance impériales</string> - <string name="init_nav">Utiliser Google Navigation</string> <string name="init_log_offline">Toujours utiliser le mode hors-ligne, même si connecté.</string> <string name="init_livelist">Afficher la direction des caches dans les listes</string> <string name="init_altitude">Correction de l\'altitude</string> @@ -438,7 +414,6 @@ <string name="init_dbonsdcard_title">Emplacement de la base</string> <string name="init_dbonsdcard_note">La base de données de c:geo peut être enregistrée sur un support externe. En choisissant cette option, vous récupérerez de l\'espace de stockage sur votre appareil au détriment de performances réduites. c:geo ne fonctionnera pas si votre carte SD est absente.</string> <string name="init_dbonsdcard">Base de données sur stockage externe</string> - <string name="init_dbmove">Déplacement de la base de données</string> <string name="init_dbmove_dbmove">Déplacement de la base de données</string> <string name="init_dbmove_running">Déplacement de la base de données</string> <string name="init_dbmove_success">Base de données déplacée</string> @@ -493,7 +468,6 @@ <string name="cache_offline_time_days">jours</string> <string name="cache_premium">Premium</string> <string name="cache_attributes">Attributs</string> - <string name="cache_attributes_no_icons">(recharger la cache pour voir les icônes des attributs)</string> <string name="cache_inventory">Inventaire</string> <string name="cache_log_offline">Visite hors-ligne</string> <string name="cache_log_images_loading">Chargement de l\'image de la visite…</string> @@ -503,7 +477,6 @@ <string name="cache_description">Description</string> <string name="cache_description_long">Description longue</string> <string name="cache_description_table_note">La description contient des informations de formattages qui nécessitent possiblement d\'être vues sur le site geocaching.com pour être affichées correctement.</string> - <string name="cache_watchlist">Liste de suivi</string> <string name="cache_watchlist_on">Cette cache est dans votre liste de suivi.</string> <string name="cache_watchlist_not_on">Cette cache n\'est pas dans votre liste de suivi.</string> <string name="cache_watchlist_add">Ajouter à votre liste de suivi</string> @@ -543,7 +516,6 @@ <string name="cache_dialog_watchlist_remove_title">Liste de suivi</string> <string name="cache_dialog_watchlist_remove_message">Retrait de la cache de votre liste de suivi…</string> <string name="cache_menu_navigate">Navigation</string> - <string name="cache_menu_tbt">Itinéraire</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Carte</string> <string name="cache_menu_map_static">Cartes statiques</string> @@ -590,7 +562,6 @@ <string name="cache_spoiler_images_loading">Chargement des images indices…</string> <string name="cache_log_types">Types de visites</string> <string name="cache_coordinates_no">Cette cache n\'a pas de coordonnées.</string> - <string name="cache_export_fieldnote">Export en tant que champ Notes</string> <string name="cache_clear_history">Effacer l\'historique</string> <string name="cache_remove_from_history">Effacer de l\'historique</string> <string name="cache_license">Licence</string> @@ -610,7 +581,6 @@ <string name="gpx_import_loading_caches">Chargement des caches depuis le fichier .gpx</string> <string name="gpx_import_loading_waypoints">Chargement des points intermédiaires depuis le fichier .gpx</string> <string name="gpx_import_store_static_maps">Écriture des cartes statiques</string> - <string name="gpx_import_storing">Écriture des caches dans la base de données\nEnregistrés :</string> <string name="gpx_import_caches_imported">caches importées</string> <string name="gpx_import_static_maps_skipped">Chargement des cartes statiques interrompu</string> <string name="gpx_import_title_static_maps">Enregistrement des cartes statiques</string> @@ -628,7 +598,6 @@ <string name="map_file_select_title">Choisir un fichier carte</string> <!-- import --> - <string name="import_title">Import…</string> <string name="web_import_title">Import depuis le web</string> <string name="web_import_waiting">En attente de nouvelles caches depuis le web…</string> <string name="web_downloading">Téléchargement</string> @@ -639,7 +608,6 @@ <!-- waypoint --> <string name="waypoint">Étape</string> - <string name="waypoint_title">Étape</string> <string name="waypoint_cache_coordinates">Coordonnées de la cache</string> <string name="waypoint_custom">Personnalisé</string> <string name="waypoint_my_coordinates">Ma position</string> @@ -653,11 +621,9 @@ <string name="waypoint_note">Note</string> <string name="waypoint_save">Sauver</string> <string name="waypoint_loading">Chargement d\'une étape…</string> - <string name="waypoint_unknown_coordinates">Coordonnées inconnues</string> <string name="waypoint_done">Ok</string> <string name="waypoint_duplicate">Dupliquer</string> <string name="waypoint_copy_of">Copie de</string> - <string name="waypoint_menu_open_cache">Ouvrir la cache</string> <string name="search_history">Historique</string> <string name="search_history_empty">Aucune destination précédente</string> <string name="search_remove_destination">Destination effacée</string> @@ -792,7 +758,6 @@ <!-- export --> <string name="export">Exporter</string> - <string name="export_as">Exporter en tant que…</string> <string name="export_exportedto">exporté vers</string> <string name="export_failed">Échec de l\'exportation</string> <string name="export_fieldnotes">Notes de terrain</string> @@ -961,11 +926,11 @@ <string name="about_auth_2">Cliquer sur le bouton \"début d\'autorisation\" pour démarrer. Une fenêtre de navigateur va s\'ouvrir pour vous connecter sur Twitter. Accepter pour que <b>c:geo</b> accéde à votre compte. Twitter vous affichera alors une code PIN composé de chiffres. Merci de coller ce code dans <b>c:geo</b> puis confirmer. C\'est tout!</string> <!-- status --> - <string name="status_new_release">Nouvelle version disponible.\nCliquer pour installer.</string> - <string name="status_new_nightly">Nouvelle version de test disponible.\nCliquer pour installer.</string> - <string name="status_new_rc">Nouvelle version candidate disponible.\nCliquer pour installer.</string> - <string name="status_geocaching_change">Des changements récents sur geocaching.com ont cassé c:geo.\nNous sommes en train de nous en occuper.</string> - <string name="status_geocaching_livemap">Des changements récents sur geocaching.com ont cassé la carte active.\nNous sommes en train de nous en occuper.</string> + <string name="status_new_release" tools:ignore="UnusedResources">Nouvelle version disponible.\nCliquer pour installer.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">Nouvelle version de test disponible.\nCliquer pour installer.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">Nouvelle version candidate disponible.\nCliquer pour installer.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">Des changements récents sur geocaching.com ont cassé c:geo.\nNous sommes en train de nous en occuper.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Des changements récents sur geocaching.com ont cassé la carte active.\nNous sommes en train de nous en occuper.</string> <string name="clipboard_copy_ok">Copié dans le presse-papiers</string> <plurals name="days_ago"> diff --git a/main/res/values-hu/strings.xml b/main/res/values-hu/strings.xml index 7b3239d..94da99f 100644 --- a/main/res/values-hu/strings.xml +++ b/main/res/values-hu/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo iránytű</string> @@ -87,9 +87,6 @@ <string name="log_post_no_rate">Log beküldése & nincs értékelés</string> <string name="log_post_not_possible">Log oldal betöltése…</string> <string name="log_add">Hozzáadás</string> - <string name="log_date">Dátum</string> - <string name="log_time">Idő</string> - <string name="log_date_time">Dátum & idő</string> <string name="log_rating">Értékelés</string> <string name="log_no_rating">Nincs értékelés</string> <string name="log_stars_1">1 csillag</string> @@ -139,8 +136,6 @@ <string name="err_license">A felhasználó nem fogadta el a geocaching.com licenszmegállapodását, így a c:geo nem tudja betölteni a ládák koordinátáit.</string> <string name="err_unpublished">A kért geoládát eltávolították.</string> <string name="err_premium_only">Ez a geoláda csak a Geocaching.com prémium felhasználóinak elérhető.</string> - <string name="err_store">Sajnáljuk, a c:geo nem tudja menteni a ládát.</string> - <string name="err_drop">Sajnáljuk, a c:geo nem tudja elvetni a ládát.</string> <string name="err_detail_open">Sajnáljuk, a c:geo nem tudja megnyitni a geoláda részletes adatait.</string> <string name="err_detail_cache">Sajnáljuk, a c:geo nem tudja megmutatni a geoládát amit szeretnél. Biztos hogy ez egy geoláda?</string> <string name="err_detail_cache_find">Sajnáljuk, a c:geo nem találja a geoládát.</string> @@ -153,20 +148,15 @@ <string name="err_detail_no_spoiler">A c:geo nem talált spoiler képeket ehhez a ládához.</string> <string name="err_detail_no_map_static">A c:geo nem talált statikus térképeket ehhez a ládához.</string> <string name="err_detail_not_load_map_static">Sajnáljuk, a c:geo nem tudott betölteni statikus térképeket.</string> - <string name="err_detail_ask_store_map_static">A c:geonak nem sikerült betölteni a statikus térképeket. Mentés?</string> <string name="err_detail_still_working">Egy másik feladat még folyamatban van.</string> <string name="err_watchlist_still_managing">Még folyik a figyelőlista kezelése.</string> <string name="err_watchlist_failed">A figyelőlita megváltoztatása nem sikerült.</string> - <string name="err_navigation_no">A c:geo nem talál semilyen támogatott navigációt.</string> <string name="err_application_no">A c:geo nem talál megfelelő alkalmazást.</string> <string name="err_auth_initialize">Sajnáljuk, a c:geo nem tudta elindítani az engedélyezési eljárást.</string> <string name="err_auth_process">Az engedélyezési eljárás sikertelen.</string> <string name="err_cannot_log_visit">A c:geo-nak nincs elég információja a láda logolásához. Kérlek logold a ládát a teljes láda leírásnál.</string> <string name="err_init_cleared">Sajnáljuk, a c:geo nem tudja törölni a belépési adatokat.</string> <string name="err_download_fail">Sajnáljuk, a c:geo nem tudja letölteni a ládákat, mert </string> - <string name="err_list_load_fail">Sajnáljuk, a c:geo nem tudja betölteni a ládalistát.</string> - <string name="err_store_failed">Sajnáljuk, a c:geo nem tudja elmenteni a geoládát.</string> - <string name="err_refresh_failed">Sajnáljuk, a c:geo nem tudjarefresh geocache.</string> <string name="err_dwld_details_failed">Sajnáljuk, a c:geo nem tudja letölteni a láda adatait.</string> <string name="err_load_descr_failed">Sajnáljuk, a c:geo nem tudja betölteni a leírást.</string> <string name="err_location_unknown">a c:geo nem ismeri a láda helyzetét.</string> @@ -174,18 +164,12 @@ <string name="err_tb_display">Sajnáljuk, a c:geo nem tudja megjeleníteni a nyomonkövethető tárgyat. Biztos, hogy ez egy nyomonkövethető tárgy?</string> <string name="err_tb_details_open">Sajnáljuk, a c:geo nem tudja megnyitni a nyomonkövethető tárgy részleteit.</string> - <string name="err_tb_details_download">Sajnáljuk, a c:geo nem tudta letölteni a nyomonkövethető tárgy részleteit, mert</string> - <string name="err_tb_forgot">Sajnáljuk, a c:geo elfelejtette melyik nyomonkövethető tárgyat szeretnéd.</string> <string name="err_tb_forgot_saw">Sajnáljuk, a c:geo elfelejtette melyik nyomonkövethető tárgyat láttad.</string> <string name="err_tb_find">Sajnáljuk, a c:geo nem találja a nyomonkövethető tárgyat.</string> <string name="err_tb_find_that">Sajnáljuk, a c:geo nem találja azt a követhető tárgyat.</string> <string name="err_waypoint_cache_unknown">Sajnáljuk, a c:geo nem tudja melyik ládához szeretnéd hozzáadni az útpontot.</string> - <string name="err_waypoint_unknown">Sajnáljuk, a c:geo elfelejtette melyik útpontot szeretnéd megjeleníteni.</string> <string name="err_waypoint_add_failed">Sajnáljuk, a c:geo nem tudta hozzáadni az útpontodat.</string> - <string name="err_waypoint_load_failed">Sajnáljuk, a c:geo nem tudta betölteni az útpontot.</string> - <string name="err_waypoint_delete_failed">Sajnáljuk, a c:geo nem tudja törölni az útpontot.</string> - <string name="err_waypoint_open_cache_failed">A c:geo nem tudja megnyitni a geoláda részleteit.</string> <string name="err_point_unknown_position">Sajnáljuk, a c:geo nem tudja felismerni hol vagy.</string> <string name="err_point_no_position_given_title">Információ szükséges</string> <string name="err_point_no_position_given">Írd be legalább a szélességi, hosszúsági, távolsági vagy irány értéket. Megadhatod mind a négyet is.</string> @@ -200,15 +184,12 @@ <string name="err_log_failed_server">Sajnáljuk, a c:geo-nak nem sikerült hozzáadni a logot mert a szerver nem válaszol.</string> <string name="err_log_post_failed">Úgy tűnik a logot nem került hozzáadásra. Kérlek ellenőrizd a geocaching.com-on.</string> - <string name="err_search_address_no_match">Sajnáljuk, a c:geo nem talált eggyező helyet.</string> <string name="err_search_address_forgot">Sajnáljuk, a c:geo elfelejtette a címet amit kerestél.</string> <string name="err_parse_lat">Sajnáljuk, a c:geo nem tudja értelmezni a szélességet.</string> <string name="err_parse_lon">Sajnáljuk, a c:geo nem tudja értelmezni a hosszúságot.</string> <string name="err_parse_dist">Sajnáljuk, a c:geo nem tudja értelmezni a távolságot.</string> <string name="err_parse_lat_lon">Sajnáljuk, a c:geo nem tudja értelmezni a szélességet vagy a hosszúságot.</string> - <string name="err_fieldnotes_export_failed">A terepjegyzetek exportálása sikertelen.</string> - <string name="warn_save_nothing">Nincs semmi amit menteni lehetne.</string> <string name="warn_no_cache_coord">Nincsenek a láda koordináták megadva.</string> <string name="warn_no_coordinates">Nincsenek koordináták.</string> @@ -233,7 +214,6 @@ <string name="info_log_cleared">A bejegyzés törölve.</string> <string name="info_log_type_changed">A bejegyzés típusa megváltoztatva!</string> - <string name="info_fieldnotes_exported_to">A terepfeljegyzések exportálva lettek ide:</string> <string name="info_storing_static_maps">Kísérlet a statikus térképek mentésére.</string> <!-- location service --> @@ -322,10 +302,7 @@ <string name="caches_filter_type">típu</string> <string name="caches_filter_track">nyomonkövethető tárgyak</string> <string name="caches_filter_clear">szűrők törlése</string> - <string name="caches_filter_size_title">Válassz méretet</string> - <string name="caches_filter_type_title">Válassz típust</string> <string name="caches_filter_modified">Módosított koordinátákkal</string> - <string name="caches_exporting_fieldnote">Exportálás terepjegyzetként…</string> <string name="caches_removing_from_history">Eltávolítás a Előzményekből…</string> <!-- caches lists --> @@ -404,7 +381,6 @@ <string name="init_offline_wp">Az útpontok statikus térképeinek mentése offline használathoz</string> <string name="init_save_log_img">Logokban található képek mentése</string> <string name="init_units">Mérföld/láb használata\n(angolszász mértékegységek)</string> - <string name="init_nav">Google Navigáció használata</string> <string name="init_log_offline">Offline logolás használata mindig (ne mutassa az online log ablakot logoláskor, ne küldje el a logot online)</string> <string name="init_livelist">Mutassa a ládák irányát a listában</string> <string name="init_altitude">Magasság korrekció</string> @@ -428,17 +404,11 @@ <string name="init_mapsources">Térkép források</string> <string name="init_mapsources_description">Itt választhatod ki a térképeid forrását. A Google térképek alternatívájaként több OpenStreetMap stílus is hozzáférhető és offline térkép fájlokat is használhatsz. (További információ <a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a>).</string> <string name="init_mapsource_select">Válassz térkép forrást</string> - <string name="init_select_themefolder">…</string> <string name="init_map_directory_description">Könyvtár az offline térképekhez</string> - <string name="init_select_map_directory">…</string> - <string name="init_select_gpx_exportdir">…</string> - <string name="init_select_gpx_importdir">…</string> <string name="init_gpx_exportdir">GPX exportálási könyvtár</string> <string name="init_gpx_importdir">GPX importálási könyvtár</string> <string name="init_gpx_exportdir_description">Itt választhatod ki a könyvtárat a GPX exportálásokhoz.</string> <string name="init_gpx_importdir_description">Itt választhatod ki a könyvtárat a GPX importálásokhoz.</string> - <string name="init_gpx_exportdir_select">A GPX exportálási könyvtár kiválasztása</string> - <string name="init_gpx_importdir_select">A GPX importálási könyvtár kiválasztása</string> <string name="init_maptrail">A nyomvonal mutatása a térképen</string> <string name="init_share_after_export">A megosztás menü megnyitása a GPX exportálás után</string> <string name="init_trackautovisit">A nyomonkövethető tárgyak automatikus \"látogatott\" logolása</string> @@ -454,7 +424,6 @@ <string name="init_dbonsdcard_title">Adatbázis helye</string> <string name="init_dbonsdcard_note">Elmentheted az adatbázist a külső eszközön is. Ezzel belső memóriát takaríthatsz meg, de a teljesítmény csökkenhet és a c:geo nem fog tudni működni ha az SD kártya nem hozzáférhető.</string> <string name="init_dbonsdcard">Az adatbázis a külső eszközön</string> - <string name="init_dbmove">Adatbázis mozgatása</string> <string name="init_dbmove_dbmove">Adatbázis mozgatása</string> <string name="init_dbmove_running">Adatbázis mozgatása</string> <string name="init_dbmove_success">Az adatbázis mozgatása sikeresen lezajlott</string> @@ -514,7 +483,6 @@ <string name="cache_offline_time_days">nappal ezelőtt</string> <string name="cache_premium">Prémium</string> <string name="cache_attributes">Tulajdonságok</string> - <string name="cache_attributes_no_icons">(frissítsd a ládát, hogy lásd a tulajdonság ikonokat)</string> <string name="cache_inventory">Tárgyak</string> <string name="cache_log_offline">Offline bejegyzés</string> <string name="cache_log_images_loading">Bejegyzés kép betöltése…</string> @@ -525,7 +493,6 @@ <string name="cache_description">Leírás</string> <string name="cache_description_long">Hosszú leírás</string> <string name="cache_description_table_note">A leírás táblázatot is tartalmaz aminek helyes megjelenítéséhez szükség lehet a geocaching.com meglátogatására.</string> - <string name="cache_watchlist">Figyelőlista</string> <string name="cache_watchlist_on">Ez a láda a figyelőlistádon van.</string> <string name="cache_watchlist_not_on">Ez a láda nincs a figyelőlistádon.</string> <string name="cache_watchlist_add">Figyelőlistához adás</string> @@ -566,7 +533,6 @@ <string name="cache_dialog_watchlist_remove_title">Figyelőlista</string> <string name="cache_dialog_watchlist_remove_message">Láda eltávolítása a figyelőlistádról…</string> <string name="cache_menu_navigate">Navigáció</string> - <string name="cache_menu_tbt">Lépésről lépésre</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Térkép</string> <string name="cache_menu_map_static">Statikus térképek</string> @@ -618,7 +584,6 @@ <string name="cache_images_loading">Képek betéltése…</string> <string name="cache_log_types">Bejegyzés típusok</string> <string name="cache_coordinates_no">Ennek a ládának nincsenek koordinátái.</string> - <string name="cache_export_fieldnote">Exportálás terepjegyzetként</string> <string name="cache_clear_history">Előzmények törlése</string> <string name="cache_remove_from_history">Eltávolítás az előzményekből</string> <string name="cache_license">Licensz</string> @@ -646,7 +611,6 @@ <string name="gpx_import_loading_caches">Geoládák betöltése .gpx fájlból</string> <string name="gpx_import_loading_waypoints">Útpontfájl betöltése</string> <string name="gpx_import_store_static_maps">Statikus térképek mentése</string> - <string name="gpx_import_storing">Geoládák adatbázisba írása</string> <string name="gpx_import_caches_imported">ládák importálva</string> <string name="gpx_import_static_maps_skipped">A statikus térképek letöltése megszakítva.</string> <string name="gpx_import_title_static_maps">Statikus térképek mentése</string> @@ -665,11 +629,7 @@ <!-- map file select --> <string name="map_file_select_title">Térkép fájl kiválasztása</string> - <!-- theme file select --> - <string name="theme_file_select_title">Válaszd ki az egyéni térképtéma fájlját</string> - <!-- import --> - <string name="import_title">Importálás…</string> <string name="web_import_title">Importálás webről</string> <string name="web_import_waiting">Várakozás új ládákra webről…</string> <string name="web_downloading">Letöltés</string> @@ -680,7 +640,6 @@ <!-- waypoint --> <string name="waypoint">Útpont</string> - <string name="waypoint_title">Útpont neve</string> <string name="waypoint_cache_coordinates">Geoláda koordinátái</string> <string name="waypoint_custom">Egyedi</string> <string name="waypoint_my_coordinates">Az én koordinátáim</string> @@ -694,11 +653,9 @@ <string name="waypoint_note">Jegyzet</string> <string name="waypoint_save">Mentés</string> <string name="waypoint_loading">Útpont betöltése…</string> - <string name="waypoint_unknown_coordinates">Ismeretlen koordináták</string> <string name="waypoint_done">Kész</string> <string name="waypoint_duplicate">Duplikálás</string> <string name="waypoint_copy_of">Ennek másolata</string> - <string name="waypoint_menu_open_cache">Geoláda megnyitása</string> <string name="search_history">Előzmény</string> <string name="search_history_empty">Nincsenek előző célpontok</string> <string name="search_remove_destination">Célpont eltávolítva</string> @@ -837,7 +794,6 @@ <!-- export --> <string name="export">Exportálás</string> - <string name="export_as">Exportálás mint…</string> <string name="export_exportedto">exportálva ide</string> <string name="export_failed">Exportálás sikertelen</string> <string name="export_fieldnotes">Helyszíni jegyzetek</string> @@ -1008,11 +964,11 @@ <string name="about_auth_2">Kattints a \"c:geo engedélyezése\" gombra, hogy elindítsd a folyamatot. Ez a folyamat meg fog nyitni egy böngészőt a Twitter weboldallal. Lépj be ezen az oldalon és hagyd jóvá, hogy a <b>c:geo</b> hozzáférjen a felhasználói fiókodhoz. Ha elfogadod, a Twitter mutatni fog egy számokból álló PIN kódot. Ezt a PIN kódot kell a <b>c:geo</b>-ban beillesztened és jóváhagynod. Ilyen egyszerű.</string> <!-- status --> - <string name="status_new_release">Új kiadás található.\nKattints a telepítéshez.</string> - <string name="status_new_nightly">Új napi verzió található.\nKattints a telepítéshez.</string> - <string name="status_new_rc">Új kiadásra jelölt verzió található.\nKattints a telepítéshez.</string> - <string name="status_geocaching_change">A c:geo a geocaching.com-on nemrégen történt változások miatt nem működik.\nDolgozunk a megoldáson. Nézz vissza hamarosan.</string> - <string name="status_geocaching_livemap">Az élő térkép a geocaching.com-on nemrégen történt változások miatt nem működik.\nDolgozunk a megoldáson. Nézz vissza hamarosan.</string> + <string name="status_new_release" tools:ignore="UnusedResources">Új kiadás található.\nKattints a telepítéshez.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">Új napi verzió található.\nKattints a telepítéshez.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">Új kiadásra jelölt verzió található.\nKattints a telepítéshez.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">A c:geo a geocaching.com-on nemrégen történt változások miatt nem működik.\nDolgozunk a megoldáson. Nézz vissza hamarosan.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Az élő térkép a geocaching.com-on nemrégen történt változások miatt nem működik.\nDolgozunk a megoldáson. Nézz vissza hamarosan.</string> <string name="clipboard_copy_ok">Kimásolva a vágólapra</string> <plurals name="days_ago"> diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index 016d3f6..4d6ce59 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo bussola</string> @@ -53,6 +53,7 @@ <string name="wp_pkg">Area parcheggio</string> <string name="wp_trailhead">Partenza percorso</string> <string name="wp_waypoint">Punto di riferimento</string> + <string name="wp_original">Coordinate originali</string> <!-- logs --> <string name="log_found">Trovato</string> @@ -72,9 +73,12 @@ <string name="log_maintenance_needed">Richiede manutenzione</string> <string name="log_update">Coordinate aggiornate</string> <string name="log_archived">Archiviato</string> + <string name="log_unarchived">Reinserito</string> <string name="log_needs_archived">Necessita archiviazione</string> <string name="log_discovered">Scoperto</string> <string name="log_reviewer">Nota del reviewer</string> + <string name="log_retractlisting">Ritirato</string> + <string name="log_marked_missing">Segnalato come mancante</string> <string name="log_tb_nothing">Non fare nulla</string> <string name="log_tb_visit">Visitato</string> <string name="log_tb_drop">Lasciato</string> @@ -87,9 +91,6 @@ <string name="log_post_no_rate">Invia log senza voto</string> <string name="log_post_not_possible">Connessione…</string> <string name="log_add">Aggiungi</string> - <string name="log_date">Data</string> - <string name="log_time">Ota</string> - <string name="log_date_time">Data e ora</string> <string name="log_rating">Voto</string> <string name="log_no_rating">Nessun voto</string> <string name="log_stars_1">1 stella</string> @@ -139,8 +140,6 @@ <string name="err_license">L\'utente non ha approvato le condizione del Geocaching.com license agreement, così c:geo non può caricare le coordinate dei cache.</string> <string name="err_unpublished">Il cache richiesto è stato ritirato</string> <string name="err_premium_only">Cache disponibile solo per utenti premium di Geocaching.com</string> - <string name="err_store">c:geo non può salvare il cache.</string> - <string name="err_drop">c:geo non può eliminare il cache.</string> <string name="err_detail_open">c:geo non può aprire i dettagli del cache.</string> <string name="err_detail_cache">c:geo non può visualizzare il cache richiesto. È veramente un geocache?</string> <string name="err_detail_cache_find">c:geo non trova il geocache</string> @@ -153,39 +152,30 @@ <string name="err_detail_no_spoiler">c:geo non trova alcuna immagine spoiler per questo cache.</string> <string name="err_detail_no_map_static">c:geo non trova alcuna mappa statica per questo cache.</string> <string name="err_detail_not_load_map_static">c:geo non riesce a caricare la mappe statiche.</string> - <string name="err_detail_ask_store_map_static">c:geo non riesce a caricare la mappa statica. La salvo ora?</string> <string name="err_detail_still_working">Momentaneamente occupato a svolgere un altro compito.</string> <string name="err_watchlist_still_managing">Sto ancora gestendo la tua watchlist.</string> <string name="err_watchlist_failed">La modifica alla tua watchlist è fallita.</string> - <string name="err_navigation_no">c:geo non trova nessun navigatore supportato.</string> <string name="err_application_no">c:geo non trova nessuna applicazione compatibile.</string> <string name="err_auth_initialize">c:geo ha fallito l\'inizializzazione del processo di autorizzazione.</string> <string name="err_auth_process">Processo di autorizzazione fallito.</string> <string name="err_cannot_log_visit">c:geo non ha abbastanza informazioni per salvare il log. Per cortesia effettuarlo dalla pagina dei dettagli completi del cache.</string> <string name="err_init_cleared">c:geo non può cancellare le informazioni di login.</string> <string name="err_download_fail">c:geo ha fallito il download dei cache perché </string> - <string name="err_list_load_fail">c:geo ha fallito il caricamento della lista cache.</string> - <string name="err_store_failed">c:geo non può salvare i geocache.</string> - <string name="err_refresh_failed">c:geo non può aggiornare i geocache.</string> <string name="err_dwld_details_failed">c:geo ha fallito il download dei dettagli del cache.</string> <string name="err_load_descr_failed">c:geo non può caricare la descrizione.</string> <string name="err_location_unknown">c:geo non conosce la posizione dei cache.</string> <string name="err_missing_device_name">Per cortesia inserire il nome del dispositivo prima di registrarsi.</string> + + <string name="err_favorite_failed">Errore nella modifica dello stato preferiti.</string> <string name="err_tb_display">c:geo non riesce a visualizzare il trackable che vuoi. È veramente un trackable?</string> <string name="err_tb_details_open">c:geo non riesce ad aprire i dettagli del trackable.</string> - <string name="err_tb_details_download">c:geo ha fallito il download dei dettagli del trackable perché </string> - <string name="err_tb_forgot">c:geo ha dimenticato quale trackable volevi.</string> <string name="err_tb_forgot_saw">c:geo ha dimenticato quale trackable vedevi.</string> <string name="err_tb_find">c:geo non trova nessun trackable</string> <string name="err_tb_find_that">c:geo non trova quel trackable.</string> <string name="err_waypoint_cache_unknown">c:geo non conosce a quale cache vuoi aggiungere un waypoint.</string> - <string name="err_waypoint_unknown">c:geo ha dimenticato quale waypoint vuoi visualizzare.</string> <string name="err_waypoint_add_failed">c:geo non è riuscito ad aggiungere il tuo waypoint.</string> - <string name="err_waypoint_load_failed">c:geo non è riuscito a caricare il waypoint.</string> - <string name="err_waypoint_delete_failed">c:geo non riesce a cancellare il waypoint.</string> - <string name="err_waypoint_open_cache_failed">c:geo non riesce ad aprire i dettagli del cache.</string> <string name="err_point_unknown_position">c:geo non capisce dove ti trovi.</string> <string name="err_point_no_position_given_title">Info richieste</string> <string name="err_point_no_position_given">Inserisci almeno latitudine, o longitudine, o distanza e angolo. Puoi anche inserire tutti e quattro i valori.</string> @@ -200,15 +190,12 @@ <string name="err_log_failed_server">c:geo non è riuscito ad inviare il log perché il server non risponde.</string> <string name="err_log_post_failed">Sembra che il log non sia stato inviato. Prego verificare su Geocaching.com.</string> - <string name="err_search_address_no_match">c:geo non ha trovato luoghi corrispondenti.</string> <string name="err_search_address_forgot">c:geo ha dimenticato l\'indirizzo che vuoi trovare.</string> <string name="err_parse_lat">c:geo non riesce ad interpretare la latitudine.</string> <string name="err_parse_lon">c:geo non riesce ad interpretare la longitudine.</string> <string name="err_parse_dist">c:geo non riesce ad interpretare la distanza.</string> <string name="err_parse_lat_lon">c:geo non riesce ad interpretare la latitudine o la longitudine.</string> - <string name="err_fieldnotes_export_failed">Esportazione delle note fallita.</string> - <string name="warn_save_nothing">Non c\'è nulla da salvare.</string> <string name="warn_no_cache_coord">Non ci sono cache con coordinate.</string> <string name="warn_no_coordinates">Coordinate non fornite.</string> @@ -225,13 +212,13 @@ <string name="warn_invalid_mapfile">La mappa selezionata non è mapsforge versione 0.3.0.\nMappa offline non disponibile.</string> <string name="warn_deprecated_mapfile">Stai usando una vecchia mappa 0.2.4.\nAggiornala alla 0.3.0 appena puoi.\nIl supporto alla 0.2.4 sarà rimosso nella prossima versione.</string> <string name="warn_nonexistant_mapfile">La mappa selezionata non esiste.\nMappa offline non disponibile.</string> + <string name="warn_rendertheme_missing">Tema mappa non trovato.</string> <string name="info_log_posted">c:geo ha inviato il log con successo.</string> <string name="info_log_saved">c:geo ha salvato il log.</string> <string name="info_log_cleared">Il log è stato azzerato.</string> <string name="info_log_type_changed">Il tipo di log è cambiato!</string> - <string name="info_fieldnotes_exported_to">Note esportate verso </string> <string name="info_storing_static_maps">Tento di salvare la static map</string> <!-- location service --> @@ -303,6 +290,7 @@ <string name="caches_drop_stored">Elimina i cache salvati</string> <string name="caches_drop_progress">Eliminando caches</string> <string name="caches_drop_all_and_list">Elimina tutti ed elimina la lista</string> + <string name="caches_delete_events">Cancella eventi passati</string> <string name="caches_refresh_selected">Aggiorna i cache selezionati</string> <string name="caches_refresh_all">Aggiorna tutti</string> <string name="caches_move_selected">Muovi i cache selezionati</string> @@ -319,10 +307,7 @@ <string name="caches_filter_type">Tipo</string> <string name="caches_filter_track">Con oggetti trackables</string> <string name="caches_filter_clear">Rimuovi filtri</string> - <string name="caches_filter_size_title">Scegli dimensione</string> - <string name="caches_filter_type_title">Scegli tipo</string> <string name="caches_filter_modified">Con coordinate modificate</string> - <string name="caches_exporting_fieldnote">Esportazione Field Notes…</string> <string name="caches_removing_from_history">Rimozione dalla cronologia…</string> <!-- caches lists --> @@ -356,6 +341,10 @@ <!-- init --> <string name="init_geocaching">Geocaching.com</string> + <string name="init_oc">opencaching.de</string> + <string name="init_oc_activate">Attiva opencaching.de su mappa live e nelle ricerche</string> + <string name="init_oc_username_description">Inserisci il tuo utente opencaching.de per marcare i tuoi ritrovamenti.</string> + <string name="init_oc_username">Inserisci nome utente</string> <string name="init_gcvote">GCvote.com</string> <string name="init_twitter">Twitter</string> <string name="init_username">Utente</string> @@ -398,7 +387,6 @@ <string name="init_offline_wp">Salva i waypoints delle mappe per uso offline</string> <string name="init_save_log_img">Salva immagini contenute nei log</string> <string name="init_units">Usa miglia/piedi</string> - <string name="init_nav">Usa Google Navigation</string> <string name="init_log_offline">Quando salvi log, fallo sempre offline (non visualizzerà lo schermo di log online, non invierà subito il log)</string> <string name="init_livelist">Visualizza in che direzione sono i cache, nelle liste</string> <string name="init_altitude">Correzione di altitudine</string> @@ -420,16 +408,13 @@ <string name="init_backup_last">Disponibile Backup delle</string> <string name="init_backup_last_no">Non esiste il file con il backup.</string> <string name="init_mapsources">Tipi di mappe</string> - <string name="init_mapsources_description">Qui puoi scegliere dove c:geo preleverà le mappe. Come alternativa a Google maps esistono vari stili di OpenStreetMap disponibili anche per uso offline (vedi <a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a> per dettagli).</string> + <string name="init_mapsources_description">Qui puoi scegliere dove c:geo preleverà le mappe. Come alternativa a Google maps esistono vari stili di OpenStreetMap disponibili anche per uso offline (vedi <a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a> per dettagli).\nIn aggiunta, temi personalizzati sono disponibili per le mappe offline</string> <string name="init_mapsource_select">Seleziona il tipo di mappa</string> - <string name="init_select_gpx_exportdir">…</string> - <string name="init_select_gpx_importdir">…</string> + <string name="init_map_directory_description">Cartella con le mappe offline</string> <string name="init_gpx_exportdir">Cartella di export GPX</string> <string name="init_gpx_importdir">Cartella di import GPX</string> <string name="init_gpx_exportdir_description">Qui puoi selezionare la cartella di esportazione GPX.</string> <string name="init_gpx_importdir_description">Qui puoi selezionare la cartella di importazione GPX.</string> - <string name="init_gpx_exportdir_select">Scegli la cartella di esportazione GPX</string> - <string name="init_gpx_importdir_select">Scegli la cartella di esportazione GPX</string> <string name="init_maptrail">Mostra la scia nella Mappa</string> <string name="init_share_after_export">Apri menu condividi dopo export GPX</string> <string name="init_trackautovisit">Setta i miei oggetti Trackables automaticamente su \"visit\" quando invio log</string> @@ -446,12 +431,13 @@ <string name="init_dbonsdcard_title">Posizione Database</string> <string name="init_dbonsdcard_note">Puoi decidere di salvare il database su memoria esterna. In questo caso risparmierai memoria interna ma potresti perdere un pochino di velocità e c:geo non funzionerà se la tua sdcard non sarà disponibile.</string> <string name="init_dbonsdcard">Database su memoria esterna</string> - <string name="init_dbmove">Spostamento Database</string> <string name="init_dbmove_dbmove">Spostamento Database</string> <string name="init_dbmove_running">Spostamento Database</string> <string name="init_dbmove_success">Database spostato con successo.</string> <string name="init_dbmove_failed">Spostamento fallito</string> <string name="init_plain_logs">Visualizza i LOG senza colori</string> + <string name="init_use_native_ua">Identifica come browser Android. Risolve alcuni problemi di login con alcuni provider di rete.</string> + <string name="init_rendertheme_folder">Cartella per i temi mappa personali off-line</string> <string name="init_sendToCgeo">Send to c:geo</string> <string name="init_sendToCgeo_name">Nome dispositivo:</string> @@ -497,7 +483,6 @@ <string name="cache_offline_time_days">giorni fa</string> <string name="cache_premium">Premium</string> <string name="cache_attributes">Attributi</string> - <string name="cache_attributes_no_icons">(aggiorna il cache per visualizzare le icone degli attributi)</string> <string name="cache_inventory">Oggetti</string> <string name="cache_log_offline">Log Offline</string> <string name="cache_log_images_loading">Caricamento immagini log…</string> @@ -507,7 +492,6 @@ <string name="cache_description">Descrizione</string> <string name="cache_description_long">Descrizione estesa</string> <string name="cache_description_table_note">La descrizione contiene una tabella formattata in modo tale che potresti aver bisogno di andare su geocaching.com per vederla correttamente.</string> - <string name="cache_watchlist">Watchlist</string> <string name="cache_watchlist_on">Questo cache è nella tua watchlist.</string> <string name="cache_watchlist_not_on">Questo cache non è nella tua watchlist.</string> <string name="cache_watchlist_add">Aggiungi alla watchlist</string> @@ -516,6 +500,8 @@ <string name="cache_favpoint_not_on">Questo cache non è uno dei tuoi favoriti.</string> <string name="cache_favpoint_add">Aggiungi</string> <string name="cache_favpoint_remove">Rimuovi</string> + <string name="cache_images">Immagini</string> + <string name="cache_waypoints">Waypoints</string> <plurals name="waypoints"> <item quantity="one">1 Waypoint</item> @@ -545,8 +531,14 @@ <string name="cache_dialog_watchlist_add_message">Aggiunto il cache alla watchlist in corso…</string> <string name="cache_dialog_watchlist_remove_title">Watchlist</string> <string name="cache_dialog_watchlist_remove_message">Rimozione dei cache dalla tua watchlist…</string> + <string name="cache_dialog_favourite_add_title">Preferiti</string> + <string name="cache_dialog_favourite_add_message">Aggiungi il cache ai tuoi preferiti…</string> + <string name="cache_dialog_favourite_remove_title">Preferiti</string> + <string name="cache_dialog_favourite_remove_message">Rimozione cache dai tuoi preferiti…</string> <string name="cache_menu_navigate">Naviga</string> - <string name="cache_menu_tbt">Itinerario guidato</string> + <string name="cache_menu_navigation_drive">Naviga (in auto)</string> + <string name="cache_menu_navigation_walk">Naviga (a piedi)</string> + <string name="cache_menu_maps_directions">Direzioni su Google Maps</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Mappa</string> <string name="cache_menu_map_static">Mappe statiche</string> @@ -559,6 +551,8 @@ <string name="cache_menu_visit_offline">Scrivi Log offline</string> <string name="cache_menu_spoilers">Immagini spoiler</string> <string name="cache_menu_around">Cache qui intorno</string> + <string name="cache_menu_set_as_cache_coords">Setta come coordinate cache</string> + <string name="cache_menu_upload_wpt_to_gc_com">Setta come coordinate cache e carica il waypoint su Geocaching.com</string> <string name="cache_menu_event">Aggiungi al calendario</string> <string name="cache_menu_details">Dettagli</string> <string name="cache_menu_share">Condividi cache</string> @@ -573,6 +567,7 @@ <string name="cache_status_archived">Archiviato</string> <string name="cache_status_disabled">Non attivo</string> <string name="cache_status_premium">Solo per utenti Premium</string> + <string name="cache_status_not_premium">Per tutti gli utenti</string> <string name="cache_geocode">GC-code</string> <string name="cache_name">Nome</string> <string name="cache_type">Tipo</string> @@ -592,9 +587,10 @@ <string name="cache_coordinates_original">Coordinate originali</string> <string name="cache_spoiler_images_title">Immagini spoiler</string> <string name="cache_spoiler_images_loading">Caricamento immagini spoiler…</string> + <string name="cache_images_title">Immaginis</string> + <string name="cache_images_loading">Caricamento immagini…</string> <string name="cache_log_types">Tipi di Log</string> <string name="cache_coordinates_no">Questo cache non ha coordinate.</string> - <string name="cache_export_fieldnote">Esporta le note (Field Notes)</string> <string name="cache_clear_history">Cancella cronologia</string> <string name="cache_remove_from_history">Rimuovi dalla cronologia</string> <string name="cache_license">Licenza</string> @@ -604,6 +600,9 @@ <string name="cache_share_field">Condividi</string> <string name="cache_time_full_hours">Precise</string> + <!-- editor dialog --> + <string name="editor_save">Salva</string> + <!-- file list base --> <string name="file_searching_in">Ricerca file\nin</string> <string name="file_searching_sdcard_in">Nessun file trovato nella cartella di default:\n%1$s\n\nRicerca in tutta la SD i files:\n</string> @@ -619,7 +618,6 @@ <string name="gpx_import_loading_caches">Caricamento dei cache da file GPX</string> <string name="gpx_import_loading_waypoints">Caricamento file waypoints</string> <string name="gpx_import_store_static_maps">Salvataggio mappe statiche</string> - <string name="gpx_import_storing">Salvataggio dei cache nel database</string> <string name="gpx_import_caches_imported">cache importati</string> <string name="gpx_import_static_maps_skipped">Download mappe statiche interrotto</string> <string name="gpx_import_title_static_maps">Salva mappe statiche</string> @@ -639,7 +637,6 @@ <string name="map_file_select_title">Seleziona il file mappa</string> <!-- import --> - <string name="import_title">Importa…</string> <string name="web_import_title">Importa dal web</string> <string name="web_import_waiting">In attesa di nuovi cache dal web…</string> <string name="web_downloading">Download in corso</string> @@ -650,7 +647,6 @@ <!-- waypoint --> <string name="waypoint">Waypoint</string> - <string name="waypoint_title">Waypoint</string> <string name="waypoint_cache_coordinates">Coordinate cache</string> <string name="waypoint_custom">Custom</string> <string name="waypoint_my_coordinates">Coordinate attuali</string> @@ -664,11 +660,25 @@ <string name="waypoint_note">Note</string> <string name="waypoint_save">Salva</string> <string name="waypoint_loading">Caricamento waypoint…</string> - <string name="waypoint_unknown_coordinates">Coordinate sconosciute</string> + <string name="waypoint_do_not_touch_cache_coordinates">Nessuna modifica alle coordinate cache</string> + <string name="waypoint_set_as_cache_coords">Setta come coordinate cache</string> + <string name="waypoint_coordinates_has_been_reset_on_website">Le coordinates sono state resettate su web</string> + <string name="waypoint_save_and_modify_on_website">Setta come coordinate cache in c:geo e su web</string> + <string name="waypoint_reset_cache_coords">Resetta le coordinate cache</string> + <string name="waypoint_coordinates_being_reset_on_website">Le coordinate sono in fase di reset su web</string> + <string name="waypoint_reset_cache_coords_info">Opzioni di reset</string> + <string name="waypoint_reset">Reset</string> + <string name="waypoint_localy_reset_cache_coords">Resetta in c:geo</string> + <string name="waypoint_reset_local_and_remote_cache_coords">Resetta in c:geo e su web.</string> + <string name="waypoint_coordinates_couldnt_be_modified_on_website">Il sito web non supporta la modifica delle coordinate</string> + <string name="waypoint_coordinates_upload_error">Errore durante il caricamento delle coordinate su web</string> + <string name="waypoint_coordinates_uploading_to_website">Caricamento delle coordinate %s su web</string> + <string name="waypoint_coordinates_reseting_on_website">Reset alle coordinate originali su web</string> + <string name="waypoint_coordinates_has_been_modified_on_website">Le coordinate cache su web sono state modificate in: %s.</string> + <string name="waypoint_coordinates_has_been_set_as_cache_coordinates">Le coordinate cache sono state modificate in c:geo in: %s.</string> <string name="waypoint_done">Fatto</string> <string name="waypoint_duplicate">Duplicato</string> <string name="waypoint_copy_of">Copia di</string> - <string name="waypoint_menu_open_cache">Apri Cache</string> <string name="search_history">Cronologia</string> <string name="search_history_empty">Nessuna precedente destinazione</string> <string name="search_remove_destination">Destinazione rimossa</string> @@ -691,10 +701,13 @@ <string name="map_map">Mappa</string> <string name="map_live">Mappa Live</string> <string name="map_view_map">Scegli mappa</string> + <string name="map_modes">Modi mappa</string> <string name="map_trail_show">Mostra scia</string> <string name="map_trail_hide">Nasconde scia</string> <string name="map_circles_show">Mostra area cache</string> <string name="map_circles_hide">Nascondi area cache</string> + <string name="map_theme_builtin">Tema predefinito</string> + <string name="map_theme_select">Scegli un tema mappa</string> <string name="map_live_enable">Attiva online</string> <string name="map_live_disable">Disattiva online</string> <string name="map_static_title">Mappe statiche</string> @@ -740,7 +753,7 @@ <!-- trackable --> <string name="trackable">Oggetto trackable</string> - <string name="trackable_details_loading">Caricamente dettagli trackable…</string> + <string name="trackable_details_loading">Caricamento dettagli trackable…</string> <string name="trackable_log_touch">Documenta il contatto</string> <string name="trackable_browser_open">Apri nel Browser</string> <string name="trackable_goal">Obbiettivo</string> @@ -803,7 +816,6 @@ <!-- export --> <string name="export">Esporta</string> - <string name="export_as">Esporta come…</string> <string name="export_exportedto">esportato in</string> <string name="export_failed">Esportazione fallita</string> <string name="export_fieldnotes">Field Note</string> @@ -974,11 +986,11 @@ <string name="about_auth_2">Clicca sul pulsante \"Autorizza c:geo\" per iniziare. Questa procedura aprirà il browser sulla pagina Twitter. Fai Login su questa pagina e autorizza <b>c:geo</b> ad accedere al tuo account. Se accettato, Twitter mostrerà un PIN code numerico. Questo PIN deve essere riportato in <b>c:geo</b> e confermato.</string> <!-- status --> - <string name="status_new_release">Una nuova versione è disponibile.\nClicca per installarla.</string> - <string name="status_new_nightly">Una nuova versione nightly è disponibile.\nClicca per installarla.</string> - <string name="status_new_rc">Una nuova release candidate è disponibile.\nClicca per installarla.</string> - <string name="status_geocaching_change">Modifiche recenti al sito geocaching hanno disattivato c:geo.\nCi stiamo lavorando, riprova più tardi.</string> - <string name="status_geocaching_livemap">Modifiche recenti al sito geocaching hanno disattivato la mappa live.\nCi stiamo lavorando, riprova più tardi.</string> + <string name="status_new_release" tools:ignore="UnusedResources">Una nuova versione è disponibile.\nClicca per installarla.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">Una nuova versione nightly è disponibile.\nClicca per installarla.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">Una nuova release candidate è disponibile.\nClicca per installarla.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">Modifiche recenti al sito geocaching hanno disattivato c:geo.\nCi stiamo lavorando, riprova più tardi.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Modifiche recenti al sito geocaching hanno disattivato la mappa live.\nCi stiamo lavorando, riprova più tardi.</string> <string name="clipboard_copy_ok">Copiato nella clipboard</string> <plurals name="days_ago"> diff --git a/main/res/values-ja/strings.xml b/main/res/values-ja/strings.xml index a8e5ef6..00b7c61 100644 --- a/main/res/values-ja/strings.xml +++ b/main/res/values-ja/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo コンパス</string> @@ -87,9 +87,6 @@ <string name="log_post_no_rate">ログの投稿(未評価)</string> <string name="log_post_not_possible">ログのページをロード中…</string> <string name="log_add">挿入</string> - <string name="log_date">日付</string> - <string name="log_time">時間</string> - <string name="log_date_time">日付と時間</string> <string name="log_rating">評価</string> <string name="log_no_rating">未評価</string> <string name="log_stars_1">星1つ</string> @@ -138,8 +135,6 @@ <string name="err_license">Geocaching.comのライセンス契約に同意しなかったのでキャッシュの座標を見ることはできません。</string> <string name="err_unpublished">The requested cache is unpublished.</string> <string name="err_premium_only">このキャッシュはプレミアム会員のみ有効です。</string> - <string name="err_store">キャッシュ情報を保存することができません。</string> - <string name="err_drop">キャッシュ情報を破棄することができません。</string> <string name="err_detail_open">キャッシュの詳細を開くことができません。</string> <string name="err_detail_cache">キャッシュ情報を表示することができません。これは本当にジオキャッシュですか?</string> <string name="err_detail_cache_find">キャッシュ情報が見つかりません。</string> @@ -152,20 +147,15 @@ <string name="err_detail_no_spoiler">このキャッシュのスポイラー画像を見つけることができませんでした。</string> <string name="err_detail_no_map_static">このキャッシュのオフライン地図を見つけることができませんでした。</string> <string name="err_detail_not_load_map_static">オフライン地図のロードに失敗しました。</string> - <string name="err_detail_ask_store_map_static">オフライン地図のロードに失敗しました。再度保存しますか?</string> <string name="err_detail_still_working">他のタスクがまだ動作中です。</string> <string name="err_watchlist_still_managing">Still managing your watchlist.</string> <string name="err_watchlist_failed">ウォッチリストの変更に失敗しました。</string> - <string name="err_navigation_no">使用できるナビゲーションが見つかりません。</string> <string name="err_application_no">適切なアプリケーションが見つかりません。</string> <string name="err_auth_initialize">認証プロセスの初期化に失敗しました。</string> <string name="err_auth_process">認証プロセスに失敗しました。</string> <string name="err_cannot_log_visit">ログを保存するのに十分な情報がありません。キャッシュの詳細を全て入力してください。</string> <string name="err_init_cleared">ログイン情報を消去することができません。</string> <string name="err_download_fail">キャッシュ情報のダウンロードに失敗しました。</string> - <string name="err_list_load_fail">キャッシュリストのロードに失敗しました。</string> - <string name="err_store_failed">キャッシュ情報を保存することができません。</string> - <string name="err_refresh_failed">キャッシュ情報を更新することができません。</string> <string name="err_dwld_details_failed">キャッシュ情報の詳細をダウンロードすることができません。</string> <string name="err_load_descr_failed">キャッシュの説明をロードすることができません。</string> <string name="err_location_unknown">キャッシュの場所が分かりません。</string> @@ -173,18 +163,12 @@ <string name="err_tb_display">トラッカブルアイテムを表示することができません。本当にトラッカブルアイテムですか?</string> <string name="err_tb_details_open">トラッカブルアイテムの詳細を開くことができません。</string> - <string name="err_tb_details_download">トラッカブルアイテムの詳細をダウンロードすることができません。</string> - <string name="err_tb_forgot">c:geo forgot which trackable you want.</string> <string name="err_tb_forgot_saw">c:geo forgot which trackable you saw.</string> <string name="err_tb_find">トラッカブルアイテムが見つかりません。</string> <string name="err_tb_find_that">トラッカブルアイテムが見つかりません。</string> <string name="err_waypoint_cache_unknown">c:geo doesn\'t know to which cache you want to add waypoint.</string> - <string name="err_waypoint_unknown">c:geo forgot what waypoint you want to display.</string> <string name="err_waypoint_add_failed">ウェイポイントを追加することができませんでした。</string> - <string name="err_waypoint_load_failed">ウェイポイントをロードすることができませんでした。</string> - <string name="err_waypoint_delete_failed">ウェイポイントを削除することができません。</string> - <string name="err_waypoint_open_cache_failed">キャッシュの詳細を開くことができません。</string> <string name="err_point_unknown_position">現在地を認識できません。</string> <string name="err_point_no_position_given_title">必要な情報</string> <string name="err_point_no_position_given">少なくとも経度、緯度、または距離と方位を入力してください。全てを入力することもできます。</string> @@ -199,15 +183,12 @@ <string name="err_log_failed_server">サーバの反応がないのでログを投稿することができませんでした。</string> <string name="err_log_post_failed">ログを投稿することができなかったようです。geocaching.comで確認してください。</string> - <string name="err_search_address_no_match">該当する場所が見つかりません。</string> <string name="err_search_address_forgot">c:geo forgot the address you tried to find.</string> <string name="err_parse_lat">緯度の解析ができません。</string> <string name="err_parse_lon">経度の解析ができません。</string> <string name="err_parse_dist">距離の解析ができません。</string> <string name="err_parse_lat_lon">緯度または経度の解析ができません。</string> - <string name="err_fieldnotes_export_failed">フィールドノートのエクスポートに失敗しました。</string> - <string name="warn_save_nothing">保存すべきものがありません。</string> <string name="warn_no_cache_coord">座標のあるキャッシュがありません。</string> <string name="warn_no_coordinates">座標が入力されていません。</string> @@ -231,7 +212,6 @@ <string name="info_log_cleared">ログを消去しました。</string> <string name="info_log_type_changed">ログのタイプを変更しました。</string> - <string name="info_fieldnotes_exported_to">フィールドノートとしてエクスポートしました</string> <string name="info_storing_static_maps">オフライン用に地図を保存中</string> <!-- location service --> @@ -320,10 +300,7 @@ <string name="caches_filter_type">タイプ</string> <string name="caches_filter_track">トラッカブルアイテムあり</string> <string name="caches_filter_clear">フィルターをクリア</string> - <string name="caches_filter_size_title">サイズを選択</string> - <string name="caches_filter_type_title">タイプを選択</string> <string name="caches_filter_modified">座標の更新あり</string> - <string name="caches_exporting_fieldnote">フィールドノートとしてエクスポート中…</string> <string name="caches_removing_from_history">履歴から削除中…</string> <!-- caches lists --> @@ -402,7 +379,6 @@ <string name="init_offline_wp">オフライン用にウェイポイントの地図を保存する</string> <string name="init_save_log_img">オフライン用にログの添付画像を保存する</string> <string name="init_units">距離をマイル/フィートで表示\n(イギリス帝国単位)</string> - <string name="init_nav">Googleマップナビを使う</string> <string name="init_log_offline">ログ書きをオフライン専用にする\n(ログを書く際にオフライン専用にし、オンラインでの投稿をしない。このチェックを外してもオフライン用に保存することは可能です)</string> <string name="init_livelist">キャッシュの一覧で方向をアイコン表示する</string> <string name="init_altitude">標高の修正</string> @@ -426,14 +402,10 @@ <string name="init_mapsources">地図の設定</string> <string name="init_mapsources_description">オンライン地図をGoogleマップからOpenStreetMap(その派生オンライン地図やオフライン地図)に変更できます。詳細は<a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a> (英語)をご覧ください。</string> <string name="init_mapsource_select">地図の選択</string> - <string name="init_select_gpx_exportdir">選択…</string> - <string name="init_select_gpx_importdir">選択…</string> <string name="init_gpx_exportdir">GPXエクスポートフォルダ</string> <string name="init_gpx_importdir">GPXインポートフォルダ</string> <string name="init_gpx_exportdir_description">GPXファイルへエクスポートする際の保存先フォルダを選択できます。</string> <string name="init_gpx_importdir_description">GPXファイルへインポートする際の保存先フォルダを選択できます。</string> - <string name="init_gpx_exportdir_select">GPXファイルのエクスポートフォルダを選択</string> - <string name="init_gpx_importdir_select">GPXファイルのインポートフォルダを選択</string> <string name="init_maptrail">地図に軌跡を表示</string> <string name="init_share_after_export">エクスポートした後に共有メニューを表示</string> <string name="init_trackautovisit">「見つけた」ログを書く際に、持っているトラッカブルアイテムを自動的に「訪れた」にする</string> @@ -449,20 +421,11 @@ <string name="init_dbonsdcard_title">データベースの保存場所</string> <string name="init_dbonsdcard_note">c:geoのデータベースを外部メディア(SDカード)に保存することもできます。その場合は端末の内蔵メモリの空き容量は増えますが、c:geoはSDカードなしでは使用できなくなり動作も少し遅くなるかもしれません。</string> <string name="init_dbonsdcard">SDカードにデータベースを保存</string> - <string name="init_dbmove">データベースの移動</string> <string name="init_dbmove_dbmove">データベースの移動</string> <string name="init_dbmove_running">データベースの移動中</string> <string name="init_dbmove_success">データベースを移動しました。</string> <string name="init_dbmove_failed">データベースの移動に失敗しました</string> - <!-- map sources --> - <string-array name="map_sources"> - <item>@string/map_source_google_map</item> - <item>@string/map_source_google_satellite</item> - <item>@string/map_source_osm_mapnik</item> - <item>@string/map_source_osm_cyclemap</item> - <item>@string/map_source_osm_offline</item> - </string-array> <string name="map_source_google_map">Googleマップ:地図</string> <string name="map_source_google_satellite">Googleマップ:航空写真</string> <string name="map_source_osm_mapnik">OpenStreetMap</string> @@ -513,7 +476,6 @@ <string name="cache_offline_time_days">日前</string> <string name="cache_premium">プレミアム会員</string> <string name="cache_attributes">属性</string> - <string name="cache_attributes_no_icons">(属性アイコンを表示するためにはキャッシュ情報を更新してください)</string> <string name="cache_inventory">目録</string> <string name="cache_log_offline">オフラインログ</string> <string name="cache_log_images_loading">添付画像をロード中…</string> @@ -523,7 +485,6 @@ <string name="cache_description">説明</string> <string name="cache_description_long">全て表示</string> <string name="cache_description_table_note">キャッシュ情報の説明にはhtmlを使ったテーブル表が含まれています。正しく表示するにはブラウザで開く必要があるかもしれません。</string> - <string name="cache_watchlist">ウォッチリスト</string> <string name="cache_watchlist_on">このキャッシュはウォッチリストに登録されています。</string> <string name="cache_watchlist_not_on">このキャッシュはウォッチリストに登録されていません。</string> <string name="cache_watchlist_add">ウォッチリストに追加</string> @@ -563,7 +524,6 @@ <string name="cache_dialog_watchlist_remove_title">ウォッチリスト</string> <string name="cache_dialog_watchlist_remove_message">ウォッチリストから削除中…</string> <string name="cache_menu_navigate">ナビゲーション</string> - <string name="cache_menu_tbt">道順ナビ</string> <string name="cache_menu_radar">レーダー</string> <string name="cache_menu_map">地図で表示</string> <string name="cache_menu_map_static">オフライン地図</string> @@ -611,7 +571,6 @@ <string name="cache_spoiler_images_loading">スポイラー画像をロード中…</string> <string name="cache_log_types">ログタイプ</string> <string name="cache_coordinates_no">このキャッシュに座標値はありません。</string> - <string name="cache_export_fieldnote">フィールドノートとしてエクスポート</string> <string name="cache_clear_history">全履歴を削除</string> <string name="cache_remove_from_history">履歴から削除</string> <string name="cache_license">ライセンス</string> @@ -636,7 +595,6 @@ <string name="gpx_import_loading_caches">GPXファイルからキャッシュをロード中</string> <string name="gpx_import_loading_waypoints">ウェイポイントファイルをロード中</string> <string name="gpx_import_store_static_maps">オフライン地図を保存中</string> - <string name="gpx_import_storing">キャッシュ情報をデータベースに書き込み中</string> <string name="gpx_import_caches_imported">個のキャッシュをインポートしました</string> <string name="gpx_import_static_maps_skipped">オフライン用地図のダウンロードを中止しました</string> <string name="gpx_import_title_static_maps">オフライン用に地図を保存</string> @@ -654,7 +612,6 @@ <string name="map_file_select_title">地図ファイルの選択</string> <!-- import --> - <string name="import_title">インポート…</string> <string name="web_import_title">Webからインポート(Send 2 c:geo経由)</string> <string name="web_import_waiting">Webから新しいキャッシュ情報を確認中…</string> <string name="web_downloading">ダウンロード中</string> @@ -665,7 +622,6 @@ <!-- waypoint --> <string name="waypoint">ウェイポイント</string> - <string name="waypoint_title">ウェイポイント</string> <string name="waypoint_cache_coordinates">キャッシュ座標</string> <string name="waypoint_custom">カスタム</string> <string name="waypoint_my_coordinates">現在地</string> @@ -679,23 +635,15 @@ <string name="waypoint_note">メモ</string> <string name="waypoint_save">保存</string> <string name="waypoint_loading">ウェイポイントをロード中…</string> - <string name="waypoint_unknown_coordinates">座標値が不明</string> <string name="waypoint_done">決定</string> <string name="waypoint_duplicate">複製</string> <string name="waypoint_copy_of">コピー ~ </string> - <string name="waypoint_menu_open_cache">Open Cache</string> <string name="search_history">履歴</string> <string name="search_history_empty">履歴はありません</string> <string name="search_remove_destination">履歴から削除しました</string> <string name="search_clear_history">全履歴を削除</string> <string name="search_history_cleared">全履歴を削除しました</string> - <string-array name="waypoint_coordinate_formats"> - <item>@string/waypoint_coordinate_formats_plain</item> - <item>DDD.DDDDD°</item> - <item>DDD°MM.MMM\'</item> - <item>DDD°MM\'SS.SSS\"</item> - </string-array> <string name="waypoint_coordinate_formats_plain">プレーン</string> <!-- distance units --> @@ -832,7 +780,6 @@ <!-- export --> <string name="export">エクスポート</string> - <string name="export_as">Export as…</string> <string name="export_exportedto">にエクスポートしました</string> <string name="export_failed">エクスポートに失敗しました</string> <string name="export_fieldnotes">フィールドノート</string> @@ -1003,11 +950,11 @@ <string name="about_auth_2">「認証を開始する」ボタンを押すとブラウザでTwitterのページが開きます。そのページにログインすれば<b>c:geo</b>があなたのアカウントにアクセルする許可が得られます。ログインに成功したら数字のPINコードが表示されるので、この下の入力欄にコピー&ペーストして「完了」ボタンを押してください。</string> <!-- status --> - <string name="status_new_release">新しいバージョンがあります。\nクリックしてインストールしてください。</string> - <string name="status_new_nightly">新しいナイトリービルドがあります。\nクリックしてインストールしてください。</string> - <string name="status_new_rc">新しいRCバージョンがあります。\nクリックしてインストールしてください。</string> - <string name="status_geocaching_change">geocaching.comが更新されましたがc:geoはまだ未対応です。\n現在、作業中です。しばらくお待ちください。</string> - <string name="status_geocaching_livemap">geocaching.comが更新されましたがオンライン地図機能はまだ未対応です。\n現在、作業中です。しばらくお待ちください。</string> + <string name="status_new_release" tools:ignore="UnusedResources">新しいバージョンがあります。\nクリックしてインストールしてください。</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">新しいナイトリービルドがあります。\nクリックしてインストールしてください。</string> + <string name="status_new_rc" tools:ignore="UnusedResources">新しいRCバージョンがあります。\nクリックしてインストールしてください。</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">geocaching.comが更新されましたがc:geoはまだ未対応です。\n現在、作業中です。しばらくお待ちください。</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">geocaching.comが更新されましたがオンライン地図機能はまだ未対応です。\n現在、作業中です。しばらくお待ちください。</string> <string name="clipboard_copy_ok">クリップボードにコピーしました</string> <plurals name="days_ago"> diff --git a/main/res/values-nb/strings.xml b/main/res/values-nb/strings.xml index 6e8435c..b10871e 100644 --- a/main/res/values-nb/strings.xml +++ b/main/res/values-nb/strings.xml @@ -68,9 +68,6 @@ <string name="log_post_rate">Last opp loggen og rangér</string> <string name="log_post_no_rate">Last opp loggen uten å rangere</string> <string name="log_add">Legg til</string> - <string name="log_date">Dato</string> - <string name="log_time">Klokkelsett</string> - <string name="log_date_time">Dato og klokkeslett</string> <string name="log_rating">Rangering</string> <string name="log_no_rating">Ingen rangering</string> <string name="log_stars_1">1 stjerne</string> @@ -94,8 +91,6 @@ <string name="err_missing_auth">Brukernavn eller passord er ikke oppgitt.</string> <string name="err_wrong">Feilaktige innloggings-opplysninger</string> <string name="err_license">Brukeren har ikke akseptert Geocaching.com sin lisens-betingelse, så c:geo kan ikke laste cachens koordinater</string> - <string name="err_store">Beklager, c:geo klarte ikke å lagre cachen.</string> - <string name="err_drop">Beklager, c:geo klarte ikke å slette cachen.</string> <string name="err_detail_open">Beklager, c:geo klarte ikke å finne detaljene.</string> <string name="err_detail_cache">Beklager, c:geo klarte ikke å finne den forespurte cachen. Er du sikker på at den eksisterer?</string> <string name="err_detail_cache_find">Beklager, c:geo klarte ikke å finne geocachen</string> @@ -106,24 +101,18 @@ <string name="err_detail_cache_forgot_visit">Beklager, c:geo glemte hvilken cache du fant.</string> <string name="err_detail_no_spoiler">c:geo fant ingen bilder for denne cachen.</string> <string name="err_detail_no_map_static">c:geo fant ingen statiske kart for denne cachen.</string> - <string name="err_navigation_no">c:geo klarte ikke å finne støttet navigasjon.</string> <string name="err_application_no">c:geo klarte ikke å finne en passende applikasjon.</string> <string name="err_auth_initialize">Beklager, c:geo klarte ikke å igangsette autoriserings-prosessen.</string> <string name="err_auth_process">Autoriserings-prosessen mislyktes.</string> <string name="err_cannot_log_visit">c:geo har ikke nok informasjon til å logge funn. Prøv å laste inn cachens detaljer først.</string> <string name="err_init_cleared">Beklager, c:geo klarte ikke å fjerne innloggings-opplysningene.</string> <string name="err_download_fail">Beklager. c:geo klarte ikke å laste ned cachene p.g.a.</string> - <string name="err_list_load_fail">Beklager, c:geo klarte ikke å laste cache-listen..</string> - <string name="err_store_failed">Beklager, c:geo klarte ikke å lagre cachen.</string> - <string name="err_refresh_failed">Beklager, c:geo klarte ikke å oppdatere cachen.</string> <string name="err_dwld_details_failed">Beklager, c:geo klarte ikke å laste ned cachens detaljer</string> <string name="err_load_descr_failed">Beklager, c:geo klarte ikke å åpne beskrivelsen.</string> <string name="err_location_unknown">c:geo vet ikke hvor cachen er.</string> <string name="err_tb_display">"Beklager, c:geo klarte ikke å finne trackable\'en du etterspurte. Er det virkelig en trackable?</string> <string name="err_tb_details_open">Beklager, c:geo klarte ikke å åpne tracable\'ens detaljer.</string> - <string name="err_tb_details_download">Beklager, c:geo klarte ikke å laste ned trackable\'ens detaljer p.g.a.</string> - <string name="err_tb_forgot">Beklager, c:geo glemte hvilken trackable du etterspurte.</string> <string name="err_tb_forgot_saw">Beklager, c:geo glemte hvilken trackable du oppdaget.</string> <string name="err_tb_find">Beklager, c:geo klarte ikke å finne noen trackable\'er.</string> <string name="err_tb_find_that">Beklager, c:geo kan ikke finne noen trackable\'er</string> @@ -134,7 +123,6 @@ <string name="err_log_failed_server">Beklager, c:geo klarte ikke å logge funnet fordi serveren er nede.</string> <string name="err_log_post_failed">Beklager, c:geo klarte ikke å logge funnet.</string> - <string name="err_search_address_no_match">Beklager, c:geo klarte ikke å finne den forespurte adressen.</string> <string name="err_search_address_forgot">Beklager, c:geo glemte adressen du prøvde å finne.</string> <string name="err_parse_lat">Beklager, c:geo klarte ikke å lese breddegraden.</string> <string name="err_parse_lon">Beklager, c:geo klarte ikke å lese lengdegraden.</string> @@ -230,7 +218,6 @@ <string name="init_disabled">Ekskluder deaktiverte cacher</string> <string name="init_offline">Lagre kartet for offline-bruk (små deler)</string> <string name="init_units">Bruk imperialistiske måleenheter</string> - <string name="init_nav">Bruk Google Navigation</string> <string name="init_autoload">Last full beskrivelse automatisk</string> <string name="init_livelist">Vis cachers retning i listen</string> <string name="init_clear">Ikke husk meg</string> @@ -284,7 +271,6 @@ <string name="cache_dialog_refresh_title">Oppdater</string> <string name="cache_dialog_refresh_message">Laster cachens detaljer på nytt…</string> <string name="cache_menu_navigate">Navigér</string> - <string name="cache_menu_tbt">Punktvis navigasjon</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Vis på kartet</string> <string name="cache_menu_map_ext">Vis på utvidet kart</string> diff --git a/main/res/values-nl/strings.xml b/main/res/values-nl/strings.xml index 8013de3..48de4aa 100644 --- a/main/res/values-nl/strings.xml +++ b/main/res/values-nl/strings.xml @@ -87,9 +87,6 @@ <string name="log_post_no_rate">Post log zonder beoordeling</string> <string name="log_post_not_possible">Laden Log Pagina…</string> <string name="log_add">Toevoegen</string> - <string name="log_date">Datum</string> - <string name="log_time">Tijd</string> - <string name="log_date_time">Datum & tijd</string> <string name="log_rating">Beoordeling</string> <string name="log_no_rating">Geen beoordeling</string> <string name="log_stars_1">1 ster</string> @@ -136,8 +133,6 @@ <string name="err_license">Gebruiker heeft de gebruikersvoorwaarden van Geocaching.com niet geaccepteerd.</string> <string name="err_unpublished">De cache is nog niet gepubliceerd</string> <string name="err_premium_only">Deze cache is alleen beschikbaar voor Geocaching.com premium leden.</string> - <string name="err_store">Sorry, c:geo kan de cache niet opslaan.</string> - <string name="err_drop">Sorry, c:geo kan de cache niet wissen.</string> <string name="err_detail_open">Sorry, c:geo kan de geocache details niet openen.</string> <string name="err_detail_cache">Sorry, c:geo kan de gezochte geocache niet weergeven.</string> <string name="err_detail_cache_find">Sorry, c:geo kan de geocache niet vinden.</string> @@ -149,20 +144,15 @@ <string name="err_detail_no_spoiler">c:geo Heeft geen spoiler images gevonden voor deze cache.</string> <string name="err_detail_no_map_static">c:geo Heeft geen statische kaarten gevonden voor deze cache.</string> <string name="err_detail_not_load_map_static">Sorry, c:geo kon de statische kaart niet laden.</string> - <string name="err_detail_ask_store_map_static">c:geo kon statische kaarten niet laden. Nu opslaan?</string> <string name="err_detail_still_working">Nog bezig met een andere (achtergrond)taak.</string> <string name="err_watchlist_still_managing">Bezig je watchlist te beheren.</string> <string name="err_watchlist_failed">Het veranderen van watchlist lukt niet.</string> - <string name="err_navigation_no">c:geo Kan geen ondersteunde navigatie applicatie vinden.</string> <string name="err_application_no">c:geo Kan geen geschikte applicatie vinden.</string> <string name="err_auth_initialize">Sorry, het is c:geo niet gelukt het autorisatie proces te initialiseren.</string> <string name="err_auth_process">Autorisatie proces mislukt.</string> <string name="err_cannot_log_visit">c:geo Heeft onvoldoende informatie om bezoek te loggen. Probeer het vanuit de volledige cache details.</string> <string name="err_init_cleared">Sorry, c:geo kan de inlog informatie niet wissen.</string> <string name="err_download_fail">Sorry, c:geo heeft caches niet kunnen downloaden omdat </string> - <string name="err_list_load_fail">Sorry, c:geo heeft cache lijst niet kunnen laden.</string> - <string name="err_store_failed">Sorry, c:geo kan de geocache niet opslaan.</string> - <string name="err_refresh_failed">Sorry, c:geo kan de geocache niet verversen.</string> <string name="err_dwld_details_failed">Sorry, c:geo kon de cache details niet downloaden.</string> <string name="err_load_descr_failed">Sorry, c:geo kan de omschrijving niet laden.</string> <string name="err_location_unknown">c:geo kent de locatie van de cache niet.</string> @@ -170,18 +160,12 @@ <string name="err_tb_display">Sorry, c:geo kan de gezochte trackable niet weergeven. Is het wel een trackable?</string> <string name="err_tb_details_open">Sorry, c:geo kan de trackable details niet laden.</string> - <string name="err_tb_details_download">Sorry, c:geo kon de trackable details niet downloaden omdat</string> - <string name="err_tb_forgot">Sorry, c:geo is vergeten welke trackable je wilde.</string> <string name="err_tb_forgot_saw">Sorry, c:geo is vergeten welke trackable je gezien hebt.</string> <string name="err_tb_find">Sorry, c:geo kan de trackable niet vinden</string> <string name="err_tb_find_that">Sorry, c:geo kan die trackable niet vinden.</string> <string name="err_waypoint_cache_unknown">Sorry, c:geo weet niet aan welke cache je een waypoint wil toevoegen.</string> - <string name="err_waypoint_unknown">Sorry, c:geo is vergeten welke waypoint je wil laten zien.</string> <string name="err_waypoint_add_failed">Sorry, c:geo kon de waypoint niet toevoegen.</string> - <string name="err_waypoint_load_failed">Sorry, c:geo kon de waypoint niet laden.</string> - <string name="err_waypoint_delete_failed">Sorry, c:geo kan de waypoint niet wissen.</string> - <string name="err_waypoint_open_cache_failed">c:geo kan cachedetails niet openen.</string> <string name="err_point_unknown_position">Sorry, c:geo kan niet bepalen waar je bent.</string> <string name="err_point_no_position_given_title">Info benodigd</string> <string name="err_point_no_position_given">Geef op zijn minst lengte- en breedtegraad of afstand en richting. Of vul alle 4 de velden.</string> @@ -196,15 +180,12 @@ <string name="err_log_failed_server">Sorry, c:geo kon bezoek niet loggen omdat de server niet reageert.</string> <string name="err_log_post_failed">Sorry, het is c:geo niet gelukt het log te posten.</string> - <string name="err_search_address_no_match">Sorry, c:geo heeft geen gelijkende plaats gevonden.</string> <string name="err_search_address_forgot">Sorry, c:geo is het adres dat je zoekt vergeten.</string> <string name="err_parse_lat">Sorry, c:geo kan breedtegraad niet verwerken.</string> <string name="err_parse_lon">Sorry, c:geo kan lengtegraad niet verwerken.</string> <string name="err_parse_dist">Sorry, c:geo kan afstand niet verwerken.</string> <string name="err_parse_lat_lon">Sorry, c:geo kan breedtegraad of lengtegraad niet verwerken.</string> - <string name="err_fieldnotes_export_failed">Exporteren van Field Notes niet gelukt.</string> - <string name="warn_save_nothing">Er is niets op te slaan.</string> <string name="warn_no_cache_coord">Er is geen cache met deze coördinaten.</string> <string name="warn_no_coordinates">Geen coördinaten opgegeven.</string> @@ -225,7 +206,6 @@ <string name="info_log_cleared">Log is gewist.</string> <string name="info_log_type_changed">Type log is gewijzigd!</string> - <string name="info_fieldnotes_exported_to">Field Notes geëxporteerd naar</string> <string name="info_storing_static_maps">Probeer statische kaarten op te slaan</string> <!-- location service --> @@ -310,10 +290,7 @@ <string name="caches_filter_type">type</string> <string name="caches_filter_track">met trackables</string> <string name="caches_filter_clear">maak filters leeg</string> - <string name="caches_filter_size_title">Kies grootte</string> - <string name="caches_filter_type_title">Kies type</string> <string name="caches_filter_modified">Met aangepaste coordinaten</string> - <string name="caches_exporting_fieldnote">Exporteer als Field Notes…</string> <string name="caches_removing_from_history">Verwijderen uit geschiedenis…</string> <!-- caches lists --> @@ -388,7 +365,6 @@ <string name="init_offline_wp">Statische kaarten van waipoints opslaan voor gebruik zonder verbinding</string> <string name="init_save_log_img">Sla afbeeldingen van logs op</string> <string name="init_units">Gebruik imperiale stelsel voor afstanden</string> - <string name="init_nav">Gebruik Google Navigatie</string> <string name="init_log_offline">Als er gelogd word, doe dit altijd offline (Laat het online log scherm niet zien en verzend de log niet)</string> <string name="init_livelist">Toon afstand tot cache in lijst</string> <string name="init_altitude">Hoogte correctie</string> @@ -472,7 +448,6 @@ <string name="cache_offline_time_days">dagen geleden</string> <string name="cache_premium">Premium</string> <string name="cache_attributes">Attributen</string> - <string name="cache_attributes_no_icons">(herlaad cache om attribuut-iconen weer te geven)</string> <string name="cache_inventory">Inventaris</string> <string name="cache_log_offline">Offline log</string> <string name="cache_log_images_loading">Laden van logafbeeldingen…</string> @@ -482,7 +457,6 @@ <string name="cache_description">Omschrijving</string> <string name="cache_description_long">Lange omschrijving</string> <string name="cache_description_table_note">Omschrijving bevat een tabel-layout welke misschien op geocaching.com bekeken moet worden.</string> - <string name="cache_watchlist">Watchlist</string> <string name="cache_watchlist_on">Deze cache komt voor op je watchlist.</string> <string name="cache_watchlist_not_on">Deze cache komt niet voor op je watchlist.</string> <string name="cache_watchlist_add">Voeg aan watchlist toe</string> @@ -516,7 +490,6 @@ <string name="cache_dialog_watchlist_remove_title">Watchlist</string> <string name="cache_dialog_watchlist_remove_message">Verwijder cache van watchlist…</string> <string name="cache_menu_navigate">Navigeer</string> - <string name="cache_menu_tbt">Turn-by-turn</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Toon op kaart</string> <string name="cache_menu_map_static">Statische kaarten</string> @@ -562,7 +535,6 @@ <string name="cache_spoiler_images_loading">Spoiler afbeeldingen laden…</string> <string name="cache_log_types">Log types</string> <string name="cache_coordinates_no">Deze cache heeft geen coördinaten.</string> - <string name="cache_export_fieldnote">Exporteer als Field Notes</string> <string name="cache_clear_history">Maak geschiedenis leeg</string> <string name="cache_remove_from_history">Verwijder uit geschiedenis</string> <string name="cache_license">Licentie</string> @@ -582,7 +554,6 @@ <string name="gpx_import_loading_caches">Caches laden van .gpx bestand</string> <string name="gpx_import_loading_waypoints">Waypoints laden van .gpx bestand</string> <string name="gpx_import_store_static_maps">Opslaan statische kaarten</string> - <string name="gpx_import_storing">Opslaan caches in de database</string> <string name="gpx_import_caches_imported">Caches geïmporteerd</string> <string name="gpx_import_static_maps_skipped">Download van statische kaarten afgebroken</string> <string name="gpx_import_title_static_maps">Sla statische kaarten op</string> @@ -600,7 +571,6 @@ <string name="map_file_select_title">Selecteer mapbestand</string> <!-- import --> - <string name="import_title">Import…</string> <string name="web_import_title">Importeer van web</string> <string name="web_import_waiting">Aan het wachten voor nieuwe caches van het web…</string> <string name="web_downloading">Downloading</string> @@ -611,7 +581,6 @@ <!-- waypoint --> <string name="waypoint">Waypoint</string> - <string name="waypoint_title">Waypoint</string> <string name="waypoint_cache_coordinates">Cache coördinaten</string> <string name="waypoint_custom">Aangepast</string> <string name="waypoint_my_coordinates">Mijn coördinaten</string> @@ -625,11 +594,9 @@ <string name="waypoint_note">Notitie</string> <string name="waypoint_save">Opslaan</string> <string name="waypoint_loading">Waypoint laden…</string> - <string name="waypoint_unknown_coordinates">coördinaten niet bekend</string> <string name="waypoint_done">Klaar</string> <string name="waypoint_duplicate">Dubbel</string> <string name="waypoint_copy_of">Kopie van</string> - <string name="waypoint_menu_open_cache">Open Cache</string> <string name="search_history">Geschiedenis</string> <string name="search_history_empty">Geen eerdere bestemmingen</string> <string name="search_remove_destination">Bestemming verwijderd</string> diff --git a/main/res/values-pl/strings.xml b/main/res/values-pl/strings.xml index 3b6b308..e8c4b63 100644 --- a/main/res/values-pl/strings.xml +++ b/main/res/values-pl/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo kompas</string> @@ -8,9 +8,11 @@ <string name="detail">Szczegóły</string> <string name="search">Szukaj</string> <string name="settings">Ustawienia</string> - <string name="helpers">Przydatne aplikacje</string> + <string name="helpers">Przydatne programy</string> <string name="about">O c:geo</string> - <string name="helper">Chcesz dowiedzieć się więcej o <b>c:geo</b>?\nZajrzyj do instrukcji opsługi programu.</string> + <string name="helper">Chcesz dowiedzieć się więcej o <b>c:geo</b>?\nZajrzyj do instrukcji obsługi.</string> + <string name="latitude">Szerokość geograficzna</string> + <string name="longitude">Długość geograficzna</string> <!-- actionbar --> <string name="action_bar_share_title">Podziel się linkiem do skrzynki</string> @@ -21,39 +23,41 @@ <string name="multi">Skrzynki wieloetapowe</string> <string name="mystery">Skrzynki zagadkowe</string> <string name="letterbox">Hybrydowe Letterbox</string> - <string name="event">Typu wydarzenie</string> + <string name="event">Wydarzenie</string> <string name="mega">Mega-Wydarzenie</string> <string name="earth">Earthcache</string> <string name="cito">CITO</string> - <string name="webcam">Skrzynki webcam</string> + <string name="webcam">Skrzynki Webcam</string> <string name="virtual">Skrzynki wirtualne</string> <string name="wherigo">Scenariusze Wherigo</string> <string name="lostfound">Lost & found</string> - <string name="ape">Projekt ape cache</string> + <string name="ape">Projekt APE Cache</string> <string name="gchq">Groundspeak HQ</string> - <string name="gps">GPS cache exhibit</string> + <string name="gps">GPS Adventures exhibit</string> + <string name="unknown">Nieznana</string> <!-- cache sizes --> - <string name="cache_size_micro">mikro</string> - <string name="cache_size_small">mała</string> - <string name="cache_size_regular">normalna</string> - <string name="cache_size_large">duża</string> - <string name="cache_size_other">inna</string> - <string name="cache_size_virtual">wirtualna</string> - <string name="cache_size_notchosen">nie wybrana</string> - <string name="cache_size_unknown">nieznany</string> + <string name="cache_size_micro">Mikro</string> + <string name="cache_size_small">Mała</string> + <string name="cache_size_regular">Normalna</string> + <string name="cache_size_large">Duża</string> + <string name="cache_size_other">Inna</string> + <string name="cache_size_virtual">Wirtualna</string> + <string name="cache_size_notchosen">Niewybrana</string> + <string name="cache_size_unknown">Nieznana</string> <!-- waypoints --> <string name="wp_final">Finał</string> - <string name="wp_stage">Etap do skrzynki</string> - <string name="wp_puzzle">Pytanie do odpowiedzi</string> + <string name="wp_stage">Etap</string> + <string name="wp_puzzle">Zagadka</string> <string name="wp_pkg">Parking</string> <string name="wp_trailhead">Punkt wyjścia</string> <string name="wp_waypoint">Punkt nawigacji</string> + <string name="wp_original">Oryginalne współrzędne</string> <!-- logs --> - <string name="log_found">Znalezione</string> - <string name="log_dnf">Nie znalezione</string> + <string name="log_found">Znalazłem</string> + <string name="log_dnf">Nie znalazłem</string> <string name="log_note">Notatka</string> <string name="log_published">Opublikowano</string> <string name="log_enabled">Aktywny</string> @@ -63,27 +67,29 @@ <string name="log_retrieved">Zabrałem</string> <string name="log_placed">Umieściłem</string> <string name="log_grabbed">Znalazłem gdzieś indziej</string> + <string name="log_movecollection">Przenieś do Kolekcji</string> + <string name="log_moveinventory">Przenieś do Inwentarza</string> <string name="log_maintained">Przegląd przeprowadzony</string> - <string name="log_maintenance_needed">Przegląd potrzebny</string> - <string name="log_update">Zmienione współrzędne</string> - <string name="log_archived">Zarchiwizowane</string> - <string name="log_needs_archived">Powinno zostać zarchiwizowane</string> - <string name="log_discovered">Odkryty</string> - <string name="log_reviewer">Sprawdzony</string> + <string name="log_maintenance_needed">Wymaga przeglądu</string> + <string name="log_update">Zmieniono współrzędne</string> + <string name="log_archived">Zarchiwizowana</string> + <string name="log_unarchived">Nie jest zarchiwizowana</string> + <string name="log_needs_archived">Powinna zostać zarchiwizowana</string> + <string name="log_discovered">Odkryta</string> + <string name="log_reviewer">Sprawdzona</string> + <string name="log_retractlisting">Wycofaj listing</string> <string name="log_tb_nothing">Nie rób nic</string> - <string name="log_tb_visit">Odwiedzić</string> - <string name="log_tb_drop">Odłożyć</string> - <string name="log_tb_changeall">Wszystkie zmienić</string> + <string name="log_tb_visit">Odwiedzony</string> + <string name="log_tb_drop">Odłożony</string> + <string name="log_tb_changeall">Zmień wszystko</string> <string name="log_save">Zapisz</string> - <string name="log_saving">Wpis w dzienniku…</string> - <string name="log_clear">Oczyść</string> + <string name="log_saving">Zapisuję w dzienniku…</string> + <string name="log_clear">Wyczyść</string> <string name="log_post">Wpisz do dziennika</string> <string name="log_post_rate">Wpisz do dziennika & oceń</string> <string name="log_post_no_rate">Wpisz do dziennika & nie oceniaj</string> + <string name="log_post_not_possible">Ładuję dziennik…</string> <string name="log_add">Dodaj</string> - <string name="log_date">Data</string> - <string name="log_time">Godzina</string> - <string name="log_date_time">Data & godzina</string> <string name="log_rating">Ocena</string> <string name="log_no_rating">Bez oceny</string> <string name="log_stars_1">1 gwiazdka</string> @@ -95,117 +101,123 @@ <string name="log_stars_4">4 gwiazdki</string> <string name="log_stars_45">4,5 gwiazdki</string> <string name="log_stars_5">5 gwiazdek</string> - <string name="log_stars_1_description">bardzo słaba</string> - <string name="log_stars_15_description">słaba</string> - <string name="log_stars_2_description">raczej słaba</string> - <string name="log_stars_25_description">może być</string> - <string name="log_stars_3_description">średnia</string> - <string name="log_stars_35_description">prawie dobra</string> - <string name="log_stars_4_description">dobra</string> - <string name="log_stars_45_description">bardzo dobra</string> - <string name="log_stars_5_description">świetna</string> + <string name="log_stars_1_description">Słaba</string> + <string name="log_stars_15_description">Raczej słaba</string> + <string name="log_stars_2_description">Poniżej średniej</string> + <string name="log_stars_25_description">Niezła</string> + <string name="log_stars_3_description">Średnia</string> + <string name="log_stars_35_description">Całkiem dobra</string> + <string name="log_stars_4_description">Powyżej średniej</string> + <string name="log_stars_45_description">Bardzo dobra</string> + <string name="log_stars_5_description">Świetna</string> <string name="log_webcam">Zdjęcie Webcam zrobione</string> <string name="log_new_log">Dodaj wpis</string> <string name="log_new_log_text">Komentarz</string> <string name="log_announcement">Ogłoszenie</string> + <string name="log_today">Dzisiaj</string> + <string name="log_yesterday">Wczoraj</string> + <string name="log_smilies">Uśmiechy</string> + + <!-- translation --> + <string name="translate_to_sys_lang">Przetłumacz na %s</string> + <string name="translate_to_english">Przetłumacz na angielski</string> + <string name="translate_length_warning">Tłumaczenie może nie udać się przy dużej ilości tekstu.</string> <!-- errors, warnings, info toasts --> <string name="err_none">OK</string> - <string name="err_start">Komunikacja nie wystartowana</string> - <string name="err_parse">Nieudana analiza strony logowania.</string> - <string name="err_server">Nieudane połączenie z Geocaching.com (server albo połączenie nieaktywne?)</string> - <string name="err_login">Brakuje danych do logowania.</string> - <string name="err_login_failed">Przepraszam, c:geo nie może się zalogować.</string> + <string name="err_start">Komunikacja nie rozpoczeła się</string> + <string name="err_parse">Nieudany odczyt strony logowania.</string> + <string name="err_server">Nieudane połączenie z Geocaching.com. Strona albo Twoje połączenie internetowe nie działa.</string> + <string name="err_login">Brak danych do logowania.</string> + <string name="err_login_failed">c:geo nie może zalogować się.</string> + <string name="err_login_failed_toast">c:geo nie może zalogować się. c:geo pracuje offline z zapisanymi skrzynkami. Sprawdź dane logowania i połączenie z internetem.</string> <string name="err_unknown">Nieznany błąd</string> <string name="err_comm">Nieznany błąd w komunikacji</string> - <string name="err_missing_auth">Nie wpisana nazwa użytkownika i/lób hasła.</string> + <string name="err_missing_auth">Brak nazwy użytkownika i/lub hasła.</string> <string name="err_wrong">Niepoprawne dane użytkownika</string> - <string name="err_license">Użytkownik nie zgodził się jeszcze z regulaminem serwisu Geocaching.com, c:geo nie jest w stanie załadować współrzędnych.</string> - <string name="err_store">Przepraszam, c:geo nie mógł zapisać skrzynki.</string> - <string name="err_drop">Przepraszam, c:geo nie mógł skasować skrzynki.</string> - <string name="err_detail_open">Przepraszam, c:geo nie mógł otworzyć szczegółów skrzynki.</string> - <string name="err_detail_cache">Przepraszam, c:geo nie mógł pokazać tobie skrzynki. Czy to jest naprawdę skrzynka?</string> - <string name="err_detail_cache_find">Przepraszam, c:geo nie mógł znaleść skrzynki.</string> - <string name="err_detail_cache_find_some">Przepraszam, c:geo nie mógł znaleść tej skrzynki.</string> - <string name="err_detail_cache_find_any">Przepraszam, c:geo nie mógł znaleść żadnej skrzynki.</string> - <string name="err_detail_cache_find_next">Przepraszam, c:geo nie mógł znaleść następnej skrzynki.</string> - <string name="err_detail_cache_forgot">Przepraszam, c:geo zapomniał którą skrzynkę chciałeś obejrzeć.</string> - <string name="err_detail_cache_forgot_visit">Przepraszam, c:geo zapomniał którą skrzynkę chciałeś odwiedzić.</string> + <string name="err_maintenance">Trwają prace serwisowe w Geocaching.com. c:geo pracuje offline z zapisanymi skrzynkami.</string> + <string name="err_license">Użytkownik nie zaakceptował jeszcze regulaminu Geocaching.com, więc c:geo nie może załadować współrzędnych skrzynek.</string> + <string name="err_unpublished">Szukana skrzynka nie została opublikowana.</string> + <string name="err_premium_only">Ta skrzynka jest dostępna tylko dla użytkowników Premium serwisu Geocaching.com.</string> + <string name="err_detail_open">c:geo nie mógł otworzyć szczegółów skrzynki.</string> + <string name="err_detail_cache">c:geo nie mógł pokazać skrzynki. Czy to naprawdę jest skrzynka?</string> + <string name="err_detail_cache_find">c:geo nie mógł znaleźć skrzynki.</string> + <string name="err_detail_cache_find_some">c:geo nie mógł znaleźć tej skrzynki.</string> + <string name="err_detail_cache_find_any">c:geo nie mógł znaleźć żadnej skrzynki.</string> + <string name="err_detail_cache_find_next">c:geo nie mógł znaleźć następnych skrzynek.</string> + <string name="err_detail_cache_forgot">c:geo zapomniał którą skrzynkę chcesz obejrzeć.</string> + <string name="err_detail_cache_forgot_visit">c:geo zapomniał którą skrzynkę odwiedziłeś.</string> + <string name="err_detail_google_maps_limit_reached">c:geo nie był w stanie pobrać map statycznych. Może limit map Google został wyczerpany.</string> <string name="err_detail_no_spoiler">c:geo nie znalazł zdjęcia spoilera dla tej skrzynki.</string> - <string name="err_detail_no_map_static">c:geo nie znalazł mapki statycznej dla tej skrzynki.</string> - <string name="err_detail_not_load_map_static">Przepraszam, c:geo nie mógł załadować statycznej mapki.</string> - <string name="err_watchlist_still_managing">Nadal pracuję nad listą obserwowanych.</string> - <string name="err_watchlist_failed">c:geo nie mógł zmienić listy obserwowanych.</string> - <string name="err_navigation_no">c:geo nie znalazł żadnych wsparć do nawigacji.</string> - <string name="err_application_no">c:geo nie znalazł żadnych odpowiednich aplikacji.</string> - <string name="err_auth_initialize">Przepraszam, c:geo nie może zainicjować procesu autoryzacji.</string> - <string name="err_auth_process">Proces autoryzacji nie udany.</string> - <string name="err_cannot_log_visit">c:geo brakuje informacji aby dodać wpis wizyty. Proszę spróbuj przez szczegóły skrzynki.</string> - <string name="err_init_cleared">Przepraszam, c:geo nie może skasować danych logowania.</string> - <string name="err_download_fail">Przepraszam, c:geo nie może załadować skrzynki, ponieważ </string> - <string name="err_list_load_fail">Przepraszam, c:geo nie może załadować listy skrzynek.</string> - <string name="err_store_failed">Przepraszam, c:geo nie może zapisać skrzynki.</string> - <string name="err_refresh_failed">Przepraszam, c:geo nie może zaktualizować skrzynki.</string> - <string name="err_dwld_details_failed">Przepraszam, c:geo nie może załadować szczegółów skrzynki.</string> - <string name="err_load_descr_failed">Przepraszam, c:geo nie może załadować opisu.</string> + <string name="err_detail_no_map_static">c:geo nie znalazł map statycznych dla tej skrzynki.</string> + <string name="err_detail_not_load_map_static">c:geo nie mógł załadować map statycznych.</string> + <string name="err_detail_still_working">Wciąż pracuję nad innym zadaniem.</string> + <string name="err_watchlist_still_managing">Wciąż pracuję nad listą obserwowanych.</string> + <string name="err_watchlist_failed">Zmiana listy obserwowanych zakończona niepowodzeniem.</string> + <string name="err_application_no">c:geo nie znalazł żadnych odpowiednich programów.</string> + <string name="err_auth_initialize">c:geo nie może rozpocząć autoryzacji.</string> + <string name="err_auth_process">Autoryzacja zakończona niepowodzeniem.</string> + <string name="err_cannot_log_visit">c:geo nie może dodać wpisu wizyty. Proszę spróbuj przez szczegóły skrzynki.</string> + <string name="err_init_cleared">c:geo nie może usunąć danych logowania.</string> + <string name="err_download_fail">c:geo nie może załadować skrzynek.</string> + <string name="err_dwld_details_failed">c:geo nie może załadować szczegółów skrzynki.</string> + <string name="err_load_descr_failed">c:geo nie może załadować opisu.</string> <string name="err_location_unknown">c:geo nie zna lokalizacji skrzynki.</string> <string name="err_missing_device_name">Proszę podać nazwę urządzenia przed zarejestrowaniem.</string> - <string name="err_tb_display">"Przepraszam, c:geo nie może pokazać przedmiotów podróżnych. Czy to rzeczywiście jest przedmiot podróżny?</string> - <string name="err_tb_details_open">Przepraszam, c:geo nie może otworzyć szczegółów przedmiotu podróżnego.</string> - <string name="err_tb_details_download">Przepraszam, c:geo nie może otworzyć szczegółów przedmiotu podróżnego, ponieważ</string> - <string name="err_tb_forgot">Przepraszam, c:geo zapomiał jaki przedmiot podróżny chciałeś.</string> - <string name="err_tb_forgot_saw">Przepraszam, c:geo zapomiał jaki przedmiot podróżny widziałeś.</string> - <string name="err_tb_find">Przepraszam, c:geo nie może znaleźć przedmiotu podróżnego.</string> - <string name="err_tb_find_that">Przepraszam, c:geo nie może znaleźć tego przedmiotu podróżnego.</string> - - <string name="err_waypoint_cache_unknown">Przepraszam, c:geo nie wie do jakiej skrzynki chcesz dodać punkt nawigacji.</string> - <string name="err_waypoint_unknown">Przepraszam, c:geo zapomiał jaki punkt nawigacyjny chciałeś obejrzeć.</string> - <string name="err_waypoint_add_failed">Przepraszam, c:geo nie może dodać punktu nawigacyjnego.</string> - <string name="err_waypoint_load_failed">Przepraszam, c:geo nie może załadować punktu nawigacyjnego.</string> - <string name="err_waypoint_delete_failed">Przepraszam, c:geo nie może skasować punktu nawigacyjnego.</string> - <string name="err_point_unknown_position">Przepraszam, c:geo nie może określić twojej lokalizacji.</string> + <string name="err_tb_display">c:geo nie może pokazać przedmiotów podróżnych. Czy to naprawdę jest przedmiot podróżny?</string> + <string name="err_tb_details_open">c:geo nie może otworzyć szczegółów przedmiotu podróżnego.</string> + <string name="err_tb_forgot_saw">c:geo zapomiał, który przedmiot podróżny widziałeś.</string> + <string name="err_tb_find">c:geo nie może znaleźć przedmiotu podróżnego.</string> + <string name="err_tb_find_that">c:geo nie może znaleźć tego przedmiotu podróżnego.</string> + + <string name="err_waypoint_cache_unknown">c:geo nie wie, do której skrzynki chcesz dodać punkt nawigacji.</string> + <string name="err_waypoint_add_failed">c:geo nie może dodać punktu nawigacyjnego.</string> + <string name="err_point_unknown_position">c:geo nie może określić Twojej lokalizacji.</string> <string name="err_point_no_position_given_title">Informacje wymagane</string> - <string name="err_point_no_position_given">Wypełnij co najmniej szerokość i długość geograficzną lub odległość i namiar. Można również wypełnić wszystkie cztery pola.</string> + <string name="err_point_no_position_given">Wypełnij co najmniej szerokość i długość geograficzną lub odległość i namiar. Możesz również wypełnić wszystkie cztery pola.</string> <string name="err_point_curr_position_unavailable">c:geo nadal nie zna aktualnych współrzędnych. Proszę chwilę poczekać…</string> <string name="err_point_bear_and_dist_title">Potrzebujesz pomocy?</string> <string name="err_point_bear_and_dist">Wypełnij zarówno namiar i odległość. Biorąc kąt od 0 do 360 stopni w stosunku do północy. Odległość z lub bez jednostki.</string> - <string name="err_point_location_error">Przepraszam, c:geo nie może rozpoznać lokalizacji punktu nawigacyjnego.</string> - - <string name="err_log_load_data">Przepraszam, c:geo nie może załadować dane wymagane do zalogowania wizyty.</string> - <string name="err_log_load_data_again">Przepraszam, c:geo nie może załadować dane wymagane do zalogowania wizyty. Próbuję ponownie.</string> - <string name="err_log_load_data_still">Nadal trwa ładowanie danych wymaganych do wpisu w dzienniku. Proszę czekać trochę dłużej.</string> - <string name="err_log_failed_server">Przepraszam, c:geo nie może wysłać wpisu ponieważ serwer nie odpowiada.</string> - <string name="err_log_post_failed">Przepraszam, c:geo nie mógł dodać wpisu do dziennika.</string> + <string name="err_point_location_error">c:geo nie może otrzymać lokalizacji punktu nawigacyjnego.</string> - <string name="err_search_address_no_match">Przepraszam, c:geo nie znalazł pasującego miejsca.</string> - <string name="err_search_address_forgot">Przepraszam, c:geo zapomiał jaki adres szukałeś.</string> - <string name="err_parse_lat">Przepraszam, c:geo nie może obliczyć szerokości geograficznej.</string> - <string name="err_parse_lon">Przepraszam, c:geo nie może obliczyć długości geograficznej.</string> - <string name="err_parse_dist">Przepraszam, c:geo nie może obliczyć odległości.</string> + <string name="err_log_load_data">c:geo nie może załadować danych wymaganych do wpisania wizyty.</string> + <string name="err_log_load_data_again">c:geo nie może załadować danych wymaganych do wpisania wizyty. Próbuję ponownie.</string> + <string name="err_log_load_data_still">Nadal trwa ładowanie danych wymaganych do wpisu w dzienniku. Proszę czekać…</string> + <string name="err_log_failed_server">c:geo nie może dokonać wpisu ponieważ serwer nie odpowiada.</string> + <string name="err_log_post_failed">Wygląda na to, że Twój wpis nie został zapisany. Proszę sprawdź na Geocaching.com.</string> - <string name="err_fieldnotes_export_failed">Eksportowanie notatek terenowych nieudane.</string> + <string name="err_search_address_forgot">c:geo zapomniał adresu, którego szukałeś.</string> + <string name="err_parse_lat">c:geo nie może obliczyć szerokości geograficznej.</string> + <string name="err_parse_lon">c:geo nie może obliczyć długości geograficznej.</string> + <string name="err_parse_dist">c:geo nie może obliczyć odległości.</string> + <string name="err_parse_lat_lon">c:geo nie może obliczyć szerokości lub długości geograficznej.</string> <string name="warn_save_nothing">Nie ma nic do zapisania.</string> - <string name="warn_no_cache_coord">Nie ma skrzynek z współrzędnymi GPS.</string> - <string name="warn_no_coordinates">Nie podane współrzędne.</string> - <string name="warn_no_keyword">Nie podane słowo kluczowe.</string> - <string name="warn_no_username">Nie podana nazwa użytkownika.</string> + <string name="warn_no_cache_coord">Brak skrzynek z współrzędnymi.</string> + <string name="warn_no_coordinates">Brak współrzędnych.</string> + <string name="warn_no_keyword">Brak słowa kluczowego.</string> + <string name="warn_no_username">Brak nazwy użytkownika.</string> <string name="warn_search_help_title">Potrzebujesz pomocy?</string> <string name="warn_search_help_address">Wpisz adres lub nazwę, np. adres ulicy \"ul. Grunwaldzka, Gdańsk, Polska\", nazwę miasta \"Koszalin\" lub po prostu nazwę jak \"Łazienki Królewskie\".</string> - <string name="warn_search_help_gccode">Wpisz kod GC. Na przykład \"GC1VCAZ\".</string> - <string name="warn_search_help_keyword">Wpisz jakieś słowo, które może być gdzieś w nazwie skrytki którą chcesz znaleźć.</string> + <string name="warn_search_help_gccode">Wpisz kod GC skrzynki. Na przykład \"GC1VCAZ\".</string> + <string name="warn_search_help_keyword">Wpisz pełną nazwę skrzynki lub jej część. Na przykład \"Rysy\".</string> <string name="warn_search_help_user">Wpisz nazwę użytkownika serwisu Geocaching.com.</string> <string name="warn_search_help_tb">Wpisz kod przedmiotu podróżnego. Na przykład \"TB29QMZ\".</string> - <string name="warn_log_text_fill">Proszę wypełnić jakimś tekstem.</string> + <string name="warn_log_text_fill">Proszę uzupełnij tekst wpisu.</string> + <string name="warn_load_images">c:geo nie był w stanie załadować obrazków.</string> + <string name="warn_invalid_mapfile">Wybrany plik mapy nie jest poprawnym plikiem mapsforge wersji 0.3.0.\nMapy offline są niedostępne.</string> + <string name="warn_deprecated_mapfile">Używasz przestarzałego pliku mapy w wersji 0.2.4.\nRozważ przejście na wersję mapy 0.3.0.\nNiedługo c:geo przestanie wspierać wersję 0.2.4.</string> + <string name="warn_nonexistant_mapfile">Wybrany plik z mapą nie istnieje.\nMapy offline są niedostępne.</string> + <string name="warn_rendertheme_missing">Nie znaleziono tytułu mapy.</string> - <string name="info_log_posted">Wpis został dodany.</string> + <string name="info_log_posted">Wpis został wysłany.</string> <string name="info_log_saved">Wpis został zapisany.</string> - <string name="info_log_cleared">Wpis został skasowany.</string> + <string name="info_log_cleared">Wpis został usunięty.</string> <string name="info_log_type_changed">Rodzaj wpisu w dzienniku został zmieniony!</string> - - <string name="info_fieldnotes_exported_to">Notatki terenowe eksportowane do</string> + + <string name="info_storing_static_maps">Próbuję zapisać mapy statyczne</string> <!-- location service --> <string name="loc_last">Ostatnia pozycja</string> @@ -214,30 +226,34 @@ <string name="loc_sat">Sat</string> <string name="loc_trying">Próba lokalizacji</string> <string name="loc_no_addr">Nieznany adres</string> + <string name="loc_gps_disabled">GPS wyłączony</string> <!-- standard menu --> <string name="menu_about">O c:geo</string> - <string name="menu_helpers">Przydatne Apps</string> + <string name="menu_helpers">Przydatne programy</string> <string name="menu_settings">Ustawienia</string> <string name="menu_history">Historia</string> <string name="menu_filter">Filter</string> + <string name="menu_scan_geo">Zeskanuj geokod</string> <!-- main screen --> - <string name="live_map_button">Mapka</string> + <string name="live_map_button">Mapa Live</string> <string name="caches_nearby_button">Najbliższe</string> <string name="advanced_search_button">Szukaj</string> <string name="stored_caches_button">Zapisane</string> - <string name="any_button">Wszędzie</string> + <string name="any_button">Gdziekolwiek</string> + <string name="unknown_scan">c:geo nie znalazł żadnego GC-kodu w wynikach skanowania.</string> <!-- caches --> - <string name="caches_no_cache">Nie ma skrzynki</string> + <string name="caches_no_cache">Brak skrzynki</string> <string name="caches_more_caches">Więcej skrzynek</string> <string name="caches_more_caches_no">Nie ma więcej skrzynek</string> <string name="caches_more_caches_loading">Ładuję skrzynki…</string> - <string name="caches_downloading">Ładuję skrzynki…\nSzacowany czas: </string> - <string name="caches_eta_ltm">Mniej niż minutę</string> + <string name="caches_downloading">Pobieram skrzynki…\nSzacowany czas: </string> + <string name="caches_eta_ltm">Mniej niż minuta</string> <plurals name="caches_eta_mins"> <item quantity="one">minuta</item> + <item quantity="two">minuty</item> <item quantity="other">minut</item> </plurals> <string name="caches_store_offline">Zapisz offline</string> @@ -249,128 +265,179 @@ <string name="caches_sort_distance">odległości</string> <string name="caches_sort_difficulty">trudności</string> <string name="caches_sort_terrain">terenu</string> - <string name="caches_sort_size">wielkości</string> + <string name="caches_sort_size">rozmiaru</string> <string name="caches_sort_favorites">popularności</string> <string name="caches_sort_name">nazwy</string> <string name="caches_sort_gccode">GC-kodu</string> <string name="caches_sort_rating">oceny</string> - <string name="caches_sort_vote">głosów (twoja ocena)</string> - <string name="caches_sort_inventory">ilości w inwentarzu</string> - <string name="caches_sort_date_hidden">daty</string> + <string name="caches_sort_vote">głosów (Twoja ocena)</string> + <string name="caches_sort_inventory">liczebności inwentarza</string> + <string name="caches_sort_date_hidden">daty ukrycia</string> + <string name="caches_sort_date_logged">daty znalezienia</string> + <string name="caches_sort_finds">ile razy znaleziona</string> + <string name="caches_sort_state">stanu</string> + <string name="caches_sort_storage">daty zapisania w urządzeniu</string> <string name="caches_select_mode">Tryb wyboru</string> <string name="caches_select_mode_exit">Wyjście z trybu wyboru</string> <string name="caches_select_invert">Odwróć zaznaczenie</string> <string name="caches_nearby">Najbliższe</string> - <string name="caches_manage">Zarządzać</string> - <string name="caches_drop_selected">Wybrane skasować</string> - <string name="caches_drop_selected_ask">Czy chcesz usunąć wybrane skrzynki z pamięci?</string> - <string name="caches_drop_all">Skasuj wszystkie</string> - <string name="caches_drop_all_ask">Czy chcesz usunąc wszystkie skrzynki z pamięci?</string> - <string name="caches_drop_stored">Skasuj zapisane</string> + <string name="caches_manage">Zarządzaj</string> + <string name="caches_drop_selected">Usuń wybrane</string> + <string name="caches_drop_selected_ask">Czy na pewno chcesz usunąć wybrane skrzynki z pamięci?</string> + <string name="caches_drop_all">Usuń wszystkie</string> + <string name="caches_drop_all_ask">Czy na pewno chcesz usunąć wszystkie skrzynki z pamięci?</string> + <string name="caches_drop_stored">Usuń zapisane</string> <string name="caches_drop_progress">Usuwanie skrzynek</string> + <string name="caches_drop_all_and_list">Usuń wszystkie skrzynki i listę</string> + <string name="caches_delete_events">Usuń minione wydarzenia</string> <string name="caches_refresh_selected">Odśwież wybrane</string> <string name="caches_refresh_all">Odśwież wszystkie</string> <string name="caches_move_selected">Przenieś zaznaczone</string> <string name="caches_move_all">Przenieś wszystkie</string> <string name="caches_map_locus">Locus</string> + <string name="caches_map_locus_export">Eksportuj do Locus</string> <string name="caches_recaptcha_title">reCAPTCHA</string> - <string name="caches_recaptcha_explanation">Proszę, napisz tekst z obrazka. Ważne to jest, aby można było pobrać współrzędne do skrzynek. To jest opcjonalne i może być wyłączone w ustawieniach.</string> + <string name="caches_recaptcha_explanation">Proszę, napisz tekst z obrazka. To ważne aby pobrać współrzędne skrzynek. Jest opcjonalne i może być wyłączone w Ustawieniach.</string> <string name="caches_recaptcha_hint">Tekst z obrazka</string> <string name="caches_recaptcha_continue">Kontynuuj</string> - <string name="caches_filter">Filter</string> - <string name="caches_filter_title">Filter według</string> - <string name="caches_filter_size">wielkości</string> + <string name="caches_filter">Filtr</string> + <string name="caches_filter_title">Filtruj według</string> + <string name="caches_filter_size">rozmiaru</string> <string name="caches_filter_type">typu</string> <string name="caches_filter_track">z przedmiotmi podróżnymi</string> - <string name="caches_filter_clear">wykasój filter</string> - <string name="caches_filter_size_title">Wybierz wielkość</string> - <string name="caches_filter_type_title">Wybierz typ</string> - <string name="caches_exporting_fieldnote">Eksportuj jako notatki terenowe…</string> - <string name="caches_removing_from_history">Kasuję z historii…</string> + <string name="caches_filter_clear">usuń filtr</string> + <string name="caches_removing_from_history">Usuwam z Historii…</string> <!-- caches lists --> <string name="list_menu">Lista</string> <string name="list_menu_create">Utwórz nową listę</string> + <string name="list_menu_all_lists">Wszystkie skrzynki</string> <string name="list_menu_drop">Usuń aktualną listę</string> - <string name="list_title">Wybierz listę</string> <string name="list_menu_change">Zmień listę</string> + <string name="list_menu_rename">Zmień nazwę aktualnej listy</string> + <string name="list_title">Wybierz listę</string> <string name="list_inbox">Zapisane</string> + <string name="list_all_lists">Wszystkie skrzynki</string> <string name="list_dialog_create_title">Nowa lista</string> - <string name="list_dialog_create">Utworzyć</string> - <string name="list_dialog_cancel">Anulować</string> + <string name="list_dialog_create">Utwórz</string> + <string name="list_dialog_cancel">Anuluj</string> <string name="list_dialog_create_ok">Nowa lista została utworzona</string> - <string name="list_dialog_create_err">c:geo nie udało się utworzyć nowej listy</string> + <string name="list_dialog_create_err">c:geo nie mógł utworzyć nowej listy</string> <string name="list_dialog_remove_title">Usuń listę</string> - <string name="list_dialog_remove_description">Chcesz usunąć aktualną listę skrzynek? Wszystkie skrzynki na tej liście zostaną przeniesione do listy \"Zapisane\".</string> + <string name="list_dialog_remove_description">Czy na pewno chcesz usunąć aktualną listę skrzynek? Wszystkie skrzynki na tej liście zostaną przeniesione do listy \"Zapisane\".</string> <string name="list_dialog_remove">Usuń</string> <string name="list_dialog_remove_ok">Lista została usunięta</string> - <string name="list_dialog_remove_err">c:geo nie udało się usunąć obecną listę</string> + <string name="list_dialog_remove_err">c:geo nie mógł usunąć aktualnej listy</string> + <string name="list_dialog_rename_title">Zmień nazwę listy</string> + <string name="list_dialog_rename">Zmień nazwę</string> <!-- about --> + <string name="about_version">Wersja</string> <string name="about_changelog">Zmiany</string> - <string name="about_donate">Wspomóc</string> + <string name="about_donate">Podaruj</string> <string name="about_detail">Szczegóły</string> <string name="about_donation_more">Darowizna dla\nprogramisty</string> <string name="about_contributors">Współpracownicy</string> <!-- init --> <string name="init_geocaching">Geocaching.com</string> + <string name="init_oc">opencaching.de</string> + <string name="init_oc_activate">Aktywuj opencaching.de na mapie Live i w wyszukiwaniu</string> + <string name="init_oc_username_description">Wpisz swoją nazwę użytkownika opencaching.de w celu umożliwienia zaznaczania znalezionych przez Ciebie skrzynek.</string> + <string name="init_oc_username">Wpisz swoją nazwę użytkownika</string> <string name="init_gcvote">GCvote.com</string> <string name="init_twitter">Twitter</string> <string name="init_username">Nazwa użytkownika</string> <string name="init_password">Hasło</string> <string name="init_passvote">Hasło</string> - <string name="init_login">Sprawdź Logowanie</string> - <string name="init_login_popup">Logowanie</string> - <string name="init_login_popup_working">Logowanie w Geocaching.com…</string> - <string name="init_login_popup_ok">Login ok.</string> - <string name="init_login_popup_failed">Logowanie nie powiodło się.</string> + <string name="init_login">Sprawdź i zapisz nazwę użytkownika</string> + <string name="init_login_popup">Nazwa użytkownika</string> + <string name="init_login_popup_working">Logowanie…</string> + <string name="init_login_popup_ok">Nazwa użytkownika OK</string> + <string name="init_login_popup_failed">Logowanie nie powiodło się</string> <string name="init_login_popup_failed_reason">Logowanie nie powiodło się, ponieważ </string> <string name="init_twitter_authorize">Autoryzacja c:geo</string> - <string name="init_twitter_publish">Publikowanie stanu, gdy znaleziono skrzynkę</string> - <string name="init_signature">Sygnatura</string> + <string name="init_twitter_publish">Publikuj stan w momencie odnalezienia skrzynki</string> + <string name="init_signature">Podpis</string> <string name="init_signature_help_button">Pomoc</string> - <string name="init_signature_help_title">Sygnatura, porady i wskazówki</string> - <string name="init_signature_help_text">Wprowadź swoją sygnaturę która będzie używana przy wpisie do dziennika.\nSpecjalne kody, które mogą być stosowane są: [DATE] , [TIME], [USER] & [NUMBER].</string> - <string name="init_signature_template_button">Wstaw szablonę</string> + <string name="init_signature_help_title">Podpis - porady i wskazówki</string> + <string name="init_signature_help_text">Wprowadź Twój podpis, który będzie używany przy wpisie do dziennika.\nWyrażenia specjalne, które mogą być użyte to: [DATE] , [TIME], [DATETIME], [USER] & [NUMBER].\nBędą one zastępowane w momencie wstawiania podpisu.</string> + <string name="init_signature_template_button">Wstaw szablon</string> <string name="init_signature_template_date">Data</string> <string name="init_signature_template_time">Czas</string> - <string name="init_signature_template_user">Użytkownki</string> + <string name="init_signature_template_datetime">Data & Czas</string> + <string name="init_signature_template_user">Użytkownik</string> <string name="init_signature_template_number">Numer</string> + <string name="init_signature_template_owner">Właściciel</string> + <string name="init_details">Szczegóły skrzynki</string> + <string name="init_ratingwanted">Załaduj ocenę skrzynki z GCvote.com</string> + <string name="init_elevationwanted">Załaduj dane o ukształtowaniu terenu</string> + <string name="init_friendlogswanted">Załaduj dodatkowy dziennik dla wpisów od przyjaciół</string> + <string name="init_openlastdetailspage">Otwórz szczegóły ostatnio używanej strony</string> + <string name="init_autoload">Automatyczne ładowanie długich opisów</string> <string name="init_other">Inne opcje</string> <string name="init_skin">Light skin\n(wymaga restartu)</string> - <string name="init_address">Pokaż adres na ekranie głównym</string> - <string name="init_captcha">Pokaż CAPTCHA w razie potrzeby</string> + <string name="init_address">Pokaż adres zamiast współrzędnych na ekranie głównym</string> + <string name="init_captcha">Pokaż CAPTCHA w razie potrzeby (tylko użytkownicy Basic)</string> <string name="init_useenglish">Użyj języka angielskiego wewnątrz c:geo\n(wymaga restartu)</string> <string name="init_exclude">Wyklucz własne lub już znalezione skrzynki</string> + <string name="init_showwaypoints">Pokaż punkty nawigacji na mapie Live</string> + <string name="init_showwaypoint_description">Jeśli mniej niż podana liczba skrzynek wyświetlana jest na mapie, ich punkty nawigacji są dodatkowo wyświetlane.</string> <string name="init_disabled">Wyklucz tymczasowo niedostępne skrzynki</string> - <string name="init_offline">Zapisuj mampki do użytku offline</string> + <string name="init_offline">Zapisuj mapy statyczne skrzynek do użytku offline</string> + <string name="init_offline_wp">Zapisuj mapy statyczne punktów nawigacji do użytku offline</string> <string name="init_save_log_img">Zapisz zdjęcia z wpisów</string> <string name="init_units">Używaj angielskich jednostek miary\n(mile)</string> - <string name="init_nav">Używaj Google Navigation</string> - <string name="init_autoload">Długie opisy automatycznie ładować</string> - <string name="init_log_offline">Podczas logowania, zawsze logój offline (nie pokazój ekranu logowania online, nie wysyłaj logu online)</string> - <string name="init_livelist">Pokazuj na liście kierunek do skrzynek</string> + <string name="init_log_offline">Włącz logowanie offline\n(Nie pokazuj ekranu logowania online, nie wysyłaj logu online)</string> + <string name="init_livelist">Pokazuj kierunek do skrzynek na liście</string> <string name="init_altitude">Korekta wysokości</string> - <string name="init_altitude_description">Jeśli GPS podaje tobie złą wysokość, możesz skorygować z liczbą dodatnią lub ujemną. Korekta jest zawsze w metrach.</string> - <string name="init_clear">Skasuj login</string> - <string name="init_cleared">c:geo skasował dane logowania.</string> + <string name="init_altitude_description">Jeśli GPS podaje Tobie złą wysokość, możesz skorygować ją liczbą dodatnią lub ujemną. Poprawka musi być zawsze wyrażona w metrach.</string> + <string name="init_clear">Usuń nazwę użytkownika</string> + <string name="init_cleared">c:geo usunął dane logowania.</string> <string name="init_backup">Kopia zapasowa</string> - <string name="init_backup_backup">Kopiuj</string> - <string name="init_backup_note">Zwróć uwagę, że ta opcja wykonuje tylko kopie/odzyskiwanie bazy danych, zawierającej skrzynki i punkty nawigacyjne, a nie ustawienia. Twoje dane logowania (hasła) nie opuszczą tej aplikacji.</string> + <string name="init_backup_backup">Wykonaj kopię zapasową</string> + <string name="init_backup_running">Tworzę kopię zapasową bazy skrzynek…</string> + <string name="init_backup_note">Zwróć uwagę, że ta opcja wykonuje tylko kopię/odzyskiwanie bazy danych zawierającej skrzynki i punkty nawigacyjne, ale nie Twoich ustawień. Twoje dane logowania (nazwa użytkownika i hasło) nigdy nie opuszczą tego programu.</string> <string name="init_backup_restore">Przywróć</string> <string name="init_backup_success">Baza danych c:geo została pomyślnie skopiowana do pliku</string> - <string name="init_backup_failed">Kopia zapasowa bazy danych c:geo nie powiodła się.</string> - <string name="init_restore_success">Przywrócenie zakończone.</string> - <string name="init_restore_failed">Przywrócenie nie powiodło się.</string> + <string name="init_backup_failed">Tworzenie kopii zapasowej bazy danych c:geo nie powiodło się.</string> + <string name="init_backup_unnecessary">Baza danych jest pusta, tworzenie kopii zapasowej nie jest potrzebne.</string> + <string name="init_restore_success">Odzyskiwanie zakończone.</string> + <string name="init_restore_failed">Odzyskiwanie nie powiodło się.</string> + <string name="init_restore_running">Odzyskiwanie bazy skrzynek…</string> + <string name="init_restore_confirm">Baza danych jest pusta. Czy na pewno chcesz odzyskać bazę danych z kopii zapasowej?</string> <string name="init_backup_last">Kopia dostępna od</string> - <string name="init_backup_last_no">Nie ma plików z kopią zapasową.</string> + <string name="init_backup_last_no">Brak pliku z kopią zapasową.</string> <string name="init_mapsources">Źródła mapy</string> - <string name="init_mapsources_description">Tutaj można wybrać źródło mapy. Jako alternatywę do Google maps, są dostępne różne style OpenStreetMap, a nawet pliki offline z mapą (szczegóły znajdziesz tutaj: <a href="http://code.google.com/p/mapsforge/"> http://code.google.com/p/mapsforge/</a>).</string> + <string name="init_mapsources_description">Tutaj możesz wybrać źródło dla Twoich map. Jako alternatywa do map Google, dostępne są różne wersje OpenStreetMap, a nawet pliki offline z mapą (szczegóły znajdziesz tutaj: <a href="http://code.google.com/p/mapsforge/"> http://code.google.com/p/mapsforge/</a>).\nPonadto wspierane są wybieralne motywy dla map offline.</string> <string name="init_mapsource_select">Wybierz źródło mapy</string> - <string name="init_trackautovisit">Ustaw przedmioty podróżne automatycznie na \"wizytę\"</string> + <string name="init_map_directory_description">Katalog z mapami offline</string> + <string name="init_gpx_exportdir">Katalog do eksportu plików GPX</string> + <string name="init_gpx_importdir">Katalog do importu plików GPX</string> + <string name="init_gpx_exportdir_description">Tutaj możesz wybrać katalog do eksportu plików GPX.</string> + <string name="init_gpx_importdir_description">Tutaj możesz wybrać katalog do importu plików GPX.</string> + <string name="init_maptrail">Pokaż szlak na mapie</string> + <string name="init_share_after_export">Otwórz dzielone menu po eksporcie plików GPX</string> + <string name="init_trackautovisit">Ustaw przedmioty podróżne domyślnie na \"Odwiedzony\"</string> <string name="init_sigautoinsert">Wstaw podpis automatycznie</string> - <string name="init_loaddirectionimg">Załaduj obrazek kierunku w razie potrzeby</string> + <string name="init_loaddirectionimg">Załaduj obrazek kierunku w razie potrzeby (tylko użytkownicy Basic)</string> + <string name="init_default_navigation_tool">Domyślna nawigacja</string> + <string name="init_default_navigation_tool_description">Tutaj możesz wybrać preferowane narzędzie nawigacji.</string> + <string name="init_default_navigation_tool_select">Wybierz narzędzie</string> + <string name="init_default_navigation_tool_2_description">Tutaj możesz wybrać drugie preferowane narzędzie nawigacji. Jest aktywowane przez długie kliknięcie ikony nawigacji obok nazwy skrzynki.</string> + <string name="init_debug_title">Informacja o błędach</string> + <string name="init_debug_note">c:geo może generować ogromne ilości informacji o błędach. Podczas gdy te informacje są w ogólności nieprzydatne dla użytkowników c:geo, deweloperzy mogą potrzebować generować te informacje w celu analizy błędów. Możesz zaznaczyć pole poniżej i wysłać plik z logiem.</string> + <string name="init_debug">Generuj informację o błędach</string> + <string name="init_dbonsdcard_title">Położenie bazy danych</string> + <string name="init_dbonsdcard_note">Możesz przechowywać bazę danych c:geo na zewnętrznym urządzeniu. Dzięki temu zaoszczędzisz miejsce w pamięci wewnętrznej, ale wydajność może zmniejszyć się trochę, a c:geo nie będzie mógł pracować jeśli Twoja karta SD będzie niedostępna.</string> + <string name="init_dbonsdcard">Baza danych na zewnętrznym urządzeniu</string> + <string name="init_dbmove_dbmove">Przenoszę bazę danych</string> + <string name="init_dbmove_running">Przenoszę bazę danych</string> + <string name="init_dbmove_success">Baza danych została przeniesiona.</string> + <string name="init_dbmove_failed">Nie udało się przenieść bazy danych</string> + <string name="init_plain_logs">Wyświetlaj wpisy dziennika bez kolorów</string> + <string name="init_use_native_ua">Identyfikuj jako przeglądarka Android. Rozwiązuje problemy z logowaniem w niektórych sieciach.</string> + <string name="init_rendertheme_folder">Katalog z tematami map offline (opcja)</string> <!-- map sources --> <string name="map_source_google_map">Google: Mapa</string> @@ -379,40 +446,42 @@ <string name="map_source_osm_cyclemap">OSM: Cyclemap</string> <string name="map_source_osm_offline">OSM: Offline</string> - <string name="init_sendToCgeo">Send to c:geo</string> + <string name="init_sendToCgeo">Wyślij do c:geo</string> <string name="init_sendToCgeo_name">Nazwa urządzenia:</string> - <string name="init_sendToCgeo_description">Sent to c:geo pozwala tobie odbierać skrytki bezpośrednio ze strony geocaching za pomocą specjalnego plugin dla przeglądarki Firefox lub Chrome. Przed rejestracją prosimy o zapoznanie się z <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a>. Rejestracja jest tylko potrzebna, jeśli będziesz używać send2cgeo. C:geo będzie również działać bez rejestracji urządzenia.</string> - <string name="init_sendToCgeo_register">wniosek o rejestrację</string> - <string name="init_sendToCgeo_registering">Rejestruję twoje urządzenie do \"Send to c:geo\"…</string> - <string name="init_sendToCgeo_register_ok">Rejestracja udana. Kod PIN jest ####. Użyj go na c:geo stronie, aby dodać urządzenie do przeglądarki.</string> + <string name="init_sendToCgeo_description"><b>Wyślij do c:geo</b> pozwala Tobie odbierać skrzynki bezpośrednio ze strony geocaching.com za pomocą specjalnego pluginu do przeglądarki Firefox lub Chrome. Przed rejestracją prosimy o zapoznanie się z <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a>. Rejestracja jest wymagana tylko jeśli będziesz używać send2cgeo. c:geo będzie normalnie działał również bez rejestracji urządzenia.</string> + <string name="init_sendToCgeo_register">Poproś o rejestrację</string> + <string name="init_sendToCgeo_registering">Rejestruję Twoje urządzenie do \"Wyślij do c:geo\"…</string> + <string name="init_sendToCgeo_register_ok">Rejestracja udana. Kod PIN to ####. Użyj go na stronie c:geo, aby dodać urządzenie do przeglądarki.</string> <string name="init_sendToCgeo_register_fail">Rejestracja nie powiodła się.</string> + <string name="sendToCgeo_download_fail">c:geo nie może pobrać skrzynek. Brak połączenia z internetem lub narzędzie send2c:geo jest wyłączone.</string> + <string name="sendToCgeo_no_registration">c:geo nie może pobrać skrzynek. Rejestracja do send2c:geo wygasła. Proszę zarejestrować urządzenie w Ustawieniach.</string> <!-- auth --> <string name="auth_twitter">Twitter</string> <string name="auth_authorize">Autoryzacja c:geo</string> - <string name="auth_start">Startuję autoryzację</string> - <string name="auth_again">Startuję ponownie autoryzację</string> + <string name="auth_start">Rozpoczynam autoryzację</string> + <string name="auth_again">Rozpoczynam ponownie autoryzację</string> <string name="auth_pin_hint">PIN nadany przez Twitter</string> <string name="auth_finish">Gotowe</string> <string name="auth_dialog_wait">Czekam na Twitter…</string> - <string name="auth_dialog_pin_title">kod PIN</string> - <string name="auth_dialog_pin_message">Proszę wpisać kod PIN dostarczony przez stronę Twitter. To jest obowiązkowe do ukończenia zezwolenia.</string> + <string name="auth_dialog_pin_title">Kod PIN</string> + <string name="auth_dialog_pin_message">Proszę wpisać kod PIN dostarczony przez stronę Twitter. To jest obowiązkowe do ukończenia autoryzacji.</string> <string name="auth_dialog_completed">c:geo jest teraz upoważniony do postu na Twitter.</string> <!-- cache --> <plurals name="cache_counts"> - <item quantity="zero">Nie ma skrzynek</item> + <item quantity="zero">Brak skrzynek</item> <item quantity="one">Jedna skrzynka</item> - <item quantity="other">%1$d Skrzynki</item> + <item quantity="other">Liczba skrzynek: %1$d</item> </plurals> <string name="cache_offline">Offline</string> <string name="cache_offline_refresh">Odśwież</string> - <string name="cache_offline_drop">Skasuj</string> + <string name="cache_offline_drop">Usuń</string> <string name="cache_offline_store">Zapisz</string> <string name="cache_offline_stored">Zapisane w pamięci</string> <string name="cache_offline_not_ready">Nie jest gotowy\ndo użytku offline</string> <string name="cache_offline_time_about">około</string> - <string name="cache_offline_time_mins">minut</string> + <string name="cache_offline_time_mins">minut temu</string> <string name="cache_offline_time_mins_few">przed kilkoma minutami</string> <string name="cache_offline_time_hour">przed jedną godziną</string> <string name="cache_offline_time_hours">przed godzinami</string> @@ -421,97 +490,157 @@ <string name="cache_attributes">Atrybuty</string> <string name="cache_inventory">Inwentarz</string> <string name="cache_log_offline">Wpis offline</string> - <string name="cache_log_images_loading">Trwa ładowanie zdjęcia z wpisu…</string> - <string name="cache_log_images_title">zdjęcie z wpisu</string> - <string name="cache_log_image_default_title">zdjęcie</string> - <string name="cache_personal_note">osobista notatka</string> + <string name="cache_log_images_loading">Trwa ładowanie zdjęć z wpisu…</string> + <string name="cache_log_images_title">Zdjęcie z wpisu</string> + <string name="cache_log_image_default_title">Zdjęcie</string> + <string name="cache_personal_note">Notatka osobista</string> <string name="cache_description">Opis</string> <string name="cache_description_long">Długi opis</string> - <string name="cache_watchlist">Lista obserwowanych</string> - <string name="cache_watchlist_on">Ta skrzynka jest na twojej liscie obserwowanych.</string> - <string name="cache_watchlist_not_on">Ta skrzynka nie jest na twojej liscie obserwowanych.</string> - <string name="cache_watchlist_add">Obserwuj</string> - <string name="cache_watchlist_remove">Usuń z listy</string> + <string name="cache_description_table_note">Opis zawiera formatowanie w formie tabeli, które w celu poprawnego wyświetlania może wymagać odwiedzenia geocaching.com.</string> + <string name="cache_watchlist_on">Ta skrzynka jest na Twojej liście obserwowanych.</string> + <string name="cache_watchlist_not_on">Ta skrzynka nie jest na Twojej liście obserwowanych.</string> + <string name="cache_watchlist_add">Dodaj do listy obserwowanych</string> + <string name="cache_watchlist_remove">Usuń z listy obserwowanych</string> + <string name="cache_favpoint_on">Ta skrzynka jest na Twojej liście ulubionych.</string> + <string name="cache_favpoint_not_on">Ta skrzynka nie jest na Twojej liście ulubionych.</string> + <string name="cache_favpoint_add">Dodaj</string> + <string name="cache_favpoint_remove">Usuń</string> + <string name="cache_images">Zdjęcia</string> <string name="cache_waypoints">Punkty nawigacji</string> + <plurals name="waypoints"> + <item quantity="one">Jeden punkt nawigacji</item> + <item quantity="other">%d punktów nawigacji</item> + </plurals> <string name="cache_waypoints_add">Dodaj punkt nawigacji</string> <string name="cache_hint">Wskazówka</string> <string name="cache_logs">Dziennik</string> - <string name="cache_dialog_loading_details">Ładuje szczegóły skrzynki…</string> + <string name="cache_logsfriends">Dziennik (Przyjaciele)</string> + <string name="cache_dialog_loading_details">Ładuję szczegóły skrzynki…</string> + <string name="cache_dialog_loading_details_status_loadpage">Ładuję stronę</string> + <string name="cache_dialog_loading_details_status_details">Przetwarzam szczegóły</string> + <string name="cache_dialog_loading_details_status_spoilers">Ładuję zdjęcia spoiler</string> + <string name="cache_dialog_loading_details_status_logs">Ładuję wpisy</string> + <string name="cache_dialog_loading_details_status_waypoints">Przetwarzam punkty nawigacji</string> + <string name="cache_dialog_loading_details_status_gcvote">Ładuję GCVote</string> + <string name="cache_dialog_loading_details_status_elevation">Ładuję dane o ukształtowaniu terenu</string> + <string name="cache_dialog_loading_details_status_cache">Zapisuję dane</string> + <string name="cache_dialog_loading_details_status_render">Renderuję widok</string> <string name="cache_dialog_offline_save_title">Offline</string> - <string name="cache_dialog_offline_save_message">Zapisywanie skrzynek do trybu offline…</string> + <string name="cache_dialog_offline_save_message">Zapisuję skrzynkę do użytku offline…</string> <string name="cache_dialog_offline_drop_title">Offline</string> - <string name="cache_dialog_offline_drop_message">Kasuję skrzynkę z pamięci…</string> + <string name="cache_dialog_offline_drop_message">Usuwam skrzynkę z pamięci urządzenia…</string> <string name="cache_dialog_refresh_title">Odśwież</string> - <string name="cache_dialog_refresh_message">Aktualizuje szczegóły skrzynki…</string> + <string name="cache_dialog_refresh_message">Aktualizuję szczegóły skrzynki…</string> <string name="cache_dialog_watchlist_add_title">Lista obserwowanych</string> <string name="cache_dialog_watchlist_add_message">Dodaję skrzynkę do listy obserwowanych…</string> <string name="cache_dialog_watchlist_remove_title">Lista obserwowanych</string> <string name="cache_dialog_watchlist_remove_message">Usuwam skrzynkę z listy obserwowanych…</string> - <string name="cache_menu_navigate">Nawigować</string> - <string name="cache_menu_tbt">Zakręt po zakręcie</string> + <string name="cache_dialog_favourite_add_title">Ulubione</string> + <string name="cache_dialog_favourite_add_message">Dodaję skrzynkę do listy ulubionych…</string> + <string name="cache_dialog_favourite_remove_title">Ulubione</string> + <string name="cache_dialog_favourite_remove_message">Usuwam skrzynkę z listy ulubionych…</string> + <string name="cache_menu_navigate">Nawiguj</string> + <string name="cache_menu_navigation_drive">Nawigacja (jazda)</string> + <string name="cache_menu_navigation_walk">Nawigacja (pieszo)</string> + <string name="cache_menu_maps_directions">Kierunki map Google</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Pokaż na mapie</string> - <string name="cache_menu_map_static">Statyczna mapa</string> + <string name="cache_menu_map_static">Mapa statyczna</string> + <string name="cache_menu_download_map_static">Pobierz mapę statyczną</string> <string name="cache_menu_rmaps">Rmaps</string> <string name="cache_menu_map_ext">Pokaż na zewn. mapie</string> <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Otwórz w przeglądarce</string> - <string name="cache_menu_visit">Zaloguj wizytę</string> - <string name="cache_menu_visit_offline">Zaloguj wizytę offline</string> - <string name="cache_menu_spoilers">Zdjęcie spoiler</string> - <string name="cache_menu_around">Skrzynek w okręgu</string> - <string name="cache_menu_event">Wpisz do kalendarza</string> + <string name="cache_menu_visit">Wpisz wizytę</string> + <string name="cache_menu_visit_offline">Wpisz wizytę offline</string> + <string name="cache_menu_spoilers">Zdjęcia spoiler</string> + <string name="cache_menu_around">Skrzynki w okręgu</string> + <string name="cache_menu_set_as_cache_coords">Ustaw jako współrzędne skrzynki</string> + <string name="cache_menu_upload_wpt_to_gc_com">Ustaw jako współrzędne skrzynki i wyślij punkt nawigacji do Geocaching.com</string> + <string name="cache_menu_event">Dodaj do kalendarza</string> <string name="cache_menu_details">Szczegóły</string> <string name="cache_menu_share">Podziel się skrzynką</string> - <string name="cache_menu_move_list">Przesuń do innej listy</string> + <string name="cache_menu_move_list">Przenieś do innej listy</string> <string name="cache_menu_gcc">GCC</string> <string name="cache_menu_whereyougo">WhereYouGo</string> + <string name="cache_menu_oruxmaps">OruxMaps</string> + <string name="cache_menu_cachebeacon">Cache Beacon</string> <string name="cache_status">Status</string> <string name="cache_status_offline_log">Zapamiętany wpis</string> - <string name="cache_status_found">Znalezione</string> - <string name="cache_status_archived">Archiwum</string> - <string name="cache_status_disabled">Niedostępny</string> - <string name="cache_status_premium">Tylko dla premium użytkowników</string> + <string name="cache_status_found">Znaleziona</string> + <string name="cache_status_archived">Zarchiwizowana</string> + <string name="cache_status_disabled">Niedostępna</string> + <string name="cache_status_premium">Tylko dla użytkowników Premium</string> + <string name="cache_status_not_premium">Dostępna dla wszystkich użytkowników</string> <string name="cache_geocode">GC-kod</string> <string name="cache_name">Nazwa</string> <string name="cache_type">Typ</string> + <string name="cache_size">Rozmiar</string> <string name="cache_distance">Odległość</string> - <string name="cache_difficulty">Trudności</string> + <string name="cache_difficulty">Trudność</string> <string name="cache_terrain">Teren</string> <string name="cache_rating">Ocena</string> + <string name="cache_own_rating">Własna ocena</string> <string name="cache_rating_of">od</string> - <string name="cache_favourite">Ulubiony</string> + <string name="cache_favourite">Ulubiona</string> <string name="cache_owner">Właściciel</string> - <string name="cache_hidden">Schowano</string> + <string name="cache_hidden">Ukryta</string> <string name="cache_event">Data</string> - <string name="cache_location">Lokacja</string> + <string name="cache_location">Położenie</string> <string name="cache_coordinates">Współrzędne</string> - <string name="cache_spoiler_images_title">Zdjęcie spoiler</string> - <string name="cache_spoiler_images_loading">Ładuje zdjęcia spoiler…</string> - <string name="cache_log_types">Rodzaj logu</string> + <string name="cache_coordinates_original">Oryginalne współrzędne</string> + <string name="cache_spoiler_images_title">Zdjęcia spoiler</string> + <string name="cache_spoiler_images_loading">Ładuję zdjęcia spoiler…</string> + <string name="cache_images_title">Zdjęcia</string> + <string name="cache_images_loading">Ładuję zdjęcia…</string> + <string name="cache_log_types">Rodzaj wpisu</string> <string name="cache_coordinates_no">Ta skrzynka nie ma współrzędnych GPS.</string> - <string name="cache_export_fieldnote">Eksportuj jako notatka terenowa</string> - <string name="cache_clear_history">Wykasuj historię</string> + <string name="cache_clear_history">Usuń historię</string> <string name="cache_remove_from_history">Usuń z historii</string> - + <string name="cache_license">Licencja</string> + <string name="cache_image">Zdjęcie</string> + <string name="cache_image_open_file">Otwórz jako plik</string> + <string name="cache_image_open_browser">Otwórz w przeglądarce</string> + <string name="cache_share_field">Współdziel</string> + <string name="cache_time_full_hours"></string> + + <!-- editor dialog --> + <string name="editor_save">Zapisz</string> + <!-- file list base --> - <string name="file_searching_in">Szukam pliki\nw</string> - <string name="file_list_no_files">Przepraszam, c:geo nie znalazł odpowiednich plików.</string> - <string name="file_searching">Wyszukiwanie plików pasujących</string> + <string name="file_searching_in">Szukam plików\nw</string> + <string name="file_searching_sdcard_in">Nie znaleziono plików w domyślnych katalogach:\n%1$s\n\nPrzeszukiwanie całej karty SD:\n</string> + <string name="file_list_no_files">c:geo nie znalazł odpowiednich plików.</string> + <string name="file_searching">Wyszukiwanie pasujących plików</string> <string name="file_title_searching">Szukam</string> + <!-- simple_dir_chooser --> + <string name="simple_dir_chooser_title">Wybierz katalog</string> + <string name="simple_dir_chooser_current_path">Ścieżka:</string> + <!-- gpx --> + <string name="gpx_import_loading_caches">Ładuję skrzynki z pliku GPX</string> + <string name="gpx_import_loading_waypoints">Ładuję plik z punktami nawigacji</string> + <string name="gpx_import_store_static_maps">Zapisuję mapy statyczne</string> <string name="gpx_import_caches_imported">skrzynek importowanych</string> - <string name="gpx_import_loading_caches">Ładuje skrzynki z pliku .gpx</string> + <string name="gpx_import_static_maps_skipped">Pobieranie map statycznych wstrzymane</string> + <string name="gpx_import_title_static_maps">Zapis map statycznych</string> + <string name="gpx_import_title_reading_file">Czytanie pliku</string> <string name="gpx_import_title">Import GPX</string> - <string name="gpx_import_title_reading_file">Czytanie pliku</string> - <string name="gpx_import_title_caches_imported">Wynik</string> + <string name="gpx_import_title_caches_imported">Rezultat</string> + <string name="gpx_import_title_caches_import_failed">Import zakończony niepowodzeniem</string> + <string name="gpx_import_error_io">Nie mogę odczytać pliku</string> + <string name="gpx_import_error_parser">Zły format pliku</string> + <string name="gpx_import_error_unexpected">Nieoczekiwany błąd</string> + <string name="gpx_import_confirm">Czy na pewno chcesz zaimportować plik GPX do c:geo?</string> + <string name="gpx_import_canceled">Import pliku GPX został anulowany</string> + <string name="gpx_import_delete_title">Usuń plik</string> + <string name="gpx_import_delete_message">Czy na pewno chcesz usunąć %s?</string> <!-- map file select --> <string name="map_file_select_title">Wybierz plik z mapą</string> <!-- import --> - <string name="import_title">Import…</string> <string name="web_import_title">Import z internetu</string> <string name="web_import_waiting">Czekam na nowe skrzynki z internetu…</string> <string name="web_downloading">Ściąganie</string> @@ -522,20 +651,38 @@ <!-- waypoint --> <string name="waypoint">Punkt nawigacji</string> - <string name="waypoint_title">Punkt nawigacji</string> + <string name="waypoint_cache_coordinates">Współrzędne skrzynki</string> <string name="waypoint_custom">Zdefiniowane przez użytkownika</string> <string name="waypoint_my_coordinates">Moje współrzędne</string> - <string name="waypoint_bearing">Kierunek</string> + <string name="waypoint_bearing">Kierunek w °</string> <string name="waypoint_distance">Odległość</string> <string name="waypoint_name">Nazwa</string> <string name="waypoint_edit">Edytuj</string> - <string name="waypoint_delete">Skasuj</string> - <string name="waypoint_edit_title">Edytuj punkt nawigacyjny</string> - <string name="waypoint_add_title">Dodaj punkt nawigacyjny</string> + <string name="waypoint_delete">Usuń</string> + <string name="waypoint_edit_title">Edytuj punkt nawigacji</string> + <string name="waypoint_add_title">Dodaj punkt nawigacji</string> <string name="waypoint_note">Notatka</string> <string name="waypoint_save">Zapisz</string> - <string name="waypoint_loading">Ładuje punkt nawigacyjny…</string> - <string name="waypoint_unknown_coordinates">Współrzędne nieznane</string> + <string name="waypoint_loading">Ładuję punkt nawigacji…</string> + <string name="waypoint_do_not_touch_cache_coordinates">Współrzędne skrzynki bez zmian</string> + <string name="waypoint_set_as_cache_coords">Ustaw jako współrzędne skrzynki w c:geo</string> + <string name="waypoint_save_and_modify_on_website">Ustaw jako współrzędne skrzynki w c:geo i na stronie WWW</string> + <string name="waypoint_reset_cache_coords">Ustaw ponownie współrzędne skrzynki</string> + <string name="waypoint_coordinates_has_been_reset_on_website">Współrzędne skrzynki zostały ustawione ponownie na stronie WWW.</string> + <string name="waypoint_coordinates_being_reset_on_website">Ponowne ustawianie współrzędnych skrzynki na na stronie WWW…</string> + <string name="waypoint_reset_cache_coords_info">Opcje ponownego ustawiania współrzędnych</string> + <string name="waypoint_reset">Ponowne ustawianie</string> + <string name="waypoint_localy_reset_cache_coords">Ponowne ustawianie w c:geo</string> + <string name="waypoint_reset_local_and_remote_cache_coords">Ponowne ustawianie w c:geo i na stronie WWW</string> + <string name="waypoint_coordinates_couldnt_be_modified_on_website">Strona WWW nie wspiera zmiany współrzędnych skrzynki.</string> + <string name="waypoint_coordinates_upload_error">Wystąpił błąd podczas modyfikacji współrzędnych na stronie WWW.</string> + <string name="waypoint_coordinates_uploading_to_website">Wysyłanie współrzędnych %s do strony WWW.</string> + <string name="waypoint_coordinates_reseting_on_website">Powracanie do oryginalnych współrzędnych na stronie WWW.</string> + <string name="waypoint_coordinates_has_been_modified_on_website">Współrzędne skrzynki zostały zmienione na stronie WWW na: %s.</string> + <string name="waypoint_coordinates_has_been_set_as_cache_coordinates">Współrzędne skrzynki zostały zmieonone w c:geo na: %s.</string> + <string name="waypoint_done">Wykonane</string> + <string name="waypoint_duplicate">Duplikat</string> + <string name="waypoint_copy_of">Kopia</string> <string name="search_history">Historia</string> <string name="search_history_empty">Brak poprzednich celów</string> <string name="search_remove_destination">Cel usunięty</string> @@ -544,25 +691,45 @@ <string name="waypoint_coordinate_formats_plain">zwykłe</string> + <!-- distance units --> + <string name="unit_m">m</string> + <string name="unit_km">km</string> + <string name="unit_ft">stopy</string> + <string name="unit_yd">jardy</string> + <string name="unit_mi">mile</string> + <!-- visit --> - <string name="visit_tweet">Wyślij ten wpis też do Twitter</string> + <string name="visit_tweet">Wyślij informację do Twitter</string> <!-- map --> <string name="map_map">Mapa</string> - <string name="map_live">Live mapa</string> + <string name="map_live">Mapa Live</string> <string name="map_view_map">Widok mapy</string> + <string name="map_modes">Tryb mapy</string> <string name="map_trail_show">Pokaż szlak</string> <string name="map_trail_hide">Ukryj szlak</string> <string name="map_circles_show">Pokaż okręgi</string> - <string name="map_circles_hide">Ukryj okręki</string> + <string name="map_circles_hide">Ukryj okręgi</string> + <string name="map_theme_builtin">Domyślny</string> + <string name="map_theme_select">Wybierz temat mapy</string> <string name="map_live_enable">Włącz live</string> <string name="map_live_disable">Wyłącz live</string> - <string name="map_static_title">Statyczna mapa</string> - <string name="map_static_loading">Ładuje statyczną mapę…</string> - <string name="map_token_err">c:geo ma możliwość pobrania tylko częściowych danych, współrzędne GPS mogą być niedokładne.</string> + <string name="map_static_title">Mapa statyczna</string> + <string name="map_static_loading">Ładuję mapę statyczną…</string> + <string name="map_token_err">W związku z tym, że c:geo ma możliwość pobrania tylko częściowych danych, współrzędne GPS mogą być niedokładne.</string> + <string name="map_as_list">Pokaż w postaci listy</string> + <string name="map_strategy">Strategia</string> + <string name="map_strategy_title">Strategia mapy Live</string> + <string name="map_strategy_fastest">Najszybsza</string> + <string name="map_strategy_fast">Szybka</string> + <string name="map_strategy_auto">Zależna od prędkości</string> + <string name="map_strategy_detailed">Szczegółowa</string> + <string name="live_map_notification">Na nowej mapie live, współrzędnie nie zawsze muszą być dokładne. Prawdopodobne niedokładne współrzędne są zaznaczane za pomocą pomarańczowych okręgów.\nOtworzenie współrzędnych skrzynki lub zapisanie skrzynki do użytku offline zawsze używa precyzyjnych współrzędnych.\n\nWięcej informacji na temat wszystkich zmian można odnaleźć na stronie \"O c:geo\" wewnątrz programu.</string> + <string name="live_map_note_close">Zamknij</string> + <string name="live_map_note_dontshow">Nie pokazuj ponownie</string> <!-- search --> - <string name="search_bar_hint">Szukaj skrzynki</string> + <string name="search_bar_hint">Szukaj skrzynek</string> <string name="search_bar_desc">Skrzynki (GC-kod, słowo kluczowe), przedmioty podróżne (TB-kod)</string> <string name="search_coordinates">Współrzędne</string> <string name="search_coordinates_button">Szukaj według współrzędnych</string> @@ -572,20 +739,21 @@ <string name="search_gc_button">Szukaj według GC-kodu</string> <string name="search_kw">Słowa kluczowe</string> <string name="search_kw_prefill">Słowo kluczowe</string> - <string name="search_kw_button">Szukaj z słowem kluczowym</string> + <string name="search_kw_button">Szukaj wg słowa kluczowego</string> <string name="search_fbu">Znalezione przez użytkownika</string> <string name="search_fbu_prefill">Nazwa użytkownika</string> <string name="search_fbu_button">Szukaj według nazwy użytkownika</string> - <string name="search_hbu">Schowane przez użytkownika</string> + <string name="search_hbu">Schowane przez użytkowników</string> <string name="search_hbu_prefill">Właściciel</string> <string name="search_hbu_button">Szukaj według właściciela</string> <string name="search_tb">Przedmioty podróżne</string> - <string name="search_tb_hint">Numer przedmiotu podróżnego</string> + <string name="search_tb_hint">Identyfikacja przedmiotu podróżnego</string> <string name="search_tb_button">Szukaj przedmiotów podróżnych</string> <string name="search_destination">Cel</string> <string name="search_direction_rel">Z tej pozycji</string> <string name="search_address_started">Wyszukiwanie miejsc</string> <string name="search_address_result">Znalezione miejsca</string> + <string name="search_own_caches">Szukaj moich skrzynek</string> <!-- trackable --> <string name="trackable">Przedmiot podróżny</string> @@ -601,8 +769,8 @@ <string name="trackable_owner">Właściciel</string> <string name="trackable_spotted">Ostatnio widziany</string> <string name="trackable_spotted_in_cache">W</string> - <string name="trackable_spotted_at_user">U</string> - <string name="trackable_spotted_unknown_location">W nieznanym miejscu</string> + <string name="trackable_spotted_at_user">W rękach</string> + <string name="trackable_spotted_unknown_location">Nieznana lokalizacja</string> <string name="trackable_spotted_owner">U właściciela</string> <string name="trackable_origin">Pochodzenie</string> <string name="trackable_unknown">Nieznany</string> @@ -614,152 +782,181 @@ <string name="user_menu_title">O użytkowniku</string> <string name="user_menu_view_hidden">Schowane skrzynki</string> <string name="user_menu_view_found">Znalezione skrzynki</string> - <string name="user_menu_open_browser">Otwórz w przeglądarce</string> + <string name="user_menu_open_browser">Otwórz profil w przeglądarce</string> <!-- navigation --> <string name="navigation">Nawigacja</string> <string name="compass_title">Kompas</string> - <string name="use_gps">Użyj GPS</string> - <string name="use_compass">Użyj kompas</string> + <string name="use_gps">Użyj tylko GPS</string> + <string name="use_compass">Użyj GPS i kompasu</string> <string name="destination_select">Wybierz cel</string> - <string name="destination_set">Ustal cel</string> + <string name="destination_set">Ustaw cel</string> + <string name="navigation_direct_navigation">Bezpośrednia nawigacja</string> + <string name="navigation_target">Cel</string> <!-- license --> <string name="license">Licencja</string> - <string name="license_show">Pokaż licencje</string> - <string name="license_dismiss">Odmówić</string> + <string name="license_show">Pokaż licencję</string> + <string name="license_dismiss">Odmów</string> <!-- helpers --> <string name="helper_manual_title">Instrukcja obsługi</string> - <string name="helper_manual_description">Obszerny przewodnik do c:geo wraz z opisem wszystkich możliwości tej aplikacji (także ukryte).</string> + <string name="helper_manual_description">Obszerny przewodnik do c:geo wraz z opisem wszystkich możliwości tego programu (także ukrytych).</string> + <string name="helper_calendar_title">Dodatek Kalendarz c:geo</string> + <string name="helper_calendar_missing">Dodatek Kalendarz c:geo nie jest zainstalowany.</string> + <string name="helper_calendar_description">Umożliwia Tobie eksport skrzynek Wydarzenie do kalendarza w Twoim urządzeniu.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Bardzo dobra aplikacja do oglądania map online która pozwala na pobieranie ich bezpośrednio do trybu offline (map rastrowych tylko). Nagrywanie ścieżek, obsługa POI i wiele innych przydatnych funkcji.</string> + <string name="helper_locus_description">Bardzo dobra aplikacja do oglądania map online, która pozwala na pobieranie ich bezpośrednio do trybu offline (tylko mapy rastrowe). Pozwala także na zapisywanie ścieżek, obsługę POI oraz ma wiele innych przydatnych funkcji.</string> <string name="helper_gpsstatus_title">GPS Status</string> - <string name="helper_gpsstatus_description">Można wywołać radar bezpośrednio z aplikacji c:geo, oferuje on również wiele informacji związanych z GPS.</string> + <string name="helper_gpsstatus_description">Można wywołać radar bezpośrednio z aplikacji c:geo. Oferuje on również wiele informacji związanych z GPS.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> - <string name="helper_bluetoothgps_description">Umożliwia korzystanie z zewnętrznego odbiornika sygnału GPS, aby uzyskać lepszy odbiór, bardziej precyzyjnej lokalizacji i oszczędzać baterię komórki.</string> - + <string name="helper_bluetoothgps_description">Umożliwia korzystanie z zewnętrznego odbiornika sygnału GPS, w celu uzyskania bardziej precyzyjnej lokalizacji i zaoszczędzenia baterii telefonu.</string> + <string name="helper_barcode_title">Barcode Scanner</string> + <string name="helper_barcode_description">Istnieją skrypty i strony WWW, które umożliwiają wyświetlanie GC-kodu jako kodu kreskowego. Z tym programem c:geo może czytać te GC-kody bezpośrednio z ekranu Twojego komputera.</string> + + <!-- add-ons --> + <string name="addon_missing_title">Brakujący dodatek</string> + <string name="addon_download_prompt">Pobierz teraz z Google Play.</string> + + <!-- export --> + <string name="export">Eksport</string> + <string name="export_exportedto">wyeksportowano do</string> + <string name="export_failed">Eksport nie powiódł się</string> + <string name="export_fieldnotes">Notatki</string> + <string name="export_fieldnotes_info">Notatki będą wyeksportowane do /sdcard/field-notes z obecną datą i czasem jako nazwą pliku.</string> + <string name="export_fieldnotes_upload">Wyślij do geocaching.com</string> + <string name="export_fieldnotes_uploading">Wysyłanie…</string> + <string name="export_fieldnotes_upload_success">Wysyłanie do geocaching.com zakończone sukcesem</string> + <string name="export_fieldnotes_onlynew">Tylko od ostatniego eksportu</string> + <string name="export_fieldnotes_creating">Tworzenie notatek…</string> + <string name="export_gpx">GPX</string> + <string name="export_gpx_info">Plik GPX będzie wyeksportowany do %1$s z obecną datą i czasem jako nazwą pliku.</string> + <string name="export_gpx_to">Wyślij wyeksportowany GPX do</string> + + <!-- attribute unknown --> + <string name="attribute_unknown_yes">Nieznany atrybut obecny</string> + <string name="attribute_unknown_no">Nieznany atrybut nieobecny</string> <!-- attributes (permissions -> allowed, not allowed) --> <string name="attribute_dogs_yes">Psy dozwolone</string> - <string name="attribute_dogs_no">Psy nie dozwolone</string> + <string name="attribute_dogs_no">Psy niedozwolone</string> <string name="attribute_bicycles_yes">Rowery dozwolone</string> - <string name="attribute_bicycles_no">Rowery nie dozwolone</string> + <string name="attribute_bicycles_no">Rowery niedozwolone</string> <string name="attribute_motorcycles_yes">Motocykle dozwolone</string> - <string name="attribute_motorcycles_no">Motocykle nie dozwolone</string> + <string name="attribute_motorcycles_no">Motocykle niedozwolone</string> <string name="attribute_quads_yes">Quady dozwolone</string> - <string name="attribute_quads_no">Quady nie dozwolone</string> + <string name="attribute_quads_no">Quady niedozwolone</string> <string name="attribute_jeeps_yes">Samochody terenowe dozwolone</string> - <string name="attribute_jeeps_no">Samochody terenowe nie dozwolone</string> + <string name="attribute_jeeps_no">Samochody terenowe niedozwolone</string> <string name="attribute_snowmobiles_yes">Skutery śnieżne dozwolone</string> - <string name="attribute_snowmobiles_no">Skutery śnieżne nie dozwolone</string> + <string name="attribute_snowmobiles_no">Skutery śnieżne niedozwolone</string> <string name="attribute_horses_yes">Konie dozwolone</string> - <string name="attribute_horses_no">Konie nie dozwolone</string> + <string name="attribute_horses_no">Konie niedozwolone</string> <string name="attribute_campfires_yes">Ogniska dozwolone</string> - <string name="attribute_campfires_no">Ogniska nie dozwolone</string> + <string name="attribute_campfires_no">Ogniska niedozwolone</string> <string name="attribute_rv_yes">Truck Driver/RV dozwolone</string> - <string name="attribute_rv_no">Truck Driver/RV nie dozwolone</string> + <string name="attribute_rv_no">Truck Driver/RV niedozwolone</string> <!-- attributes (conditions -> yes, no) --> <string name="attribute_kids_yes">Polecane dla dzieci</string> - <string name="attribute_kids_no">Nie polecane dla dzieci</string> + <string name="attribute_kids_no">Niepolecane dla dzieci</string> <string name="attribute_onehour_yes">Odnalezienie zajmuje mniej niż godzinę</string> <string name="attribute_onehour_no">Odnalezienie zajmuje więcej niż godzinę</string> <string name="attribute_scenic_yes">Piękne widoki</string> <string name="attribute_scenic_no">Bez pięknych widoków</string> - <string name="attribute_hiking_yes">Nęcząca wędrówka</string> - <string name="attribute_hiking_no">Nie Męcząca wędrówka</string> + <string name="attribute_hiking_yes">Męcząca wędrówka</string> + <string name="attribute_hiking_no">Niemęcząca wędrówka</string> <string name="attribute_climbing_yes">Trudna wspinaczka</string> - <string name="attribute_climbing_no">Nie trudna wspinaczka</string> + <string name="attribute_climbing_no">Nietrudna wspinaczka</string> <string name="attribute_wading_yes">Może wymagać brodzenia</string> <string name="attribute_wading_no">Nie wymaga brodzenia</string> <string name="attribute_swimming_yes">Może wymagać pływania</string> <string name="attribute_swimming_no">Nie wymaga pływania</string> - <string name="attribute_available_yes">Dostępne przez cały czas</string> - <string name="attribute_available_no">Nie dostępne przez cały czas</string> - <string name="attribute_night_yes">Zalecane w nocy</string> - <string name="attribute_night_no">Nie zalecane w nocy</string> - <string name="attribute_winter_yes">Dostępne zimą</string> - <string name="attribute_winter_no">Nie dostępne zimą</string> + <string name="attribute_available_yes">Dostępna przez cały czas</string> + <string name="attribute_available_no">Niedostępna przez cały czas</string> + <string name="attribute_night_yes">Zalecana w nocy</string> + <string name="attribute_night_no">Niezalecana w nocy</string> + <string name="attribute_winter_yes">Dostępna zimą</string> + <string name="attribute_winter_no">Niedostępna zimą</string> <string name="attribute_stealth_yes">Wymagana konspiracja</string> - <string name="attribute_stealth_no">Konspiracja nie wymagana</string> - <string name="attribute_firstaid_yes">Wymagany serwis skrytki</string> - <string name="attribute_firstaid_no">Nie wymagany serwis skrytki</string> + <string name="attribute_stealth_no">Niewymagana konspiracja</string> + <string name="attribute_firstaid_yes">Wymagany serwis skrzynki</string> + <string name="attribute_firstaid_no">Niewymagany serwis skrzynki</string> <string name="attribute_cow_yes">Uważaj na zwierzęta gospodarskie</string> <string name="attribute_cow_no">Bez zwierzęt gospodarskich</string> - <string name="attribute_field_puzzle_yes">Field Puzzle</string> - <string name="attribute_field_puzzle_no">Bez Field Puzzle</string> - <string name="attribute_nightcache_yes">Nocna skrytka</string> - <string name="attribute_nightcache_no">Nie jest nocną skrytką</string> - <string name="attribute_parkngrab_yes">Drive-in</string> - <string name="attribute_parkngrab_no">Nie jest Drive-in</string> + <string name="attribute_field_puzzle_yes">Zagadka terenowa</string> + <string name="attribute_field_puzzle_no">Bez zagadki terenowej</string> + <string name="attribute_nightcache_yes">Skrytka nocna</string> + <string name="attribute_nightcache_no">Nie jest skrytką nocną</string> + <string name="attribute_parkngrab_yes">Park and grab</string> + <string name="attribute_parkngrab_no">Nie jest park and grab</string> <string name="attribute_abandonedbuilding_yes">Opuszczona budowla</string> - <string name="attribute_abandonedbuilding_no">Nie opuszczona budowla</string> + <string name="attribute_abandonedbuilding_no">Nieopuszczona budowla</string> <string name="attribute_hike_short_yes">Krótki spacer (mniej niż 1 km)</string> - <string name="attribute_hike_short_no">Nie krótki spacer</string> - <string name="attribute_hike_med_yes">Średni spacer (1–10 km)</string> - <string name="attribute_hike_med_no">Nie średni spacer</string> + <string name="attribute_hike_short_no">Spacer nie jest krótki</string> + <string name="attribute_hike_med_yes">Średni spacer (od 1 do 10 km)</string> + <string name="attribute_hike_med_no">Spacer nie jest średni</string> <string name="attribute_hike_long_yes">Długi spacer (więcej niż 10 km)</string> - <string name="attribute_hike_long_no">Nie długi spacer</string> + <string name="attribute_hike_long_no">Spacer nie jest długi</string> <string name="attribute_seasonal_yes">Dostęp sezonowy</string> <string name="attribute_seasonal_no">Bez dostępu sezonowego</string> <string name="attribute_touristok_yes">Przyjazna turystom</string> - <string name="attribute_touristok_no">Nie przyjazna turystom</string> - <string name="attribute_frontyard_yes">Prywatny teren</string> - <string name="attribute_frontyard_no">Nie prywatny teren</string> + <string name="attribute_touristok_no">Nieprzyjazna turystom</string> + <string name="attribute_frontyard_yes">Teren prywatny</string> + <string name="attribute_frontyard_no">Teren nie jest prywatny</string> <string name="attribute_teamwork_yes">Praca zespołowa</string> - <string name="attribute_teamwork_no">Bez pracy zespołowej</string> - <string name="attribute_landf_yes">Lost And Found tura</string> - <string name="attribute_landf_no">Żadna Lost And Found tura</string> - <string name="attribute_partnership_yes">Partnerska skrytka</string> - <string name="attribute_partnership_no">Żadna partnerska skrytka</string> + <string name="attribute_teamwork_no">Praca zespołowa niewymagana</string> + <string name="attribute_landf_yes">Wyprawa Lost And Found</string> + <string name="attribute_landf_no">Bez wyprawy Lost And Found</string> + <string name="attribute_partnership_yes">Skrytka partnerska</string> + <string name="attribute_partnership_no">Skrytka nie jest partnerska</string> <!-- attributes (equipment -> required, not required) --> <string name="attribute_fee_yes">Opłata za wejście lub parking</string> <string name="attribute_fee_no">Bez opłaty za wejście lub parking</string> - <string name="attribute_rappelling_yes">Sprzęt wspinaczkowy</string> - <string name="attribute_rappelling_no">Sprzęt wspinaczkowy nie potrzebny</string> - <string name="attribute_boat_yes">Łódź</string> - <string name="attribute_boat_no">Łódź nie potrzebna</string> - <string name="attribute_scuba_yes">Sprzęt do nurkowania</string> - <string name="attribute_scuba_no">Sprzęt do nurkowania nie potrzebny</string> - <string name="attribute_flashlight_yes">Latarka</string> - <string name="attribute_flashlight_no">Latarka nie potrzebna</string> - <string name="attribute_uv_yes">Wymagane światło UV</string> - <string name="attribute_uv_no">Światło UV nie potrzebne</string> - <string name="attribute_snowshoes_yes">Rakiety śnieżne</string> - <string name="attribute_snowshoes_no">Rakiety śnieżne nie potrzebne</string> - <string name="attribute_skiis_yes">Narty biegowe</string> - <string name="attribute_skiis_no">Narty biegowe nie potrzebne</string> - <string name="attribute_s_tool_yes">Wymagane specjalne narzędzia</string> - <string name="attribute_s_tool_no">Specjalne narzędzia nie potrzebne</string> - <string name="attribute_wirelessbeacon_yes">Wireless Beacon</string> - <string name="attribute_wirelessbeacon_no">Bez Wireless Beacon</string> + <string name="attribute_rappelling_yes">Sprzęt wspinaczkowy potrzebny</string> + <string name="attribute_rappelling_no">Sprzęt wspinaczkowy niepotrzebny</string> + <string name="attribute_boat_yes">Łódź potrzebna</string> + <string name="attribute_boat_no">Łódź niepotrzebna</string> + <string name="attribute_scuba_yes">Sprzęt do nurkowania potrzebny</string> + <string name="attribute_scuba_no">Sprzęt do nurkowania niepotrzebny</string> + <string name="attribute_flashlight_yes">Latarka potrzebna</string> + <string name="attribute_flashlight_no">Latarka niepotrzebna</string> + <string name="attribute_uv_yes">Światło UV potrzebne</string> + <string name="attribute_uv_no">Światło UV niepotrzebne</string> + <string name="attribute_snowshoes_yes">Rakiety śnieżne potrzebne</string> + <string name="attribute_snowshoes_no">Rakiety śnieżne niepotrzebne</string> + <string name="attribute_skiis_yes">Narty biegowe potrzebne</string> + <string name="attribute_skiis_no">Narty biegowe niepotrzebne</string> + <string name="attribute_s_tool_yes">Specjalne narzędzia potrzebne</string> + <string name="attribute_s_tool_no">Specjalne narzędzia niepotrzebne</string> + <string name="attribute_wirelessbeacon_yes">Bezprzewodowe nadajniki</string> + <string name="attribute_wirelessbeacon_no">Bez bezprzewodowych nadajników</string> <string name="attribute_treeclimbing_yes">Wspinaczka na drzewo</string> <string name="attribute_treeclimbing_no">Bez wspinaczki na drzewo</string> <!-- attributes (hazards -> present, not present) --> <string name="attribute_poisonoak_yes">Trujące rośliny</string> - <string name="attribute_poisonoak_no">Nie trujące rośliny</string> + <string name="attribute_poisonoak_no">Bez trujących roślin</string> <string name="attribute_dangerousanimals_yes">Niebezpieczne zwierzęta</string> - <string name="attribute_dangerousanimals_no">Bez niebezpiecznych zwierzęt</string> + <string name="attribute_dangerousanimals_no">Bez niebezpiecznych zwierząt</string> <string name="attribute_ticks_yes">Kleszcze</string> <string name="attribute_ticks_no">Bez kleszczy</string> <string name="attribute_mine_yes">Opuszczone kopalnie</string> - <string name="attribute_mine_no">Nie ma opuszczonych kopalń</string> + <string name="attribute_mine_no">Bez opuszczonych kopalń</string> <string name="attribute_cliff_yes">Klif / spadające kamienie</string> - <string name="attribute_cliff_no">Nie ma Klif / bez spadających kamieni</string> + <string name="attribute_cliff_no">Bez klifów / bez spadających kamieni</string> <string name="attribute_hunting_yes">Polowania</string> - <string name="attribute_hunting_no">Bez polowania</string> + <string name="attribute_hunting_no">Bez polowań</string> <string name="attribute_danger_yes">Niebezpieczny obszar</string> - <string name="attribute_danger_no">Nie ma niebezpiecznego obszaru</string> + <string name="attribute_danger_no">Bez niebezpiecznego obszaru</string> <string name="attribute_thorn_yes">Kolce</string> <string name="attribute_thorn_no">Bez kolców</string> <!-- attributes (facilities -> yes, no) --> <string name="attribute_wheelchair_yes">Dostępne dla wózków inwalidzkich</string> <string name="attribute_wheelchair_no">Niedostępne dla wózków inwalidzkich</string> - <string name="attribute_parking_yes">Dostępny parking</string> - <string name="attribute_parking_no">Niedostępny parking</string> + <string name="attribute_parking_yes">Parking dostępny</string> + <string name="attribute_parking_no">Parking niedostępny</string> <string name="attribute_public_yes">Transport publiczny</string> <string name="attribute_public_no">Bez transportu publicznego</string> <string name="attribute_water_yes">Woda pitna w pobliżu</string> @@ -767,26 +964,41 @@ <string name="attribute_restrooms_yes">Toalety publiczne w pobliżu</string> <string name="attribute_restrooms_no">Bez toalet publicznych w pobliżu</string> <string name="attribute_phone_yes">Telefon w pobliżu</string> - <string name="attribute_phone_no">Nie ma telefonu w pobliżu</string> + <string name="attribute_phone_no">Bez telefonu w pobliżu</string> <string name="attribute_picnic_yes">Stoły piknikowe w pobliżu</string> <string name="attribute_picnic_no">Bez stołów piknikowych w pobliżu</string> <string name="attribute_camping_yes">Możliwość biwakowania</string> <string name="attribute_camping_no">Bez możliwości biwakowania</string> <string name="attribute_stroller_yes">Dostępne dla wózków z dziećmi</string> - <string name="attribute_stroller_no">Niedostępne dla wózków z dziećmi</string> + <string name="attribute_stroller_no">Niedostępna dla wózków z dziećmi</string> <string name="attribute_fuel_yes">Stacja benzynowa w pobliżu</string> <string name="attribute_fuel_no">Bez stacji benzynowej w pobliżu</string> <string name="attribute_food_yes">Gastronomia w pobliżu</string> <string name="attribute_food_no">Bez gastronomii w pobliżu</string> <!-- next things --> - <string name="legal_note">Aby móc korzystać z usług serwisu Geocaching.com <a href="http://www.geocaching.com/about/termsofuse.aspx">warunki korzystania Groundspeak</a> muszą być potwierdzone.</string> + <string name="legal_note">Aby móc korzystać z usług serwisu Geocaching.com <a href="http://www.geocaching.com/about/termsofuse.aspx">warunki korzystania Groundspeak</a> muszą być zaakceptowane.</string> + <string name="quote">Aby uczynić geocaching prostszym, a użytkowników bardziej leniwymi.</string> + <string name="powered_by">carnero</string> <string name="support">Support: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string> <string name="website">Website: <a href="http://cgeo.org/">cgeo.org</a></string> <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo strona</a></string> <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string> - <string name="nutshellmanual">Manuał: <a href="http://itw.bidix.info/cgeo/">c:geo skrócona instrukcja obsługi</a></string> - <string name="about_twitter">Czy chczesz aby <b>c:geo</b> publikował wiadomości textowe na stronie Twitter za każdym razem jak znajdziesz skrzynkę?</string> - <string name="about_auth_1">Poniższy proces pozwala <b>c:geo</b>, aby uzyskać dostęp do Twitter - po uzgodnieniu.</string> - <string name="about_auth_2">Kliknięcie na \"Autoryzacja c:geo\" spowoduje rozpoczęcie procesu. Ten proces spowoduje otwarcie przeglądarki internetowej na stronie Twitter. Zaloguj się na tej stronie i pozwól <b>c:geo</b> aby uzyskać dostęp do konta. Jeśli zostanie zaakceptowany, Twitter pojawi kod numeryczny PIN. Kod PIN musi zostać wklejony do <b>c:geo</b> i zostać potwierdzony. To jest wszystko.</string> + <string name="nutshellmanual">Podręcznik: <a href="http://manual.cgeo.org/">c:geo skrócona instrukcja obsługi</a></string> + <string name="about_twitter">Czy chczesz aby <b>c:geo</b> publikował nowy status na Twitter za każdym razem kiedy znajdziesz skrzynkę?</string> + <string name="about_auth_1">Poniższy proces pozwala <b>c:geo</b> uzyskać dostęp do Twitter za Twoim pozwoleniem.</string> + <string name="about_auth_2">Kliknięcie na \"Autoryzacja c:geo\" spowoduje rozpoczęcie procesu. Ten proces spowoduje otwarcie przeglądarki internetowej na stronie Twitter. Zaloguj się na tej stronie i pozwól <b>c:geo</b> uzyskać dostęp do Twojego konta. Jeśli zostanie zaakceptowany, Twitter wyświetli kod numeryczny PIN. Kod PIN musi zostać wklejony do <b>c:geo</b> i potwierdzony. To wszystko.</string> + + <!-- status (used via string based resource loading) --> + <string name="status_new_release" tools:ignore="UnusedResources">Dostępna nowa wersja.\nKliknij aby zainstalować.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">Dostępna nowa codzienna wersja.\nKliknij aby zainstalować.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">Dostępny nowy kandydat na nową wersję.\nKliknij aby zainstalować.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">Ostatnie zmiany na geocaching.com popsuły c:geo.\nPracujemy nad tym, sprawdź ponownie niedługo.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Ostatnie zmiany na geocaching.com popsuły funkcjonalność map Live.\nWe are working on it, Pracujemy nad tym, sprawdź ponownie niedługo.</string> + + <string name="clipboard_copy_ok">Skopiowano do schowka</string> + <plurals name="days_ago"> + <item quantity="one">wczoraj</item> + <item quantity="other">%d dni temu</item> + </plurals> </resources> diff --git a/main/res/values-pt/strings.xml b/main/res/values-pt/strings.xml index 60e2fa1..d8acac3 100644 --- a/main/res/values-pt/strings.xml +++ b/main/res/values-pt/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo bússola</string> @@ -88,9 +88,6 @@ <string name="log_post_no_rate">Publicar registo & Não votar</string> <string name="log_post_not_possible">A carregar página de registo…</string> <string name="log_add">Adicionar</string> - <string name="log_date">Data</string> - <string name="log_time">Hora</string> - <string name="log_date_time">Data & Hora</string> <string name="log_rating">Pontuação</string> <string name="log_no_rating">Não votar</string> <string name="log_stars_1">1 estrela</string> @@ -140,8 +137,6 @@ <string name="err_license">O utilizador não concordou com a licença de utilização de Geocaching.com, por isso c:geo não pode carregar as coordenadas da cache.</string> <string name="err_unpublished">A cache pedida não está publicada.</string> <string name="err_premium_only">Esta cache só está disponível para membros premium do Geocaching.com.</string> - <string name="err_store">O c:geo não consegue arquivar a cache.</string> - <string name="err_drop">O c:geo não consegue apagar a cache.</string> <string name="err_detail_open">O c:geo não consegue abrir os detalhes da geocache.</string> <string name="err_detail_cache">O c:geo não consegue mostrar a cache pretendida. É mesmo uma geocache?</string> <string name="err_detail_cache_find">O c:geo não encontra a geocache</string> @@ -154,20 +149,15 @@ <string name="err_detail_no_spoiler">O c:geo não encontrou images spoiler para esta cache.</string> <string name="err_detail_no_map_static">O c:geo não encontrou mapas estáticos para esta cache.</string> <string name="err_detail_not_load_map_static">O c:geo falhou o carregamento de mapas estáticos.</string> - <string name="err_detail_ask_store_map_static">O c:geo falhou o carregamento de mapas estáticos. Arquivar agora?</string> <string name="err_detail_still_working">A trabalhar noutra tarefa.</string> <string name="err_watchlist_still_managing">Ainda a gerir a sua watchlist.</string> <string name="err_watchlist_failed">A gestão da sua watchlist falhou.</string> - <string name="err_navigation_no">O c:geo não encontra nenhuma navegação suportada.</string> <string name="err_application_no">O c:geo não encontra a aplicação correcta.</string> <string name="err_auth_initialize">O c:geo falhou a iniciar o processo de autorização.</string> <string name="err_auth_process">Processo de autorização falhou.</string> <string name="err_cannot_log_visit">O c:geo não tem informação suficiente para registar a visita. Por favor, faça-o a partir dos detalhes completos da cache.</string> <string name="err_init_cleared">O c:geo não consegue limpar os dados de login.</string> <string name="err_download_fail">O c:geo falhou o download das caches porque </string> - <string name="err_list_load_fail">O c:geo falhou a carregar a lista das caches.</string> - <string name="err_store_failed">O c:geo não pode arquivar a geocache.</string> - <string name="err_refresh_failed">O c:geo não consegue actualizar a geocache.</string> <string name="err_dwld_details_failed">O c:geo falhou o download dos detalhes da cache.</string> <string name="err_load_descr_failed">O c:geo não consegue carregar a descrição.</string> <string name="err_location_unknown">O c:geo não sabe a localização da cache.</string> @@ -175,18 +165,12 @@ <string name="err_tb_display">O c:geo não consegue mostrar o trackable pretendido. É mesmo um trackable?</string> <string name="err_tb_details_open">O c:geo não consegue abrir os detalhes do trackable.</string> - <string name="err_tb_details_download">O c:geo falhou o download dos detalhes do trackable porque</string> - <string name="err_tb_forgot">O c:geo esqueceu o trackable pretendido.</string> <string name="err_tb_forgot_saw">O c:geo esqueceu o trackable que viu.</string> <string name="err_tb_find">O c:geo não encontra o trackable</string> <string name="err_tb_find_that">O c:geo não encontra esse trackable.</string> <string name="err_waypoint_cache_unknown">O c:geo não sabe a que cache quer adicionar o ponto de referência.</string> - <string name="err_waypoint_unknown">O c:geo esqueceu qual o ponto de referência que pretende visualizar.</string> <string name="err_waypoint_add_failed">O c:geo falhou o adicionamento do seu ponto de referência.</string> - <string name="err_waypoint_load_failed">O c:geo falhou o carregamento do ponto de referência.</string> - <string name="err_waypoint_delete_failed">O c:geo falhou a remoção do ponto de referência.</string> - <string name="err_waypoint_open_cache_failed">O c:geo não consegue abrir os detalhes da cache.</string> <string name="err_point_unknown_position">O c:geo não conseguiu reconhecer a sua localização.</string> <string name="err_point_no_position_given_title">Informação requerida</string> <string name="err_point_no_position_given">Preencha pelo menos a latitude, a longitude, a distância ou a direcção. Também pode preencher os quatro campos.</string> @@ -201,15 +185,12 @@ <string name="err_log_failed_server">O c:geo falhou a publicação do registo porque o servidor não responde.</string> <string name="err_log_post_failed">O c:geo falhou a publicação do registo.</string> - <string name="err_search_address_no_match">O c:geo não encontrou um local que corresponda.</string> <string name="err_search_address_forgot">O c:geo esqueceu o endereço que procura.</string> <string name="err_parse_lat">O c:geo não consegue analisar a latitue.</string> <string name="err_parse_lon">O c:geo não consegue analisar a logitude.</string> <string name="err_parse_dist">O c:geo não consegue analisar a distância.</string> <string name="err_parse_lat_lon">O c:geo não consegue analisar a latitue ou a longitude.</string> - <string name="err_fieldnotes_export_failed">A exportação das Notas de Campo falhou.</string> - <string name="warn_save_nothing">Não há nada para guardar.</string> <string name="warn_no_cache_coord">Não há cache com coordenadas.</string> <string name="warn_no_coordinates">Nenhumas coordenadas fornecidas.</string> @@ -234,7 +215,6 @@ <string name="info_log_cleared">O registo foi limpo.</string> <string name="info_log_type_changed">O tipo de registo foi alterado!</string> - <string name="info_fieldnotes_exported_to">Notas de campo exportadas para</string> <string name="info_storing_static_maps">A tentar arquivar mapas estáticos.</string> <!-- location service --> @@ -323,10 +303,7 @@ <string name="caches_filter_type">Tipo</string> <string name="caches_filter_track">Com trackables</string> <string name="caches_filter_clear">Limpar filtros</string> - <string name="caches_filter_size_title">Escolha o tamanho</string> - <string name="caches_filter_type_title">Escolha o tipo</string> <string name="caches_filter_modified">Com as coordenadas modificadas</string> - <string name="caches_exporting_fieldnote">A exportar como Notas de Campo…</string> <string name="caches_removing_from_history">A remover do histórico…</string> <!-- caches lists --> @@ -405,7 +382,6 @@ <string name="init_offline_wp">Armazenar waypoints de mapas estáticos para utilização offline</string> <string name="init_save_log_img">Guardar imagens dos registos</string> <string name="init_units">Utilizar distância nas unidades do sistema imperial</string> - <string name="init_nav">Utilizar Google Navigation</string> <string name="init_log_offline">Activar registo offline\n(Não mostrar o registo online quando fôr registar, não enviar o registo online)</string> <string name="init_livelist">Mostrar a direcção para a cache na lista</string> <string name="init_altitude">Correcção de altitude</string> @@ -429,14 +405,11 @@ <string name="init_mapsources">Fontes de mapa</string> <string name="init_mapsources_description">Aqui pode seleccionar a fonte dos seus mapas. Como alternativa ao Google Maps, vários estilos de OpenStreetMap estão disponíveis, e até ficheiros de mapas offline (veja <a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a> para mais detalhes).</string> <string name="init_mapsource_select">Seleccione a fonte de mapa</string> - <string name="init_select_themefolder">…</string> <string name="init_map_directory_description">Directório com os mapas offline</string> <string name="init_gpx_exportdir">Directório para exportar GPX</string> <string name="init_gpx_importdir">Directório para importar GPX</string> <string name="init_gpx_exportdir_description">Aqui pode selecionar o directório para exportar os GPX.</string> <string name="init_gpx_importdir_description">Aqui pode selecionar o directório para importar os GPX.</string> - <string name="init_gpx_exportdir_select">Selecione directório para exportar GPX</string> - <string name="init_gpx_importdir_select">Selecione directório para importar GPX</string> <string name="init_maptrail">Mostrar rasto no mapa</string> <string name="init_share_after_export">Abrir o menu de partilha depois da exportação GPX</string> <string name="init_trackautovisit">Marcar automaticamente os trackables como \"visitados\"</string> @@ -452,7 +425,6 @@ <string name="init_dbonsdcard_title">Localização da base de dados</string> <string name="init_dbonsdcard_note">Pode armazenar a base de dados do c:geo no armazenamento externo. Se o fizer vai poupar memória interna, mas pode perder um pouco de performance e o c:geo pode não funcionar se o armazenamento externo não estiver disponível.</string> <string name="init_dbonsdcard">base de dados no armazenamento externo</string> - <string name="init_dbmove">A mover a base de dados</string> <string name="init_dbmove_dbmove">A mover a base de dados</string> <string name="init_dbmove_running">A mover a base de dados</string> <string name="init_dbmove_success">Base de dados movida com sucesso.</string> @@ -462,13 +434,6 @@ <string name="init_rendertheme_folder">Directório com os temas de mapas offline personalizados (opcional)</string> <!-- map sources --> - <string-array name="map_sources"> - <item>@string/map_source_google_map</item> - <item>@string/map_source_google_satellite</item> - <item>@string/map_source_osm_mapnik</item> - <item>@string/map_source_osm_cyclemap</item> - <item>@string/map_source_osm_offline</item> - </string-array> <string name="map_source_google_map">Google: Mapa</string> <string name="map_source_google_satellite">Google: Satélite</string> <string name="map_source_osm_mapnik">OSM: Mapnik</string> @@ -519,7 +484,6 @@ <string name="cache_offline_time_days">dias atrás</string> <string name="cache_premium">Premium</string> <string name="cache_attributes">Atributos</string> - <string name="cache_attributes_no_icons">(actualize a cache para mostrar os ícones dos atributos)</string> <string name="cache_inventory">Inventário</string> <string name="cache_log_offline">Registo Offline</string> <string name="cache_log_images_loading">A carregar imagem do registo…</string> @@ -530,7 +494,6 @@ <string name="cache_description">Descrição</string> <string name="cache_description_long">Descrição longa</string> <string name="cache_description_table_note">A descrição contém a formatação da tabela que pode ser necessário para ser vista correctamente em Geocaching.com.</string> - <string name="cache_watchlist">Lista de observação</string> <string name="cache_watchlist_on">Esta cache está na sua lista de observação.</string> <string name="cache_watchlist_not_on">Esta cache não está na sua lista de observação.</string> <string name="cache_watchlist_add">Adicionar à lista de observação</string> @@ -571,7 +534,9 @@ <string name="cache_dialog_watchlist_remove_title">Lista de observação</string> <string name="cache_dialog_watchlist_remove_message">A remover cache da lista de observação…</string> <string name="cache_menu_navigate">Navegar</string> - <string name="cache_menu_tbt">Turn-by-turn</string> + <string name="cache_menu_navigation_drive">Navegar (Conduzir)</string> + <string name="cache_menu_navigation_walk">Navegar (Andar)</string> + <string name="cache_menu_maps_directions">Direcções pelo Google Maps</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Mostrar no mapa</string> <string name="cache_menu_map_static">Mapas estáticos</string> @@ -622,7 +587,6 @@ <string name="cache_images_loading">A carregar as imagens…</string> <string name="cache_log_types">Tipos de log</string> <string name="cache_coordinates_no">Esta cache não tem coordenadas.</string> - <string name="cache_export_fieldnote">Exportar como Notas de Campo</string> <string name="cache_clear_history">Apagar histórico</string> <string name="cache_remove_from_history">Remover do histórico</string> <string name="cache_license">Licença</string> @@ -650,7 +614,6 @@ <string name="gpx_import_loading_caches">A carregar as caches do ficheiro .gpx</string> <string name="gpx_import_loading_waypoints">A carregar o ficheiro dos waypoints</string> <string name="gpx_import_store_static_maps">A gravar mapas estáticos</string> - <string name="gpx_import_storing">A gravar as caches na base de dados</string> <string name="gpx_import_caches_imported">caches importadas</string> <string name="gpx_import_static_maps_skipped">Download of static maps aborted</string> <string name="gpx_import_title_static_maps">Gravar mapas estáticos</string> @@ -670,10 +633,7 @@ <string name="map_file_select_title">Seleccione ficheiro de mapa</string> <!-- theme file select --> - <string name="theme_file_select_title">Selecione o ficheiro do tema de mapa personalizado</string> - <!-- import --> - <string name="import_title">Importar…</string> <string name="web_import_title">Importar da web</string> <string name="web_import_waiting">À espera de novas caches da web…</string> <string name="web_downloading">A transferir</string> @@ -684,7 +644,6 @@ <!-- waypoint --> <string name="waypoint">Ponto de referência</string> - <string name="waypoint_title">Ponto de referência</string> <string name="waypoint_cache_coordinates">Coordenadas da cache</string> <string name="waypoint_custom">Personalizado</string> <string name="waypoint_my_coordinates">Minhas coordenadas</string> @@ -698,39 +657,17 @@ <string name="waypoint_note">Nota</string> <string name="waypoint_save">Gravar</string> <string name="waypoint_loading">A carregar ponto de referência…</string> - <string name="waypoint_unknown_coordinates">Coordenadas desconhecidas</string> <string name="waypoint_done">Feito</string> <string name="waypoint_duplicate">Duplicar</string> <string name="waypoint_copy_of">Cópia de</string> - <string name="waypoint_menu_open_cache">Abrir cache</string> <string name="search_history">Histórico</string> <string name="search_history_empty">Não existem destinos recentes</string> <string name="search_remove_destination">Destino removido</string> <string name="search_clear_history">Limpar histórico</string> <string name="search_history_cleared">Histórico limpo</string> - <string-array name="waypoint_coordinate_formats"> - <item>@string/waypoint_coordinate_formats_plain</item> - <item>DDD.DDDDD°</item> - <item>DDD°MM.MMM\'</item> - <item>DDD°MM\'SS.SSS\"</item> - </string-array> <string name="waypoint_coordinate_formats_plain">Plano</string> - <!-- distance units --> - <string-array name="distance_units"> - <item>@string/unit_m</item> - <item>@string/unit_km</item> - <item>@string/unit_ft</item> - <item>@string/unit_yd</item> - <item>@string/unit_mi</item> - </string-array> - <string name="unit_m">m</string> - <string name="unit_km">km</string> - <string name="unit_ft">ft</string> - <string name="unit_yd">yd</string> - <string name="unit_mi">mi</string> - <!-- visit --> <string name="visit_tweet">Publicar esta descoberta no Twitter</string> @@ -854,7 +791,6 @@ <!-- export --> <string name="export">Exportar</string> - <string name="export_as">Exportar como…</string> <string name="export_exportedto">exportado para</string> <string name="export_failed">Exportação falhou</string> <string name="export_fieldnotes">Notas de campo</string> @@ -868,9 +804,6 @@ <string name="export_gpx_info">O ficheiro GPX vai ser exportado para %1$s com a data e a hora actual como nome de ficheiro.</string> <string name="export_gpx_to">Enviar GPX exportado para</string> - <!-- attribute unknown --> - <string name="attribute_unknown_yes">Unknown attribute present</string> - <string name="attribute_unknown_no">Unknown attribute not present</string> <!-- attributes (permissions -> allowed, not allowed) --> <string name="attribute_dogs_yes">Cães permitidos</string> <string name="attribute_dogs_no">Cães não permitidos</string> @@ -1025,11 +958,11 @@ <string name="about_auth_2">Premir o botão \"Autorizar c:geo\" dará início ao processo. Este processo irá abrir a página do Twitter no seu browser. Faça login nesta página e autorize o <b>c:geo</b> a aceder à sua conta. Se autorizar, o Twitter irá mostrar um código PIN numérico. Este PIN deverá ser copiado para o <b>c:geo</b> e sujeito a confirmação. E é tudo.</string> <!-- status --> - <string name="status_new_release">Nova versão disponível.\nClique para instalar.</string> - <string name="status_new_nightly">Nova \'nightly build\' disponível.\nClique para instalar.</string> - <string name="status_new_rc">Nova \'release candidate\' disponível .\nClique para instalar.</string> - <string name="status_geocaching_change">Alterações recentes em geocaching.com fizeram com que c:geo funcione mal.\nEstamos a trabalhar nisto, verifique de novo mais tarde.</string> - <string name="status_geocaching_livemap">Alterações recentes em geocaching.com fizeram com o mapa ao vivo não funcione bem.\nEstamos a trabalhar nisto, verifique de novo mais tarde.</string> + <string name="status_new_release" tools:ignore="UnusedResources">Nova versão disponível.\nClique para instalar.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">Nova \'nightly build\' disponível.\nClique para instalar.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">Nova \'release candidate\' disponível .\nClique para instalar.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">Alterações recentes em geocaching.com fizeram com que c:geo funcione mal.\nEstamos a trabalhar nisto, verifique de novo mais tarde.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Alterações recentes em geocaching.com fizeram com o mapa ao vivo não funcione bem.\nEstamos a trabalhar nisto, verifique de novo mais tarde.</string> <string name="clipboard_copy_ok">Copiado para a área de transferência</string> <plurals name="days_ago"> diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml index fadf078..0593da5 100644 --- a/main/res/values-sk/strings.xml +++ b/main/res/values-sk/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo kompas</string> @@ -87,9 +87,6 @@ <string name="log_post_no_rate">Odoslať log a nehlasovať</string> <string name="log_post_not_possible">Načítanie stránky s logmi…</string> <string name="log_add">Pridať</string> - <string name="log_date">Dátum</string> - <string name="log_time">Čas</string> - <string name="log_date_time">Dátum a čas</string> <string name="log_rating">Hlasovať</string> <string name="log_no_rating">Nehlasovať</string> <string name="log_stars_1">1 hviezdička</string> @@ -139,8 +136,6 @@ <string name="err_license">Používateľ nepotvrdil súhlas s licenčnou dohodou serveru Geocaching.com, takže c:geo nemôže načítať koordináty skrýše.</string> <string name="err_unpublished">Požadovaná skrýša nebola publikovaná</string> <string name="err_premium_only">Skrýša je dostupná iba pre platiacich používateľov Geocaching.com</string> - <string name="err_store">Prepáčte, c:geo nemôže uložiť skrýšu.</string> - <string name="err_drop">Prepáčte, c:geo nemôže zmazať skrýšu.</string> <string name="err_detail_open">Prepáčte, c:geo nedokáže načítať detaily skrýše.</string> <string name="err_detail_cache">Prepáčte, c:geo nedokáže načítať detaily skrýše. Je to naozaj skrýša?</string> <string name="err_detail_cache_find">Prepáčte, c:geo nemôže nájsť skrýšu</string> @@ -153,20 +148,15 @@ <string name="err_detail_no_spoiler">c:geo nenašla pre túto skrýšu žiaden spoilerový obrázok.</string> <string name="err_detail_no_map_static">c:geo nenašla žiadnu statickú mapu pre túto skrýšu.</string> <string name="err_detail_not_load_map_static">Prepáčte, c:geo sa nepodarilo načítať statické mapy.</string> - <string name="err_detail_ask_store_map_static">c:geo sa nepodarilo načítať statické mapy. Chcete ich uložiť teraz?</string> <string name="err_detail_still_working">Stále prebieha práca na inej úlohe.</string> <string name="err_watchlist_still_managing">Stále prebieha správa vášho zoznamu sledovaných.</string> <string name="err_watchlist_failed">Zlyhala zmena sledovaných.</string> - <string name="err_navigation_no">Prepáčte, c:geo nemôže nájsť žiadnu podporovanú navigáciu.</string> <string name="err_application_no">Prepáčte, c:geo nemôže násjť žiadnu použiteľnú aplikáciu.</string> <string name="err_auth_initialize">Prepáčte, c:geo nedokázalo zahájiť autorizáciu.</string> <string name="err_auth_process">Autorizácia zlyhala.</string> <string name="err_cannot_log_visit">c:geo nemá dostatok informácií pre zapísanie návštevy. Prosím urobte to z kompletného detailu skrýše.</string> <string name="err_init_cleared">Prepáčte, c:geo nedokázalo zmazať prihlasovacie údaje.</string> <string name="err_download_fail">Prepáčte, c:geo nemôže načítať skrýšu, pretože</string> - <string name="err_list_load_fail">c:geo nemôže načítať zoznam skrýš.</string> - <string name="err_store_failed">c:geo nemôže uložiť skrýšu.</string> - <string name="err_refresh_failed">c:geo nemôže obnoviť skrýšu.</string> <string name="err_dwld_details_failed">c:geo nemôže stiahnuť detaily skrýše.</string> <string name="err_load_descr_failed">c:geo nemôže načítať popis.</string> <string name="err_location_unknown">c:geo nepozná súradnice skrýše</string> @@ -174,18 +164,12 @@ <string name="err_tb_display">Prepáčte, c:geo nemôže zobraziť trasovateľný predmet. Je to naozaj trasovateľný?</string> <string name="err_tb_details_open">Prepáčte, c:geo nemôže otvoriť podrobnosti k trasovateľnému predmetu.</string> - <string name="err_tb_details_download">Prepáčte, c:geo nemôže stiahnuť podrobnosti k trasovateľnému predmetu, pretože</string> - <string name="err_tb_forgot">c:geo zabudlo, ktorý trasovateľný predmet ste chceli.</string> <string name="err_tb_forgot_saw">c:geo zabudlo, ktorý trasovateľný predmet ste pozerali.</string> <string name="err_tb_find">c:geo nemôže nájsť trasovateľný predmet.</string> <string name="err_tb_find_that">c:geo nemôže nájsť tento trasovateľný predmet.</string> <string name="err_waypoint_cache_unknown">c:geo nevie, ku ktorej skrýši chcete pridať bod trasy.</string> - <string name="err_waypoint_unknown">c:geo zabudlo, ktorý bod trasy chcete zobraziť.</string> <string name="err_waypoint_add_failed">c:geo nemôže pridať bod trasy.</string> - <string name="err_waypoint_load_failed">c:geo nemôže načítať bod trasy.</string> - <string name="err_waypoint_delete_failed">c:geo nemôže zmazať bod trasy.</string> - <string name="err_waypoint_open_cache_failed">c:geo nemôže otvoriť detaily skrýše.</string> <string name="err_point_unknown_position">c:geo nevie, kde ste.</string> <string name="err_point_no_position_given_title">popis je požadovaný</string> <string name="err_point_no_position_given">Vyplňte aspoň šírku alebo dĺžku alebo vzdialenosť a smer. Môžete tiež vyplniť všetky štyri polia.</string> @@ -200,15 +184,12 @@ <string name="err_log_failed_server">c:geo nemohlo odoslať log, pretože server neodpovedá.</string> <string name="err_log_post_failed">c:geo nemohlo odoslať log.</string> - <string name="err_search_address_no_match">c:geo nenašlo žiadne zodpovedajúce miesto</string> <string name="err_search_address_forgot">c:geo zabudlo adresu, ktorú sa pokúšate nájsť.</string> <string name="err_parse_lat">c:geo nemôže dopočítať šírku.</string> <string name="err_parse_lon">c:geo nemôže dopočítať dĺžku.</string> <string name="err_parse_dist">c:geo nemôže dopočítať vzdialenosť.</string> <string name="err_parse_lat_lon">c:geo nemôže zistiť šírku a dĺžku.</string> - <string name="err_fieldnotes_export_failed">Zlyhal export poznámok v poli.</string> - <string name="warn_save_nothing">Nie je čo uložiť.</string> <string name="warn_no_cache_coord">Nie je žiadna skrýša so súradnicami.</string> <string name="warn_no_coordinates">Nezískané súradnice</string> @@ -233,7 +214,6 @@ <string name="info_log_cleared">Log bol vyprázdnený.</string> <string name="info_log_type_changed">Typ logu bol zmenený!</string> - <string name="info_fieldnotes_exported_to">Poznámky exportované do</string> <string name="info_storing_static_maps">ukladanie statických máp</string> <!-- location service --> @@ -322,10 +302,7 @@ <string name="caches_filter_type">podľa typu</string> <string name="caches_filter_track">s trasovateľnými predmetmi</string> <string name="caches_filter_clear">vymazať filtre</string> - <string name="caches_filter_size_title">Výber veľkosti</string> - <string name="caches_filter_type_title">Výber typu</string> <string name="caches_filter_modified">S upravenými súradnicami</string> - <string name="caches_exporting_fieldnote">Exportovanie ako poznámky…</string> <string name="caches_removing_from_history">Odstraňovanie z histórie…</string> <!-- caches lists --> @@ -404,7 +381,6 @@ <string name="init_offline_wp">Uložiť statické mapy bodov strás pre použitie offline</string> <string name="init_save_log_img">Uložiť obrázky zo záznamov</string> <string name="init_units">Používať imperiálne jednotky vzdialenosti</string> - <string name="init_nav">Používať Navigáciu Google</string> <string name="init_log_offline">Pri zaznamenávaní vždy použiť offline režim (nezobrazovať online obrazovku počas zaznamenávania, neposielať záznam online)</string> <string name="init_livelist">Zobrazovať smer v zozname skrýš</string> <string name="init_altitude">Oprava výšky</string> @@ -428,17 +404,11 @@ <string name="init_mapsources">Mapové zdroje</string> <string name="init_mapsources_description">Tu môžete vybrať zdroje pre vaše mapy. Je to alternatíva ku Google mapám rôznych OpenStreetMap styles sú dostupné a dokonca offline mapové súbory (podrobnosti nájdete na <a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a>).</string> <string name="init_mapsource_select">Vyberte zdroj máp</string> - <string name="init_select_themefolder">…</string> <string name="init_map_directory_description">Priečinok s offline mapami</string> - <string name="init_select_map_directory">…</string> - <string name="init_select_gpx_exportdir">…</string> - <string name="init_select_gpx_importdir">…</string> <string name="init_gpx_exportdir">Priečinok pre GPX Export</string> <string name="init_gpx_importdir">Priečinok pre GPX Import</string> <string name="init_gpx_exportdir_description">Tu si môžete vybrať priečinok pre GPX exporty.</string> <string name="init_gpx_importdir_description">Tu si môžete vybrať priečinok pre GPX importy.</string> - <string name="init_gpx_exportdir_select">Výber priečinka pre GPX export</string> - <string name="init_gpx_importdir_select">Výber priečinka pre GPX import</string> <string name="init_maptrail">Zobraziť stopu na mape</string> <string name="init_share_after_export">Po exporte GPX otvoriť menu pre zdieľanie</string> <string name="init_trackautovisit">Nastaviť trasovateľné predmety automaticky na „navštívené“</string> @@ -454,7 +424,6 @@ <string name="init_dbonsdcard_title">Umiestnenie databázy</string> <string name="init_dbonsdcard_note">Databázu c:geo môžete umiestniť na externé úložisko. Ak to spravíte, ušetríte vnútornú pamäť, ale môžete stratiť časť z výkonu a c:geo nebude fungovať, keď vaša SD karta nebude dostupná.</string> <string name="init_dbonsdcard">Databáza na externom úložisku</string> - <string name="init_dbmove">Presúvanie databázy</string> <string name="init_dbmove_dbmove">Presúvanie databázy</string> <string name="init_dbmove_running">Prebieha presúvanie databázy</string> <string name="init_dbmove_success">Databáza bola úspešne presunutá.</string> @@ -514,7 +483,6 @@ <string name="cache_offline_time_days">pred dňami</string> <string name="cache_premium">platený účet</string> <string name="cache_attributes">Atribúty</string> - <string name="cache_attributes_no_icons">(obnoví skrýšu pre zobrazenie ikon atribútov)</string> <string name="cache_inventory">Obsah</string> <string name="cache_log_offline">Offline log</string> <string name="cache_log_images_loading">Načítanie obrázku z logu…</string> @@ -525,7 +493,6 @@ <string name="cache_description">Popis</string> <string name="cache_description_long">Dlhý popis</string> <string name="cache_description_table_note">Popis obsahuje formátovanie tabuľky, ktorý môže byť pre správne zobrazenie potrebné otvoriť v geocaching.com.</string> - <string name="cache_watchlist">Zoznam sledovaných</string> <string name="cache_watchlist_on">Skrýša je vo vašom zozname sledovaných.</string> <string name="cache_watchlist_not_on">Skrýša nie je vo vašom zozname sledovaných.</string> <string name="cache_watchlist_add">Pridať do zoznamu sledovaných</string> @@ -567,7 +534,6 @@ <string name="cache_dialog_watchlist_remove_title">Zoznam sledovaných</string> <string name="cache_dialog_watchlist_remove_message">Odstraňovanie skrýše zo zoznamu sledovaných…</string> <string name="cache_menu_navigate">Navigovať</string> - <string name="cache_menu_tbt">Navigácia s inštrukciami</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Mapa</string> <string name="cache_menu_map_static">Statická mapa</string> @@ -619,7 +585,6 @@ <string name="cache_images_loading">Prebieha načítanie obrázkov…</string> <string name="cache_log_types">Typy záznamov</string> <string name="cache_coordinates_no">Táto skrýša nemá žiadne súradnice.</string> - <string name="cache_export_fieldnote">Exportovať ako poznámky</string> <string name="cache_clear_history">Vymazať históriu</string> <string name="cache_remove_from_history">Odstrániť z histórie</string> <string name="cache_license">Licencia</string> @@ -647,7 +612,6 @@ <string name="gpx_import_loading_caches">Načítanie skrýš z .gpx súboru\nNačítané:</string> <string name="gpx_import_loading_waypoints">Načítanie bodov trasy z .gpx súboru\nNačítané:</string> <string name="gpx_import_store_static_maps">Ukladanie statických máp</string> - <string name="gpx_import_storing">Zapisovanie skrýš do databázy\nZapísané:</string> <string name="gpx_import_caches_imported">skrýše importované</string> <string name="gpx_import_static_maps_skipped">Preberanie statických máp zrušené</string> <string name="gpx_import_title_static_maps">Uloženie statických máp</string> @@ -667,10 +631,7 @@ <string name="map_file_select_title">Výber mapového súboru</string> <!-- theme file select --> - <string name="theme_file_select_title">Výber súboru s témou mapy</string> - <!-- import --> - <string name="import_title">Import…</string> <string name="web_import_title">Import z webu</string> <string name="web_import_waiting">Čakanie na nové skrýše z webu…</string> <string name="web_downloading">Preberanie</string> @@ -681,7 +642,6 @@ <!-- waypoint --> <string name="waypoint">Bod trasy</string> - <string name="waypoint_title">Bod trasy</string> <string name="waypoint_cache_coordinates">Súradnice skrýše</string> <string name="waypoint_custom">vlastný</string> <string name="waypoint_my_coordinates">Aktuálna poloha</string> @@ -695,11 +655,9 @@ <string name="waypoint_note">poznámka</string> <string name="waypoint_save">Uložiť</string> <string name="waypoint_loading">Načítanie bodu trasy…</string> - <string name="waypoint_unknown_coordinates">Neznáme súradnice</string> <string name="waypoint_done">Hotovo</string> <string name="waypoint_duplicate">Duplikovať</string> <string name="waypoint_copy_of">Kópia</string> - <string name="waypoint_menu_open_cache">Otvoriť skrýšu</string> <string name="search_history">História</string> <string name="search_history_empty">Bez predchádzajúcich cieľov</string> <string name="search_remove_destination">Cieľ odstránený</string> @@ -838,7 +796,6 @@ <!-- export --> <string name="export">Exportovať</string> - <string name="export_as">Exportovať ako…</string> <string name="export_exportedto">exportované do</string> <string name="export_failed">Export zlyhal</string> <string name="export_fieldnotes">Poznámky</string> @@ -1009,11 +966,11 @@ <string name="about_auth_2">Ťuknutím na tlačidlo „Zahájiť autorizáciu“ celý proces začne. Tento proces otvorí webovú stránku Twitteru, kde sa sa prihlásite a tlačidlom „Authorize app“ umožníte aplikácii <b>c:geo</b> prístup k vášmu Twitter účtu. Potom čo ťuknete na „Authorize app“, Twitter vám pridelí PIN kód. Tento kód skopírujte a vložte do aplikácie <b>c:geo</b>. A potvrďte. To je všetko.</string> <!-- status --> - <string name="status_new_release">Je dostupné nové vydanie.\nKliknite pre inštaláciu.</string> - <string name="status_new_nightly">Je dostupná nová nočná zostava.\nKliknite pre inštaláciu.</string> - <string name="status_new_rc">Je dostupná nová verzia „release candidate“.\nKliknite pre inštaláciu.</string> - <string name="status_geocaching_change">Nedávne zmeny na geocaching.com znefunkčnili c:geo.\nPracujeme na tom, skúste skontrolovať aktualizácie onedlho.</string> - <string name="status_geocaching_livemap">Nedávne zmeny na geocaching.com znefunkčnili aktívnu mapu.\nPracujeme na tom, skúste skontrolovať aktualizácie onedlho.</string> + <string name="status_new_release" tools:ignore="UnusedResources">Je dostupné nové vydanie.\nKliknite pre inštaláciu.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">Je dostupná nová nočná zostava.\nKliknite pre inštaláciu.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">Je dostupná nová verzia „release candidate“.\nKliknite pre inštaláciu.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">Nedávne zmeny na geocaching.com znefunkčnili c:geo.\nPracujeme na tom, skúste skontrolovať aktualizácie onedlho.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Nedávne zmeny na geocaching.com znefunkčnili aktívnu mapu.\nPracujeme na tom, skúste skontrolovať aktualizácie onedlho.</string> <string name="clipboard_copy_ok">Skopírované do schránky</string> <plurals name="days_ago"> diff --git a/main/res/values-sv/strings.xml b/main/res/values-sv/strings.xml index 2c4e004..03400a1 100644 --- a/main/res/values-sv/strings.xml +++ b/main/res/values-sv/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo kompass</string> @@ -53,6 +53,7 @@ <string name="wp_pkg">Parkeringsplats</string> <string name="wp_trailhead">Stigstart</string> <string name="wp_waypoint">Referensplats</string> + <string name="wp_original">Ursprungliga koordinater</string> <!-- logs --> <string name="log_found">Hittad</string> @@ -72,9 +73,12 @@ <string name="log_maintenance_needed">Behöver underhåll</string> <string name="log_update">Uppdaterade koordinaterna</string> <string name="log_archived">Arkiverad</string> + <string name="log_unarchived">Återöppnad</string> <string name="log_needs_archived">Behöver arkiveras</string> <string name="log_discovered">Såg den</string> <string name="log_reviewer">Meddelande från reviewern</string> + <string name="log_retractlisting">Återkallad</string> + <string name="log_marked_missing">Markerad saknad</string> <string name="log_tb_nothing">Gör inget</string> <string name="log_tb_visit">Besök</string> <string name="log_tb_drop">Lämna här</string> @@ -87,9 +91,6 @@ <string name="log_post_no_rate">Posta logg utan betyg</string> <string name="log_post_not_possible">Laddar loggningssida…</string> <string name="log_add">Lägg till</string> - <string name="log_date">Datum</string> - <string name="log_time">Tid</string> - <string name="log_date_time">Datum & tid</string> <string name="log_rating">Betyg</string> <string name="log_no_rating">Inget betyg</string> <string name="log_stars_1">1 stjärna</string> @@ -139,8 +140,6 @@ <string name="err_license">Du har inte bekräftat licensavtalet med Geocaching.com, så c:geo kan inte läsa in koordinater för cacherna.</string> <string name="err_unpublished">Den sökta cachen är opubliserad.</string> <string name="err_premium_only">Cachen är enbart för premium medlemmar på Geocaching.com.</string> - <string name="err_store">Tyvärr kan c:geo inte spara cachen.</string> - <string name="err_drop">Tyvärr kan c:geo inte ta bort cachen.</string> <string name="err_detail_open">Tyvärr kan c:geo inte visa detaljer om geocachen.</string> <string name="err_detail_cache">Tyvärr kan c:geo inte visa den geocache du önskar. Är det verkligen en geocache?</string> <string name="err_detail_cache_find">Tyvärr kan c:geo inte hitta geocache</string> @@ -153,39 +152,29 @@ <string name="err_detail_no_spoiler">c:geo hittade inga spoiler bilder för den här cachen.</string> <string name="err_detail_no_map_static">c:geo hittade inga sparade kartor för denna cache.</string> <string name="err_detail_not_load_map_static">Tyvärr misslyckades c:geo att ladda sparade kartor.</string> - <string name="err_detail_ask_store_map_static">c:geo kunde inte läsa in statiska kartor. Ladda ner nu?</string> <string name="err_detail_still_working">Arbetar fortfarande med annat.</string> <string name="err_watchlist_still_managing">Hanterar fortfarande din watchlist.</string> <string name="err_watchlist_failed">Hanteringen av din watchlist misslyckades.</string> - <string name="err_navigation_no">c:geo kan inte hitta något stöd för navigering.</string> <string name="err_application_no">c:geo kan inte hitta något lämpligt program.</string> <string name="err_auth_initialize">Tyvärr misslyckades c:geo att starta inloggningsproceduren.</string> <string name="err_auth_process">Inloggningsproceduren misslyckades.</string> <string name="err_cannot_log_visit">c:geo har inte tillräckligt med information för att logga ditt besök. Vänligen försök igen från vyn men all information om cachen.</string> <string name="err_init_cleared">Tyvärr kan c:geo inte rensa inloggningsinställningarna.</string> <string name="err_download_fail">Tyvärr misslyckades c:geo att ladda ner cacher pga</string> - <string name="err_list_load_fail">Tyvärr misslyckades c:geo att ladda listan med cacher.</string> - <string name="err_store_failed">Tyvärr kan c:geo inte spara geocachen.</string> - <string name="err_refresh_failed">Tyvärr kan c:geo inte uppdatera geocachen.</string> <string name="err_dwld_details_failed">Tyvärr misslyckades c:geo att ladda detaljer.</string> <string name="err_load_descr_failed">Tyvärr kan c:geo inte ladda beskrivningen.</string> <string name="err_location_unknown">c:geo har inte koordinaterna för cachen.</string> <string name="err_missing_device_name">Vänligen ange ett namn för din enhet innan registering.</string> + <string name="err_favorite_failed">Misslyckades att ändra favoritstatus.</string> <string name="err_tb_display">Tyvärr kan c:geo inte visa den trackable du önskar. Är den verkligen trackable?</string> <string name="err_tb_details_open">Tyvärr kan c:geo inte öppna detaljer för trackable.</string> - <string name="err_tb_details_download">Tyvärr misslyckades c:geo att ladda ner detaljer för trackable pga</string> - <string name="err_tb_forgot">Tyvärr glömde c:geo vilken trackable önskade.</string> <string name="err_tb_forgot_saw">Tyvärr glömde c:geo vilken trackable du såg.</string> <string name="err_tb_find">Tyvärr kunde c:geo inte hitta trackable</string> <string name="err_tb_find_that">Tyvärr kan c:geo inte hitta önskad trackable.</string> <string name="err_waypoint_cache_unknown">Tyvärr vet inte c:geo till vilken cache du vill lägga till en punkt.</string> - <string name="err_waypoint_unknown">Tyvärr glömde c:geo vilken punkt du ville visa.</string> <string name="err_waypoint_add_failed">Tyvärr misslyckades c:geo att lägga till din punkt.</string> - <string name="err_waypoint_load_failed">Tyvärr misslyckades c:geo att ladda punkten.</string> - <string name="err_waypoint_delete_failed">Tyvärr kan c:geo inte ta bort punkten.</string> - <string name="err_waypoint_open_cache_failed">c:geo kan inte öppna beskrivningen av cachen.</string> <string name="err_point_unknown_position">Tyvärr kan c:geo inte bestämma din position.</string> <string name="err_point_no_position_given_title">Mer info krävs</string> <string name="err_point_no_position_given">Ange minst latitud och longitud eller avstånd och riktning. Du kan också ange alla fyra.</string> @@ -200,15 +189,12 @@ <string name="err_log_failed_server">Tyvärr misslyckades c:geo att posta loggen eftersom servern inte svarade.</string> <string name="err_log_post_failed">Tyvärr misslyckades c:geo att posta loggen.</string> - <string name="err_search_address_no_match">Tyvärr hittade c:geo ingen plats som stämde.</string> <string name="err_search_address_forgot">Tyvärr glömde c:geo adressen du sökte efter.</string> <string name="err_parse_lat">Tyvärr kan c:geo inte tolka latitud.</string> <string name="err_parse_lon">Tyvärr kan c:geo inte tolka longitud.</string> <string name="err_parse_dist">Tyvärr kan c:geo inte tolka avstånd.</string> <string name="err_parse_lat_lon">Tyvärr kan c:geo inte tolka latitud eller longitud.</string> - <string name="err_fieldnotes_export_failed">Exportering av Field Notes misslyckades.</string> - <string name="warn_save_nothing">Det finns inget att spara.</string> <string name="warn_no_cache_coord">Det finns inga koordinater för cachen.</string> <string name="warn_no_coordinates">Inga koordinater angivna.</string> @@ -232,7 +218,6 @@ <string name="info_log_cleared">Loggen har rensats.</string> <string name="info_log_type_changed">Typen av logg har ändrats!</string> - <string name="info_fieldnotes_exported_to">Field Notes har exporterats till</string> <string name="info_storing_static_maps">Försöker ladda ner statiska kartor</string> <!-- location service --> @@ -305,6 +290,7 @@ <string name="caches_drop_stored">Ta bort sparade</string> <string name="caches_drop_progress">Tar bort cacher</string> <string name="caches_drop_all_and_list">Ta bort listan och dess cacher</string> + <string name="caches_delete_events">Ta bort gamla event</string> <string name="caches_refresh_selected">Uppdatera valda</string> <string name="caches_refresh_all">Uppdatera alla</string> <string name="caches_move_selected">Flytta valda</string> @@ -321,10 +307,7 @@ <string name="caches_filter_type">Typ</string> <string name="caches_filter_track">Med trackables</string> <string name="caches_filter_clear">Rensa filter</string> - <string name="caches_filter_size_title">Välj storlek</string> - <string name="caches_filter_type_title">Välj typ</string> <string name="caches_filter_modified">Med tillagda koordinater</string> - <string name="caches_exporting_fieldnote">Exporterar som Field Notes…</string> <string name="caches_removing_from_history">Tar bort från historik…</string> <!-- caches lists --> @@ -360,6 +343,10 @@ <!-- init --> <string name="init_geocaching">Geocaching.com</string> + <string name="init_oc">opencaching.de</string> + <string name="init_oc_activate">Aktivera opencaching.de i live-kartor och sökningar</string> + <string name="init_oc_username_description">Ange användarnamn till opencaching.de för att kunna markera dina hittade cacher.</string> + <string name="init_oc_username">Ange ditt användarnamn</string> <string name="init_gcvote">GCvote.com</string> <string name="init_twitter">Twitter</string> <string name="init_username">Användare</string> @@ -403,7 +390,6 @@ <string name="init_offline_wp">Spara kartor för extra punkter för användning offline</string> <string name="init_save_log_img">Spara bilder från loggar</string> <string name="init_units">Använd amerikanska enheter för avstånd</string> - <string name="init_nav">Använd Google Navigering</string> <string name="init_log_offline">Vid loggning: spara bara loggen lokalt (visa inte loggningfönster och skicka inte loggen till gc.com)</string> <string name="init_livelist">Visa riktning till cacher i listan</string> <string name="init_altitude">Höjd justering</string> @@ -425,19 +411,13 @@ <string name="init_backup_last">Tillgänglig kopia från</string> <string name="init_backup_last_no">Det finns ingen säkerhetskopia.</string> <string name="init_mapsources">Kartkällor</string> - <string name="init_mapsources_description">Här kan du vilken typ av kartor du vill använda. Som alternativ till Google Maps finns olika varianter av OpenStreetMap och till och med offline kartor (se <a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a> för detaljer).</string> + <string name="init_mapsources_description">Här kan du vilken typ av kartor du vill använda. Som alternativ till Google Maps finns olika varianter av OpenStreetMap och till och med offline kartor (se <a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a> för detaljer). Ytterligare valbara teman stödjs också.</string> <string name="init_mapsource_select">Välj kartkälla</string> - <string name="init_select_themefolder">…</string> <string name="init_map_directory_description">Katalog med offline kartor</string> - <string name="init_select_map_directory">…</string> - <string name="init_select_gpx_exportdir">…</string> - <string name="init_select_gpx_importdir">…</string> <string name="init_gpx_exportdir">GPX-exportkatalog</string> <string name="init_gpx_importdir">GPX-importkatalog</string> <string name="init_gpx_exportdir_description">Här kan du välja katalog för GPX-exporteringar.</string> <string name="init_gpx_importdir_description">Här kan du välja katalog för GPX-importeringar.</string> - <string name="init_gpx_exportdir_select">Välj katalog för GPX-export</string> - <string name="init_gpx_importdir_select">Välj katalog för GPX-import</string> <string name="init_maptrail">Visa spår på kartan</string> <string name="init_share_after_export">Visa meny för att dela efter slutförd exportering</string> <string name="init_trackautovisit">Sätt trackable automatiskt till \"besök\" vid loggning av en cache</string> @@ -453,14 +433,13 @@ <string name="init_dbonsdcard_title">Databasplacering</string> <string name="init_dbonsdcard_note">Du kan placera c:geos databas på ditt minneskort. På detta sätt kan du spara internminne, men du kan också få något sämre prestanda och c:geo kommer inte fungera om ditt minneskort inte är tillgängligt (exempelvis när den är kopplad till en dator).</string> <string name="init_dbonsdcard">Databas på minneskort</string> - <string name="init_dbmove">Flyttar databasen</string> <string name="init_dbmove_dbmove">Flyttar databasen</string> <string name="init_dbmove_running">Flyttar databasen</string> <string name="init_dbmove_success">Databasen har ny flyttats.</string> <string name="init_dbmove_failed">Misslyckades att flytta databasen</string> <string name="init_plain_logs">Visa loggar utan färger</string> <string name="init_use_native_ua">Identifiera som en Android webbläsare. Löser problem med inloggning vid uppkoppling via vissa operatörer.</string> - <string name="init_rendertheme_folder">Välj katalog för egna offline kartteman</string> + <string name="init_rendertheme_folder">Katalog för offline kartteman (valfritt)</string> <!-- map sources --> <string name="map_source_google_map">Google: Map</string> @@ -513,7 +492,6 @@ <string name="cache_offline_time_days">dagar sedan</string> <string name="cache_premium">Premium</string> <string name="cache_attributes">Attribut</string> - <string name="cache_attributes_no_icons">(uppdatera cachen för att visa bilder för attribut)</string> <string name="cache_inventory">Innehåll</string> <string name="cache_log_offline">Offline logg</string> <string name="cache_log_images_loading">Laddar loggbilder…</string> @@ -524,7 +502,6 @@ <string name="cache_description">Beskrivning</string> <string name="cache_description_long">Lång beskrivning</string> <string name="cache_description_table_note">Varning från c:geo! Beskrivningen innehåller HTML-tabeller som eventuellt kan behöva öppnas i en webbläsare för att visas på önskat sätt.</string> - <string name="cache_watchlist">Watchlist</string> <string name="cache_watchlist_on">Den här cachen finns i din watchlist.</string> <string name="cache_watchlist_not_on">Den här cachen finns inte i din watchlist.</string> <string name="cache_watchlist_add">Lägg till i watchlist</string> @@ -564,8 +541,14 @@ <string name="cache_dialog_watchlist_add_message">Lägger till cachen till din watchlist…</string> <string name="cache_dialog_watchlist_remove_title">Watchlist</string> <string name="cache_dialog_watchlist_remove_message">Tar bort cachen från din watchlist…</string> + <string name="cache_dialog_favourite_add_title">Favorit</string> + <string name="cache_dialog_favourite_add_message">Lägger till cachen till dina favoriter…</string> + <string name="cache_dialog_favourite_remove_title">Favorit</string> + <string name="cache_dialog_favourite_remove_message">Tar bort cachen från dina favoriter…</string> <string name="cache_menu_navigate">Navigera</string> - <string name="cache_menu_tbt">Sväng-för-sväng</string> + <string name="cache_menu_navigation_drive">Navigering (med bil)</string> + <string name="cache_menu_navigation_walk">Navigering (till fots)</string> + <string name="cache_menu_maps_directions">Google Maps Navigering</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Visa på karta</string> <string name="cache_menu_map_static">Sparade kartor</string> @@ -578,6 +561,8 @@ <string name="cache_menu_visit_offline">Logga besök offline</string> <string name="cache_menu_spoilers">Spoiler bilder</string> <string name="cache_menu_around">Cacher i närheten</string> + <string name="cache_menu_set_as_cache_coords">Sätt som cachens koordinater</string> + <string name="cache_menu_upload_wpt_to_gc_com">Sätt som cachens koordinater och ladda upp waypoint till Geocaching.com</string> <string name="cache_menu_event">Lägg till i kalender</string> <string name="cache_menu_details">Detaljer</string> <string name="cache_menu_share">Skicka länk</string> @@ -592,6 +577,7 @@ <string name="cache_status_archived">Arkiverad</string> <string name="cache_status_disabled">Inaktiverad</string> <string name="cache_status_premium">Enbart för Premium medlemmar</string> + <string name="cache_status_not_premium">Tillgänglig för alla medlemmar</string> <string name="cache_geocode">GC-kod</string> <string name="cache_name">Namn</string> <string name="cache_type">Typ</string> @@ -615,7 +601,6 @@ <string name="cache_images_loading">Laddar bilder…</string> <string name="cache_log_types">Loggtyper</string> <string name="cache_coordinates_no">Cachen saknar koordinater.</string> - <string name="cache_export_fieldnote">Exportera som Field Notes</string> <string name="cache_clear_history">Rensa historik</string> <string name="cache_remove_from_history">Ta bort från historik</string> <string name="cache_license">Licens</string> @@ -643,7 +628,6 @@ <string name="gpx_import_loading_caches">Läser in cacher från .gpx filen</string> <string name="gpx_import_loading_waypoints">Läser in punkter från .gpx file</string> <string name="gpx_import_store_static_maps">Sparar kartor</string> - <string name="gpx_import_storing">Skriver cacher till databasen</string> <string name="gpx_import_caches_imported">cacher importerade</string> <string name="gpx_import_static_maps_skipped">Hämtningen av kartor avbröts</string> <string name="gpx_import_title_static_maps">Sparar kartor</string> @@ -652,7 +636,7 @@ <string name="gpx_import_title_caches_imported">Resultat</string> <string name="gpx_import_title_caches_import_failed">Importeringen misslyckades</string> <string name="gpx_import_error_io">Kan inte läsa filen</string> - <string name="gpx_import_error_parser">Filens format är felaktigt</string> + <string name="gpx_import_error_parser">Felaktigt filformat</string> <string name="gpx_import_error_unexpected">Oväntat fel</string> <string name="gpx_import_confirm">Vill du importera GPX filen till c:geo?</string> <string name="gpx_import_canceled">Importeringen av GPX filen avbröts</string> @@ -663,10 +647,7 @@ <string name="map_file_select_title">Välj kartfil</string> <!-- theme file select --> - <string name="theme_file_select_title">Välj fil med egna anpassningar för karttema</string> - <!-- import --> - <string name="import_title">Importerar…</string> <string name="web_import_title">Importerar från webben</string> <string name="web_import_waiting">Väntar på nya cacher från webben…</string> <string name="web_downloading">Laddar ner</string> @@ -677,7 +658,6 @@ <!-- waypoint --> <string name="waypoint">Punkt</string> - <string name="waypoint_title">Punkt</string> <string name="waypoint_cache_coordinates">Cache koordinater</string> <string name="waypoint_custom">Egen</string> <string name="waypoint_my_coordinates">Mina koordinater</string> @@ -691,11 +671,25 @@ <string name="waypoint_note">Kommentar</string> <string name="waypoint_save">Spara</string> <string name="waypoint_loading">Laddar punkt…</string> - <string name="waypoint_unknown_coordinates">Koordinaterna ogiltiga</string> + <string name="waypoint_do_not_touch_cache_coordinates">Ingen förändring av cachens koordinater</string> + <string name="waypoint_set_as_cache_coords">Ange som cachens koordinater i c:geo</string> + <string name="waypoint_save_and_modify_on_website">Ange som cachens koordinater i c:geo och på hemsidan</string> + <string name="waypoint_reset_cache_coords">Återställ cachens koordinater</string> + <string name="waypoint_coordinates_has_been_reset_on_website">Cachens koordinater har återställts på hemsidan.</string> + <string name="waypoint_coordinates_being_reset_on_website">Återställer cachens koordinater på hemsidan…</string> + <string name="waypoint_reset_cache_coords_info">Återställningsalternativ</string> + <string name="waypoint_reset">Återställ</string> + <string name="waypoint_localy_reset_cache_coords">Återställ koordinaterna i c:geo</string> + <string name="waypoint_reset_local_and_remote_cache_coords">Återställ i c:geo och på hemsidan</string> + <string name="waypoint_coordinates_couldnt_be_modified_on_website">Hemsidan kan inte hantera att ändra cachens koordinater.</string> + <string name="waypoint_coordinates_upload_error">Ett fel inträffade när koordinaterna skulle ändras på hemsidan.</string> + <string name="waypoint_coordinates_uploading_to_website">Laddar upp koordinaterna %s till hemsidan.</string> + <string name="waypoint_coordinates_reseting_on_website">Återställer till ursprungliga koordinaterna på hemsidan.</string> + <string name="waypoint_coordinates_has_been_modified_on_website">Cachens koordinater på hemsidan har ändrats till: %s.</string> + <string name="waypoint_coordinates_has_been_set_as_cache_coordinates">Cachens koordinater har ändrats i c:geo till: %s.</string> <string name="waypoint_done">Klar</string> <string name="waypoint_duplicate">Duplicera</string> <string name="waypoint_copy_of">Kopia av</string> - <string name="waypoint_menu_open_cache">Visa cache</string> <string name="search_history">Historik</string> <string name="search_history_empty">Inga tidigare målpunkter</string> <string name="search_remove_destination">Punkten borttagen</string> @@ -716,7 +710,7 @@ <string name="map_trail_hide">Dölj spår</string> <string name="map_circles_show">Visa cirklar</string> <string name="map_circles_hide">Dölj cirklar</string> - <string name="map_theme_builtin">Inbyggt karttema</string> + <string name="map_theme_builtin">Standard</string> <string name="map_theme_select">Välj karttema</string> <string name="map_live_enable">Aktivera live</string> <string name="map_live_disable">Inaktivera live</string> @@ -826,7 +820,6 @@ <!-- export --> <string name="export">Exportera</string> - <string name="export_as">Exportera som…</string> <string name="export_exportedto">exporterat till</string> <string name="export_failed">Exporteringen misslyckades</string> <string name="export_fieldnotes">Field Notes</string> @@ -851,11 +844,11 @@ <string name="about_auth_2">Klicka på \"Påbörja koppling mot Twitter\" om du vill koppla ihop <b>c:geo</b> med Twitter. Twitters hemsida kommer att öppnas i en webbläsare. Logga in på den sidan och tillåt <b>c:geo</b> att ansluta till ditt konto. När du godkänt så kommer Twitter att visa en PIN kod. Kom ihåg denna PIN kod, stäng webbläsaren och skriv in PIN koden i <b>c:geo</b> och bekräfta.</string> <!-- status --> - <string name="status_new_release">Ny officiell version finns tillgänglig.\nKlicka för att installera.</string> - <string name="status_new_nightly">Nytt nattligt bygge finns tillgängligt.\nKlicka för att installera.</string> - <string name="status_new_rc">Ny kandidat till officiellt bygge finns tillgängligt.\nKlicka för att installera.</string> - <string name="status_geocaching_change">Ändringar som gjorts på geocaching.com har gjort så att c:geo inte fungerar.\nVi jobbar för att lösa problemen, försök igen om en stund.</string> - <string name="status_geocaching_livemap">Ändringar som gjorts på geocaching.com har gjort så att Live kartan inte fungerar.\nVi jobbar för att lösa problemen, försök igen om en stund.</string> + <string name="status_new_release" tools:ignore="UnusedResources">Ny officiell version finns tillgänglig.\nKlicka för att installera.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">Nytt nattligt bygge finns tillgängligt.\nKlicka för att installera.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">Ny kandidat till officiellt bygge finns tillgängligt.\nKlicka för att installera.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">Ändringar som gjorts på geocaching.com har gjort så att c:geo inte fungerar.\nVi jobbar för att lösa problemen, försök igen om en stund.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Ändringar som gjorts på geocaching.com har gjort så att Live kartan inte fungerar.\nVi jobbar för att lösa problemen, försök igen om en stund.</string> <string name="clipboard_copy_ok">Kopierat till urklipp.</string> <plurals name="days_ago"> diff --git a/main/res/values/cache_attributes.xml b/main/res/values/cache_attributes.xml index 3277a42..815e007 100644 --- a/main/res/values/cache_attributes.xml +++ b/main/res/values/cache_attributes.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <resources> - <string-array name="attribute_ids"> + <string-array name="attribute_ids" translatable="false"> <item>dogs_yes</item> <item>dogs_no</item> <item>bicycles_yes</item> diff --git a/main/res/values/colors.xml b/main/res/values/colors.xml index 7289bc7..5a5c4ac 100644 --- a/main/res/values/colors.xml +++ b/main/res/values/colors.xml @@ -9,8 +9,6 @@ <color name="background_light_notice">#FFDFDFDF</color> <color name="background_dark_transparent">#44000000</color> <color name="background_light_transparent">#44FFFFFF</color> - <color name="owncache_background_dark">#FF222222</color> - <color name="owncache_background_light">#FFDDDDDD</color> <color name="separator_dark">#44FFFFFF</color> <color name="separator_light">#44000000</color> <color name="text_icon">#FFFFFFFF</color> diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index 6384bbd..9831059 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> <string name="app_name_compass">c:geo compass</string> @@ -53,6 +53,7 @@ <string name="wp_pkg">Parking Area</string> <string name="wp_trailhead">Trailhead</string> <string name="wp_waypoint">Reference Point</string> + <string name="wp_original">Original Coordinates</string> <!-- logs --> <string name="log_found">Found it</string> @@ -77,6 +78,7 @@ <string name="log_discovered">Discovered</string> <string name="log_reviewer">Reviewer Note</string> <string name="log_retractlisting">Retract Listing</string> + <string name="log_marked_missing">Marked Missing</string> <string name="log_tb_nothing">Do Nothing</string> <string name="log_tb_visit">Visited</string> <string name="log_tb_drop">Dropped Off</string> @@ -89,9 +91,6 @@ <string name="log_post_no_rate">Submit Log & Do not Rate</string> <string name="log_post_not_possible">Loading Log Page…</string> <string name="log_add">Add</string> - <string name="log_date">Date</string> - <string name="log_time">Time</string> - <string name="log_date_time">Date & Time</string> <string name="log_rating">Rating</string> <string name="log_no_rating">No rating</string> <string name="log_stars_1">1 Star</string> @@ -141,8 +140,6 @@ <string name="err_license">You have not agreed to Geocaching.com license agreement, so c:geo can\'t load cache coordinates.</string> <string name="err_unpublished">The requested cache is unpublished.</string> <string name="err_premium_only">This Cache is only available to Geocaching.com Premium Members.</string> - <string name="err_store">c:geo can\'t store the cache.</string> - <string name="err_drop">c:geo can\'t drop cache.</string> <string name="err_detail_open">c:geo can\'t open geocache details.</string> <string name="err_detail_cache">c:geo can\'t display the geocache you want. Is it really a geocache?</string> <string name="err_detail_cache_find">c:geo can\'t find geocache</string> @@ -155,39 +152,29 @@ <string name="err_detail_no_spoiler">c:geo found no spoiler images for this cache.</string> <string name="err_detail_no_map_static">c:geo found no static maps for this cache.</string> <string name="err_detail_not_load_map_static">c:geo failed to load static maps.</string> - <string name="err_detail_ask_store_map_static">c:geo failed to load static maps. Store now?</string> <string name="err_detail_still_working">Still working on another task.</string> <string name="err_watchlist_still_managing">Still managing your watchlist.</string> <string name="err_watchlist_failed">Changing your watchlist failed.</string> - <string name="err_navigation_no">c:geo can\'t find any supported navigation.</string> <string name="err_application_no">c:geo can\'t find any suitable application.</string> <string name="err_auth_initialize">c:geo failed to initialize authorization process.</string> <string name="err_auth_process">Authorization process failed.</string> <string name="err_cannot_log_visit">c:geo is unable to log your visit. Please log your visit from full cache details screen.</string> <string name="err_init_cleared">c:geo can\'t clear login information.</string> <string name="err_download_fail">c:geo failed to download caches.</string> - <string name="err_list_load_fail">c:geo failed to load cache list.</string> - <string name="err_store_failed">c:geo can\'t store geocache.</string> - <string name="err_refresh_failed">c:geo can\'t refresh geocache.</string> <string name="err_dwld_details_failed">c:geo failed to download cache details.</string> <string name="err_load_descr_failed">c:geo can\'t load description.</string> <string name="err_location_unknown">c:geo doesn\'t know location of cache.</string> <string name="err_missing_device_name">Please enter a device name before registering.</string> - + <string name="err_favorite_failed">Changing favorite status failed.</string> + <string name="err_tb_display">c:geo can\'t display trackable you want. Is it really a trackable?</string> <string name="err_tb_details_open">c:geo can\'t open trackable details.</string> - <string name="err_tb_details_download">c:geo failed to download trackable details.</string> - <string name="err_tb_forgot">c:geo forgot which trackable you want.</string> <string name="err_tb_forgot_saw">c:geo forgot which trackable you saw.</string> <string name="err_tb_find">c:geo can\'t find trackable</string> <string name="err_tb_find_that">c:geo can\'t find that trackable.</string> <string name="err_waypoint_cache_unknown">c:geo doesn\'t know to which cache you want to add waypoint.</string> - <string name="err_waypoint_unknown">c:geo forgot what waypoint you want to display.</string> <string name="err_waypoint_add_failed">c:geo failed to add your waypoint.</string> - <string name="err_waypoint_load_failed">c:geo failed to load waypoint.</string> - <string name="err_waypoint_delete_failed">c:geo can\'t delete waypoint.</string> - <string name="err_waypoint_open_cache_failed">c:geo can\'t open cache details.</string> <string name="err_point_unknown_position">c:geo can\'t recognize where you are.</string> <string name="err_point_no_position_given_title">Info required</string> <string name="err_point_no_position_given">Fill at least latitude or longitude or distance and bearing. You can also fill all four fields.</string> @@ -202,15 +189,12 @@ <string name="err_log_failed_server">c:geo failed to post log because server is not responding.</string> <string name="err_log_post_failed">It seems that your log was not posted. Please check it on Geocaching.com.</string> - <string name="err_search_address_no_match">c:geo found no matching place.</string> <string name="err_search_address_forgot">c:geo forgot the address you tried to find.</string> <string name="err_parse_lat">c:geo can\'t parse latitude.</string> <string name="err_parse_lon">c:geo can\'t parse longitude.</string> <string name="err_parse_dist">c:geo can\'t parse distance.</string> <string name="err_parse_lat_lon">c:geo can\'t parse latitude or longitude.</string> - <string name="err_fieldnotes_export_failed">Export of Field Notes failed.</string> - <string name="warn_save_nothing">There is nothing to be saved.</string> <string name="warn_no_cache_coord">There is no cache with coordinates.</string> <string name="warn_no_coordinates">No Coordinates given.</string> @@ -235,7 +219,6 @@ <string name="info_log_cleared">Log was cleared.</string> <string name="info_log_type_changed">Type of log has been changed!</string> - <string name="info_fieldnotes_exported_to">Field Notes exported to</string> <string name="info_storing_static_maps">Trying to store static maps</string> <!-- location service --> @@ -308,6 +291,7 @@ <string name="caches_drop_stored">Drop stored</string> <string name="caches_drop_progress">Removing caches</string> <string name="caches_drop_all_and_list">Drop all and remove list</string> + <string name="caches_delete_events">Delete past events</string> <string name="caches_refresh_selected">Refresh selected</string> <string name="caches_refresh_all">Refresh all</string> <string name="caches_move_selected">Move selected</string> @@ -324,10 +308,7 @@ <string name="caches_filter_type">Type</string> <string name="caches_filter_track">With Trackables</string> <string name="caches_filter_clear">Clear filters</string> - <string name="caches_filter_size_title">Choose size</string> - <string name="caches_filter_type_title">Choose type</string> <string name="caches_filter_modified">With modified coordinates</string> - <string name="caches_exporting_fieldnote">Exporting as Field Notes…</string> <string name="caches_removing_from_history">Removing from History…</string> <!-- caches lists --> @@ -363,6 +344,10 @@ <!-- init --> <string name="init_geocaching">Geocaching.com</string> + <string name="init_oc">opencaching.de</string> + <string name="init_oc_activate">Activate opencaching.de on live-map and in searches</string> + <string name="init_oc_username_description">Enter your opencaching.de user name in order to allow marking your finds.</string> + <string name="init_oc_username">Enter your user name</string> <string name="init_gcvote">GCvote.com</string> <string name="init_twitter">Twitter</string> <string name="init_username">Username</string> @@ -406,7 +391,6 @@ <string name="init_offline_wp">Store waypoints static maps for offline use</string> <string name="init_save_log_img">Save Images from Logs</string> <string name="init_units">Use Imperial Units instead of Metric Units</string> - <string name="init_nav">Use Google Navigation</string> <string name="init_log_offline">Enable Offline Logging\n(Don\'t show online Log screen when logging, don\'t send the Log online)</string> <string name="init_livelist">Show Direction to caches in the list</string> <string name="init_altitude">Altitude Correction</string> @@ -430,17 +414,11 @@ <string name="init_mapsources">Map Sources</string> <string name="init_mapsources_description">Here you can select the source for your maps. As an alternative to Google maps various OpenStreetMap styles are available and even offline map files (See <a href="http://code.google.com/p/mapsforge/">http://code.google.com/p/mapsforge/</a> for details).\nFurthermore selectable themes for offline maps are supported.</string> <string name="init_mapsource_select">Select Map Source</string> - <string name="init_select_themefolder">…</string> <string name="init_map_directory_description">Directory with offline maps</string> - <string name="init_select_map_directory">…</string> - <string name="init_select_gpx_exportdir">…</string> - <string name="init_select_gpx_importdir">…</string> <string name="init_gpx_exportdir">GPX Export Directory</string> <string name="init_gpx_importdir">GPX Import Directory</string> <string name="init_gpx_exportdir_description">Here you can select the directory for GPX exports.</string> <string name="init_gpx_importdir_description">Here you can select the directory for GPX imports.</string> - <string name="init_gpx_exportdir_select">Select GPX Export Directory</string> - <string name="init_gpx_importdir_select">Select GPX Import Directory</string> <string name="init_maptrail">Show trail on Map</string> <string name="init_share_after_export">Open share menu after GPX export</string> <string name="init_trackautovisit">Set trackables to \"Visited\" as a default</string> @@ -456,7 +434,6 @@ <string name="init_dbonsdcard_title">Database location</string> <string name="init_dbonsdcard_note">You may store the database of c:geo on the external storage medium. If you do so you will save internal memory, but you may loose a bit of performance and c:geo will not work if your sdcard is not available.</string> <string name="init_dbonsdcard">Database on external storage</string> - <string name="init_dbmove">Moving Database</string> <string name="init_dbmove_dbmove">Moving Database</string> <string name="init_dbmove_running">Moving Database</string> <string name="init_dbmove_success">Successfully moved the database.</string> @@ -466,13 +443,6 @@ <string name="init_rendertheme_folder">Directory with custom offline map themes (optional)</string> <!-- map sources --> - <string-array name="map_sources"> - <item>@string/map_source_google_map</item> - <item>@string/map_source_google_satellite</item> - <item>@string/map_source_osm_mapnik</item> - <item>@string/map_source_osm_cyclemap</item> - <item>@string/map_source_osm_offline</item> - </string-array> <string name="map_source_google_map">Google: Map</string> <string name="map_source_google_satellite">Google: Satellite</string> <string name="map_source_osm_mapnik">OSM: Mapnik</string> @@ -523,7 +493,6 @@ <string name="cache_offline_time_days">days ago</string> <string name="cache_premium">Premium</string> <string name="cache_attributes">Attributes</string> - <string name="cache_attributes_no_icons">(refresh cache to show attribute icons)</string> <string name="cache_inventory">Inventory</string> <string name="cache_log_offline">Offline Log</string> <string name="cache_log_images_loading">Loading Log images…</string> @@ -534,7 +503,6 @@ <string name="cache_description">Description</string> <string name="cache_description_long">Long Description</string> <string name="cache_description_table_note">Description contains table formatting which may need to be viewed at geocaching.com to be seen correctly.</string> - <string name="cache_watchlist">Watchlist</string> <string name="cache_watchlist_on">This cache is on your watchlist.</string> <string name="cache_watchlist_not_on">This cache is not on your watchlist.</string> <string name="cache_watchlist_add">Add to Watchlist</string> @@ -574,8 +542,14 @@ <string name="cache_dialog_watchlist_add_message">Adding cache to your watchlist…</string> <string name="cache_dialog_watchlist_remove_title">Watchlist</string> <string name="cache_dialog_watchlist_remove_message">Removing cache from your watchlist…</string> + <string name="cache_dialog_favourite_add_title">Favourite</string> + <string name="cache_dialog_favourite_add_message">Adding cache to your favourites…</string> + <string name="cache_dialog_favourite_remove_title">Favourite</string> + <string name="cache_dialog_favourite_remove_message">Removing cache from your favourites…</string> <string name="cache_menu_navigate">Navigate</string> - <string name="cache_menu_tbt">Turn-by-Turn</string> + <string name="cache_menu_navigation_drive">Navigation (Driving)</string> + <string name="cache_menu_navigation_walk">Navigation (Walking)</string> + <string name="cache_menu_maps_directions">Google Maps Directions</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Map</string> <string name="cache_menu_map_static">Static Maps</string> @@ -588,6 +562,8 @@ <string name="cache_menu_visit_offline">Log Visit offline</string> <string name="cache_menu_spoilers">Spoiler images</string> <string name="cache_menu_around">Caches around</string> + <string name="cache_menu_set_as_cache_coords">Set as cache coords</string> + <string name="cache_menu_upload_wpt_to_gc_com">Set as cache coords and upload waypoint to Geocaching.com</string> <string name="cache_menu_event">Add to calendar</string> <string name="cache_menu_details">Details</string> <string name="cache_menu_share">Share cache</string> @@ -627,7 +603,6 @@ <string name="cache_images_loading">Loading images…</string> <string name="cache_log_types">Log types</string> <string name="cache_coordinates_no">This cache has no coordinates.</string> - <string name="cache_export_fieldnote">Export as Field Notes</string> <string name="cache_clear_history">Clear history</string> <string name="cache_remove_from_history">Remove from history</string> <string name="cache_license">License</string> @@ -655,7 +630,6 @@ <string name="gpx_import_loading_caches">Loading caches from .gpx file</string> <string name="gpx_import_loading_waypoints">Loading waypoints file</string> <string name="gpx_import_store_static_maps">Storing static maps</string> - <string name="gpx_import_storing">Writing caches to database</string> <string name="gpx_import_caches_imported">caches imported</string> <string name="gpx_import_static_maps_skipped">Download of static maps aborted</string> <string name="gpx_import_title_static_maps">Store static maps</string> @@ -675,10 +649,7 @@ <string name="map_file_select_title">Select map file</string> <!-- theme file select --> - <string name="theme_file_select_title">Select custom map theme file</string> - <!-- import --> - <string name="import_title">Import…</string> <string name="web_import_title">Import from web</string> <string name="web_import_waiting">Waiting for new caches from web…</string> <string name="web_downloading">Downloading</string> @@ -689,7 +660,6 @@ <!-- waypoint --> <string name="waypoint">Waypoint</string> - <string name="waypoint_title">Waypoint</string> <string name="waypoint_cache_coordinates">Cache coordinates</string> <string name="waypoint_custom">Custom</string> <string name="waypoint_my_coordinates">My coordinates</string> @@ -703,33 +673,34 @@ <string name="waypoint_note">Note</string> <string name="waypoint_save">Save</string> <string name="waypoint_loading">Loading waypoint…</string> - <string name="waypoint_unknown_coordinates">Coordinates unknown</string> + <string name="waypoint_do_not_touch_cache_coordinates">No change to cache coordinates</string> + <string name="waypoint_set_as_cache_coords">Set as cache coordinates in c:geo</string> + <string name="waypoint_save_and_modify_on_website">Set as cache coordinates in c:geo and on website</string> + <string name="waypoint_reset_cache_coords">Reset cache coordinates</string> + <string name="waypoint_coordinates_has_been_reset_on_website">Cache coordinates have been reset on website.</string> + <string name="waypoint_coordinates_being_reset_on_website">Resetting cache coordinates on website…</string> + <string name="waypoint_reset_cache_coords_info">Coordinate reset options</string> + <string name="waypoint_reset">Reset</string> + <string name="waypoint_localy_reset_cache_coords">Reset in c:geo</string> + <string name="waypoint_reset_local_and_remote_cache_coords">Reset in c:geo and on website</string> + <string name="waypoint_coordinates_couldnt_be_modified_on_website">Website doesn\'t support modifying cache coordinates.</string> + <string name="waypoint_coordinates_upload_error">Error occurred while modifying coordinates on website.</string> + <string name="waypoint_coordinates_uploading_to_website">Uploading coordinates %s to website.</string> + <string name="waypoint_coordinates_reseting_on_website">Resetting to original coordinates on website.</string> + <string name="waypoint_coordinates_has_been_modified_on_website">Cache coordinates on website have been modified to: %s.</string> + <string name="waypoint_coordinates_has_been_set_as_cache_coordinates">Cache coordinates have been changed in c:geo to: %s.</string> <string name="waypoint_done">Done</string> <string name="waypoint_duplicate">Duplicate</string> <string name="waypoint_copy_of">Copy of</string> - <string name="waypoint_menu_open_cache">Open Cache</string> <string name="search_history">History</string> <string name="search_history_empty">No previous destinations</string> <string name="search_remove_destination">Destination removed</string> <string name="search_clear_history">Clear History</string> <string name="search_history_cleared">History cleared</string> - <string-array name="waypoint_coordinate_formats"> - <item>@string/waypoint_coordinate_formats_plain</item> - <item>DDD.DDDDD°</item> - <item>DDD°MM.MMM\'</item> - <item>DDD°MM\'SS.SSS\"</item> - </string-array> <string name="waypoint_coordinate_formats_plain">Plain</string> <!-- distance units --> - <string-array name="distance_units"> - <item>@string/unit_m</item> - <item>@string/unit_km</item> - <item>@string/unit_ft</item> - <item>@string/unit_yd</item> - <item>@string/unit_mi</item> - </string-array> <string name="unit_m">m</string> <string name="unit_km">km</string> <string name="unit_ft">ft</string> @@ -859,7 +830,6 @@ <!-- export --> <string name="export">Export</string> - <string name="export_as">Export as…</string> <string name="export_exportedto">exported to</string> <string name="export_failed">Export failed</string> <string name="export_fieldnotes">Field Notes</string> @@ -1029,164 +999,16 @@ <string name="about_auth_1">The following process allows <b>c:geo</b> to access Twitter - if agreed.</string> <string name="about_auth_2">A click on the \"authorize c:geo\" button will start the process. This process will open up a web browser with a Twitter page. Login on this page and allow <b>c:geo</b> to access your account. If this is accepted, Twitter will show up a numeric PIN code. This PIN must be pasted into <b>c:geo</b> and confirmed. That\'s all.</string> - <!-- status --> - <string name="status_new_release">New release available.\nClick to install.</string> - <string name="status_new_nightly">New nightly build available.\nClick to install.</string> - <string name="status_new_rc">New release candidate available.\nClick to install.</string> - <string name="status_geocaching_change">Recent changes on geocaching.com broke c:geo.\nWe are working on it, check again soon.</string> - <string name="status_geocaching_livemap">Recent changes on geocaching.com broke the live map feature.\nWe are working on it, check again soon.</string> + <!-- status (used via string based resource loading) --> + <string name="status_new_release" tools:ignore="UnusedResources">New release available.\nClick to install.</string> + <string name="status_new_nightly" tools:ignore="UnusedResources">New nightly build available.\nClick to install.</string> + <string name="status_new_rc" tools:ignore="UnusedResources">New release candidate available.\nClick to install.</string> + <string name="status_geocaching_change" tools:ignore="UnusedResources">Recent changes on geocaching.com broke c:geo.\nWe are working on it, check again soon.</string> + <string name="status_geocaching_livemap" tools:ignore="UnusedResources">Recent changes on geocaching.com broke the live map feature.\nWe are working on it, check again soon.</string> <string name="clipboard_copy_ok">Copied to clipboard</string> <plurals name="days_ago"> <item quantity="one">yesterday</item> <item quantity="other">%d days ago</item> </plurals> - - <!-- ====== please, do not translate (and include in translation) things below this line ====== --> - - <!-- contributors --> - <string name="contributors">\n - · <a href="http://carnero.cc/">carnero</a> as the father of c:geo\n - \n - · 0xErnie (localization DE)\n - · <a href="mailto:bazsy@freemail.hu">Balazs Szabo (Bazsy1983)</a> (loc. HU)\n - · Bananeweizen (code, loc. DE)\n - · blafoo (code, localization DE)\n - · Bonemaro (tester)\n - · BudBundi (localization DE, tester)\n - · campbeb (code)\n - · Charles (localization FR)\n - · Denny (localization DA)\n - · Eisbehr (code)\n - · F. Coello (localization ES)\n - · Filipe C. (code)\n - · <a href="http://www.hunterthornsberry.com">Hunter275</a> (tester)\n - · <a href="http://iirojappinen.com/">Iiro Jäppinen</a> (graphic)\n - · inkantis (localization PL)\n - · <a href="http://www.jaytech.cz/">Jan Žatecký</a> (graphic)\n - · <a href="http://joachim-wilke.de/">JoWi24</a> (code)\n - · <a href="http://github.com/koem">Karsten Priegnitz</a> (code, artwork computation)\n - · <a href="http://www.geocaching.com/email/?guid=d11a3e3d-7db0-4d43-87f2-7893238844a6">Lineflyer</a> (tester, support, localization DE)\n - · Ludovic Valente (localization FR)\n - · marco-jacob (code, loc. DE)\n - · MichielK (code, loc. NL)\n - · mucek4 (code, open source project leader)\n - · ncorreia (code, localization PT)\n - · Pascal (localization NL)\n - · Pavol Babinčák (code, loc. SK)\n - · Peter (localization HU)\n - · <a href="https://github.com/Portree-Kid">Portree Kid</a> (code)\n - · Rainer S. (code)\n - · Ray (code, loc. JA)\n - · <a href="http://seromenho.com/">Ricardo Seromenho</a> (localization PT)\n - · RoadRunner- (code, loc. DE)\n - · <a href="http://www.blueskysoftware.it/">RomNexus6</a> (localization IT)\n - · <a href="http://www.sammyshp.de/">SammysHP</a> (code, localization DE)\n - · <a href="http://www.rfc1149.net/sam.html">Samuel Tardieu</a> (code, localization FR)\n - · serenity (localization DE)\n - · Shan, a.k.a. ShakurNO (localization NO)\n - · Shizo87 (tester)\n - · stephanme/Geoteufel (code)\n - · thiasB (code, loc. DE EN)\n - · YraFyra (code, loc. SV)\n - · zenobios (code, loc. DE EN)\n - \n - · <a href="http://code.google.com/p/mapsforge/">Mapsforge</a> (OSM-rendering)\n - · <a href="http://thenounproject.com/">The Noun Project</a> (basis for attribute icons)\n - · <a href="http://commons.apache.org/">The Apache Commons Project</a>\n - · <a href="http://androidicons.com/">Android Icons</a> (<a href="https://creativecommons.org/licenses/by/3.0/">CC-BY 3.0</a>)\n - · <a href="http://rrze-icon-set.berlios.de/index.html">RRZE Icon set</a> (<a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA 3.0</a>)\n - </string> - - <!-- changelog --> - <string name="changelog">\n - <b>2013.01.10</b>\n\n - <b>Bugfixing:</b>\n - · Avoid crash in dir chooser\n - · Allow translation of cache description in case the app is forced to english\n - · Adapt to changes on gc.com (own and found caches)\n\n - <b>2013.01.07</b>\n\n - <b>Bugfixing:</b>\n - · Bad watchlist status detection\n - · Wrong cache count in cache list\n - · Failed filtering in nearby search\n - · Crash in history search when used with an old database\n - · Crash when using old OSM offline maps\n - · Crash when using OSM offline maps without sdcard\n - · Error when backing up the phone\n - · Problem with some caches in live maps\n - · Out of memory issues when loading large caches lists\n - · Error when scanning cache QR code\n - · Unspported multi-user mode\n - · Some hint pictures not shown\n - · Avoid crash when leaving nearby search before results are returned\n\n - <b>2012.12.18</b>\n\n - <b>Bugfixing:</b>\n - · Found caches not shown correctly for basic members\n - · Recognition of some special log types\n - · Correction in directory selector\n - · Corrected detection of premium caches in nearby search\n\n - <b>2012.12.12</b>\n\n - <b>New Features/Functions:</b>\n - · Opencaching.NL support in search function\n - <b>Bugfixing:</b>\n - · Adapting to geocaching.com changes\n\n - <b>2012.12.03</b>\n\n - <b>New Features/Functions:</b>\n - · If static maps are enabled, batch update of caches will now update caches without static maps first\n - · If a cache has a chirp attribute the navigation menu supports starting the Cache Beacon app\n - · Search bar on main screen now allows searching OC geocodes\n - · Removed Go4Cache support as this third party service is no longer available\n - · Selectable GPX import directory\n - · New log template for inserting owner name\n - · New option to remove colors from log entries\n - · Ability to delete GPX files after import\n - · Quick signature insertion\n - · Template for inserting smilies when logging a cache\n - · Option to identify as android browser. Might help in case of login problems on mobile networks\n - · Create and edit a personal note for each cache (not yet synchronized to geocaching.com)\n - · Quick change between different offline maps within live map\n - · Support of custom themes for offline maps (e.g. nightview)\n - · Sygic navigation support\n - · Filter for non premium member caches\n - · New image tab in cache details\n - \n - <b>Bugfixing:</b>\n - · Crash when modifying lists fixed\n - · Improvement for cache description translation\n - · Avoid crash when searching for an unactivated TB\n - · Improvement for enabling live mode on map\n - · Improvement for GPX export operations\n - · Readability improvement for cache description with dark text when using black theme\n - · Store for offline on live map now always available for basic members\n - · Live map now stays live after display rotation\n - · Open in browser improved to allow setting a default browser without losing the option to open coord.info URLs with c:geo\n - · Improve offline stability\n - · Static map download improvements\n - · Failure when importing previously exported GPX file fixed\n - · Opening a link from a TB description improved\n - · Last activity time on TB page corrected\n - · 4-digit favorite points shown correctly in lists\n - · File scan for offline maps improved\n - · Allow HTML in trackable description\n - · Live map filter now also working for basic members\n - · Improved stability for large GPX file import\n - \n - <a href="https://github.com/cgeo/c-geo-opensource/issues?milestone=8&state=closed">Detailed list of all changes</a>\n - \n - <b>Known Limitations/Bugs:</b>\n - · Live map:\n - Approximated coords due to limitations on the GC-website\n - Be aware: If navigation is started directly from live map it may also use the approximated coords!\n - In fast mode the cache type might be wrong in rare cases\n - Fast mode only detectes Tradi, Multi, Mystery, Event caches\n - On low zoom owned/found caches may not be hidden anymore\n - · Other:\n - Log images with huge size cause a long loading time\n - In special situations the logbook might not be shown completely after logging a cache\n - The personal note added to a cache is not synced to geocaching.com but will be overruled by personal notes on geocaching.com\n - On devices with HD display resolution OSM maps might not work. Please use Google maps in this case.\n - <b>Old releases</b>\n - · Please refer to the release notes on the <a href="http://www.cgeo.org">c:geo-website</a>.\n - \n</string> </resources> diff --git a/main/res/values/strings_not_translatable.xml b/main/res/values/strings_not_translatable.xml new file mode 100644 index 0000000..3678357 --- /dev/null +++ b/main/res/values/strings_not_translatable.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string-array name="waypoint_coordinate_formats" translatable="false">
+ <item>@string/waypoint_coordinate_formats_plain</item>
+ <item>DDD.DDDDD°</item>
+ <item>DDD°MM.MMM\'</item>
+ <item>DDD°MM\'SS.SSS\"</item>
+ </string-array>
+
+ <!-- distance units -->
+ <string-array name="distance_units">
+ <item>@string/unit_m</item>
+ <item>@string/unit_km</item>
+ <item>@string/unit_ft</item>
+ <item>@string/unit_yd</item>
+ <item>@string/unit_mi</item>
+ </string-array>
+
+ <string name="init_select_themefolder" translatable="false">…</string>
+ <string name="init_select_map_directory" translatable="false">…</string>
+ <string name="init_select_gpx_exportdir" translatable="false">…</string>
+ <string name="init_select_gpx_importdir" translatable="false">…</string>
+
+ <!-- contributors -->
+ <string name="contributors" translatable="false">\n
+ · <a href="http://carnero.cc/">carnero</a> as the father of c:geo\n
+ \n
+ · 0xErnie (localization DE)\n
+ · <a href="mailto:bazsy@freemail.hu">Balazs Szabo (Bazsy1983)</a> (loc. HU)\n
+ · Bananeweizen (code, loc. DE)\n
+ · blafoo (code, localization DE)\n
+ · Bonemaro (tester)\n
+ · BudBundi (localization DE, tester)\n
+ · campbeb (code)\n
+ · Charles (localization FR)\n
+ · Denny (localization DA)\n
+ · Eisbehr (code)\n
+ · F. Coello (localization ES)\n
+ · Filipe C. (code)\n
+ · <a href="http://www.hunterthornsberry.com">Hunter275</a> (tester)\n
+ · <a href="http://iirojappinen.com/">Iiro Jäppinen</a> (graphic)\n
+ · inkantis (localization PL)\n
+ · <a href="http://www.jaytech.cz/">Jan Žatecký</a> (graphic)\n
+ · <a href="http://joachim-wilke.de/">JoWi24</a> (code)\n
+ · <a href="http://github.com/koem">Karsten Priegnitz</a> (code, artwork computation)\n
+ · <a href="http://www.geocaching.com/email/?guid=d11a3e3d-7db0-4d43-87f2-7893238844a6">Lineflyer</a> (tester, support, localization DE)\n
+ · Ludovic Valente (localization FR)\n
+ · marco-jacob (code, loc. DE)\n
+ · MichielK (code, loc. NL)\n
+ · mucek4 (code, open source project leader)\n
+ · ncorreia (code, localization PT)\n
+ · Pascal (localization NL)\n
+ · Pavol Babinčák (code, loc. SK)\n
+ · Peter (localization HU)\n
+ · <a href="https://github.com/Portree-Kid">Portree Kid</a> (code)\n
+ · Rainer S. (code)\n
+ · Ray (code, loc. JA)\n
+ · <a href="http://seromenho.com/">Ricardo Seromenho</a> (localization PT)\n
+ · RoadRunner- (code, loc. DE)\n
+ · <a href="http://www.blueskysoftware.it/">RomNexus6</a> (localization IT)\n
+ · <a href="http://www.sammyshp.de/">SammysHP</a> (code, localization DE)\n
+ · <a href="http://www.rfc1149.net/sam.html">Samuel Tardieu</a> (code, localization FR)\n
+ · serenity (localization DE)\n
+ · Shan, a.k.a. ShakurNO (localization NO)\n
+ · Shizo87 (tester)\n
+ · stephanme/Geoteufel (code)\n
+ · thiasB (code, loc. DE EN)\n
+ · YraFyra (code, loc. SV)\n
+ · zenobios (code, loc. DE EN)\n
+ \n
+ · <a href="http://code.google.com/p/mapsforge/">Mapsforge</a> (OSM-rendering)\n
+ · <a href="http://thenounproject.com/">The Noun Project</a> (basis for attribute icons)\n
+ · <a href="http://commons.apache.org/">The Apache Commons Project</a>\n
+ · <a href="http://androidicons.com/">Android Icons</a> (<a href="https://creativecommons.org/licenses/by/3.0/">CC-BY 3.0</a>)\n
+ · <a href="http://rrze-icon-set.berlios.de/index.html">RRZE Icon set</a> (<a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA 3.0</a>)\n
+ </string>
+
+ <!-- changelog -->
+ <string name="changelog" translatable="false">\n
+ <b>Next release</b>\n\n
+ <b>New Features/Functions:</b>\n
+ · Alphabetical sorting of OSM:Offline maps in map selection\n
+ · Color markers also in trackable logbook\n
+ · Edit cache type filter by clicking on filter bar\n
+ · Support for searching opencaching.nl caches\n
+ · Inverse sorting of cache lists (hit the same menu again)\n
+ · view pager in trackable activity\n
+ · menu item to delete past events\n
+ · ability to select "all" list from main screen\n
+ \n
+ <b>Bugfixing:</b>\n
+ · Final flag icon lost when updating cache with self defined final\n
+ · Bad selection in directory chooser\n
+ · Scanning geocode by QR code\n
+ · Log type "Retract Listing" now parsed correctly\n
+ \n
+ <a href="https://github.com/cgeo/c-geo-opensource/issues?milestone=9&state=closed">Detailed list of all changes</a>\n
+ \n
+ <b>Known Limitations/Bugs:</b>\n
+ · Live map:\n
+ Approximated coords due to limitations on the GC-website\n
+ Be aware: If navigation is started directly from live map it may also use the approximated coords!\n
+ In fast mode the cache type might be wrong in rare cases\n
+ Fast mode only detectes Tradi, Multi, Mystery, Event caches\n
+ On low zoom owned/found caches may not be hidden anymore\n
+ · Other:\n
+ Log images with huge size cause a long loading time\n
+ In special situations the logbook might not be shown completely after logging a cache\n
+ The personal note added to a cache is not synced to geocaching.com but will be overruled by personal notes on geocaching.com\n
+ On devices with HD display resolution OSM maps might not work. Please use Google maps in this case.\n
+ <b>Old releases</b>\n
+ · Please refer to the release notes on the <a href="http://www.cgeo.org">c:geo-website</a>.\n
+ \n</string>
+
+</resources>
\ No newline at end of file diff --git a/main/res/values/styles.xml b/main/res/values/styles.xml index 394e3d0..caa884a 100644 --- a/main/res/values/styles.xml +++ b/main/res/values/styles.xml @@ -26,6 +26,24 @@ <item name="android:capitalize">none</item> </style> + <style name="checkbox" parent="@android:style/Widget.CompoundButton.CheckBox"> + <item name="android:textColor">?text_color</item> + </style> + + <style name="checkbox_full" parent="checkbox"> + <item name="android:layout_width">fill_parent</item> + <item name="android:layout_height">wrap_content</item> + </style> + + <style name="radiobutton" parent="@android:style/Widget.CompoundButton.RadioButton"> + <item name="android:textColor">?text_color</item> + </style> + + <style name="radiobutton_wrap" parent="radiobutton"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + </style> + <!-- own definitions --> <!-- actionbar --> <style name="action_bar"> diff --git a/main/src/android/support/v4/app/FragmentListActivity.java b/main/src/android/support/v4/app/FragmentListActivity.java new file mode 100644 index 0000000..d392ac6 --- /dev/null +++ b/main/src/android/support/v4/app/FragmentListActivity.java @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.support.v4.app; + +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ListAdapter; +import android.widget.ListView; + +/** + * An activity that displays a list of items by binding to a data source such as + * an array or Cursor, and exposes event handlers when the user selects an item. + * <p> + * FragmentListActivity hosts a {@link android.widget.ListView ListView} object that can + * be bound to different data sources, typically either an array or a Cursor + * holding query results. Binding, screen layout, and row layout are discussed + * in the following sections. + * <p> + * <strong>Screen Layout</strong> + * </p> + * <p> + * FragmentListActivity has a default layout that consists of a single, full-screen list + * in the center of the screen. However, if you desire, you can customize the + * screen layout by setting your own view layout with setContentView() in + * onCreate(). To do this, your own view MUST contain a ListView object with the + * id "@android:id/list" (or {@link android.R.id#list} if it's in code) + * <p> + * Optionally, your custom view can contain another view object of any type to + * display when the list view is empty. This "empty list" notifier must have an + * id "android:empty". Note that when an empty view is present, the list view + * will be hidden when there is no data to display. + * <p> + * The following code demonstrates an (ugly) custom screen layout. It has a list + * with a green background, and an alternate red "no data" message. + * </p> + * + * <pre> + * <?xml version="1.0" encoding="utf-8"?> + * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + * android:orientation="vertical" + * android:layout_width="fill_parent" + * android:layout_height="fill_parent" + * android:paddingLeft="8dp" + * android:paddingRight="8dp"> + * + * <ListView android:id="@id/android:list" + * android:layout_width="fill_parent" + * android:layout_height="fill_parent" + * android:background="#00FF00" + * android:layout_weight="1" + * android:drawSelectorOnTop="false"/> + * + * <TextView android:id="@id/android:empty" + * android:layout_width="fill_parent" + * android:layout_height="fill_parent" + * android:background="#FF0000" + * android:text="No data"/> + * </LinearLayout> + * </pre> + * + * <p> + * <strong>Row Layout</strong> + * </p> + * <p> + * You can specify the layout of individual rows in the list. You do this by + * specifying a layout resource in the ListAdapter object hosted by the activity + * (the ListAdapter binds the ListView to the data; more on this later). + * <p> + * A ListAdapter constructor takes a parameter that specifies a layout resource + * for each row. It also has two additional parameters that let you specify + * which data field to associate with which object in the row layout resource. + * These two parameters are typically parallel arrays. + * </p> + * <p> + * Android provides some standard row layout resources. These are in the + * {@link android.R.layout} class, and have names such as simple_list_item_1, + * simple_list_item_2, and two_line_list_item. The following layout XML is the + * source for the resource two_line_list_item, which displays two data + * fields,one above the other, for each list row. + * </p> + * + * <pre> + * <?xml version="1.0" encoding="utf-8"?> + * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + * android:layout_width="fill_parent" + * android:layout_height="wrap_content" + * android:orientation="vertical"> + * + * <TextView android:id="@+id/text1" + * android:textSize="16sp" + * android:textStyle="bold" + * android:layout_width="fill_parent" + * android:layout_height="wrap_content"/> + * + * <TextView android:id="@+id/text2" + * android:textSize="16sp" + * android:layout_width="fill_parent" + * android:layout_height="wrap_content"/> + * </LinearLayout> + * </pre> + * + * <p> + * You must identify the data bound to each TextView object in this layout. The + * syntax for this is discussed in the next section. + * </p> + * <p> + * <strong>Binding to Data</strong> + * </p> + * <p> + * You bind the FragmentListActivity's ListView object to data using a class that + * implements the {@link android.widget.ListAdapter ListAdapter} interface. + * Android provides two standard list adapters: + * {@link android.widget.SimpleAdapter SimpleAdapter} for static data (Maps), + * and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor + * query results. + * </p> + * <p> + * The following code from a custom FragmentListActivity demonstrates querying the + * Contacts provider for all contacts, then binding the Name and Company fields + * to a two line row layout in the activity's ListView. + * </p> + * + * <pre> + * public class MyListAdapter extends FragmentListActivity { + * + * @Override + * protected void onCreate(Bundle savedInstanceState){ + * super.onCreate(savedInstanceState); + * + * // We'll define a custom screen layout here (the one shown above), but + * // typically, you could just use the standard FragmentListActivity layout. + * setContentView(R.layout.custom_list_activity_view); + * + * // Query for all people contacts using the {@link android.provider.Contacts.People} convenience class. + * // Put a managed wrapper around the retrieved cursor so we don't have to worry about + * // requerying or closing it as the activity changes state. + * mCursor = this.getContentResolver().query(People.CONTENT_URI, null, null, null, null); + * startManagingCursor(mCursor); + * + * // Now create a new list adapter bound to the cursor. + * // SimpleListAdapter is designed for binding to a Cursor. + * ListAdapter adapter = new SimpleCursorAdapter( + * this, // Context. + * android.R.layout.two_line_list_item, // Specify the row template to use (here, two columns bound to the two retrieved cursor + * rows). + * mCursor, // Pass in the cursor to bind to. + * new String[] {People.NAME, People.COMPANY}, // Array of cursor columns to bind to. + * new int[] {android.R.id.text1, android.R.id.text2}); // Parallel array of which template objects to bind to those columns. + * + * // Bind to our new adapter. + * setListAdapter(adapter); + * } + * } + * </pre> + * + * @see #setListAdapter + * @see android.widget.ListView + */ +public class FragmentListActivity extends FragmentActivity { + /** + * This field should be made private, so it is hidden from the SDK. + * {@hide} + */ + protected ListAdapter mAdapter; + /** + * This field should be made private, so it is hidden from the SDK. + * {@hide} + */ + protected ListView mList; + + private Handler mHandler = new Handler(); + private boolean mFinishedStart = false; + + private Runnable mRequestFocus = new Runnable() { + public void run() { + mList.focusableViewAvailable(mList); + } + }; + + /** + * This method will be called when an item in the list is selected. + * Subclasses should override. Subclasses can call + * getListView().getItemAtPosition(position) if they need to access the + * data associated with the selected item. + * + * @param l The ListView where the click happened + * @param v The view that was clicked within the ListView + * @param position The position of the view in the list + * @param id The row id of the item that was clicked + */ + protected void onListItemClick(ListView l, View v, int position, long id) { + } + + /** + * Ensures the list view has been created before Activity restores all + * of the view states. + * + *@see Activity#onRestoreInstanceState(Bundle) + */ + @Override + protected void onRestoreInstanceState(Bundle state) { + ensureList(); + super.onRestoreInstanceState(state); + } + + /** + * Updates the screen state (current list and other views) when the + * content changes. + * + * @see Activity#onContentChanged() + */ + @Override + public void onContentChanged() { + super.onContentChanged(); + View emptyView = findViewById(android.R.id.empty); + mList = (ListView)findViewById(android.R.id.list); + if (mList == null) { + throw new RuntimeException( + "Your content must have a ListView whose id attribute is " + + "'android.R.id.list'"); + } + if (emptyView != null) { + mList.setEmptyView(emptyView); + } + mList.setOnItemClickListener(mOnClickListener); + if (mFinishedStart) { + setListAdapter(mAdapter); + } + mHandler.post(mRequestFocus); + mFinishedStart = true; + } + + /** + * Provide the cursor for the list view. + */ + public void setListAdapter(ListAdapter adapter) { + synchronized (this) { + ensureList(); + mAdapter = adapter; + mList.setAdapter(adapter); + } + } + + /** + * Set the currently selected list item to the specified + * position with the adapter's data + * + * @param position + */ + public void setSelection(int position) { + mList.setSelection(position); + } + + /** + * Get the position of the currently selected list item. + */ + public int getSelectedItemPosition() { + return mList.getSelectedItemPosition(); + } + + /** + * Get the cursor row ID of the currently selected list item. + */ + public long getSelectedItemId() { + return mList.getSelectedItemId(); + } + + /** + * Get the activity's list view widget. + */ + public ListView getListView() { + ensureList(); + return mList; + } + + /** + * Get the ListAdapter associated with this activity's ListView. + */ + public ListAdapter getListAdapter() { + return mAdapter; + } + + private void ensureList() { + if (mList != null) { + return; + } + setContentView(android.R.layout.list_content); + + } + + private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView<?> parent, View v, int position, long id) + { + onListItemClick((ListView)parent, v, position, id); + } + }; +} + diff --git a/main/src/cgeo/geocaching/AbstractLoggingActivity.java b/main/src/cgeo/geocaching/AbstractLoggingActivity.java index 62cb5cb..eaeffb0 100644 --- a/main/src/cgeo/geocaching/AbstractLoggingActivity.java +++ b/main/src/cgeo/geocaching/AbstractLoggingActivity.java @@ -20,7 +20,7 @@ public abstract class AbstractLoggingActivity extends AbstractActivity { private static final int MENU_SIGNATURE = 1; private static final int MENU_SMILEY = 2; - public AbstractLoggingActivity(String helpTopic) { + protected AbstractLoggingActivity(String helpTopic) { super(helpTopic); } @@ -55,7 +55,7 @@ public abstract class AbstractLoggingActivity extends AbstractActivity { if (cache != null && ConnectorFactory.getConnector(cache).equals(GCConnector.getInstance())) { smileyVisible = true; } - final cgTrackable trackable = getLogContext().getTrackable(); + final Trackable trackable = getLogContext().getTrackable(); if (trackable != null && ConnectorFactory.getConnector(trackable).equals(GCConnector.getInstance())) { smileyVisible = true; } diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java index 830d61a..db9a04c 100644 --- a/main/src/cgeo/geocaching/AbstractPopupActivity.java +++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java @@ -73,7 +73,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity { } }; - public AbstractPopupActivity(String helpTopic, int layout) { + protected AbstractPopupActivity(String helpTopic, int layout) { super(helpTopic); this.layout = layout; } @@ -109,7 +109,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity { } protected void init() { - cache = app.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); if (cache == null) { showToast(res.getString(R.string.err_detail_cache_find)); @@ -118,7 +118,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity { return; } - geocode = cache.getGeocode().toUpperCase(); + geocode = cache.getGeocode(); } private void showInBrowser() { @@ -186,10 +186,10 @@ public abstract class AbstractPopupActivity extends AbstractActivity { case MENU_SHOW_IN_BROWSER: showInBrowser(); return true; - } - - if (LoggingUI.onMenuItemSelected(item, this, cache)) { - return true; + default: + if (LoggingUI.onMenuItemSelected(item, this, cache)) { + return true; + } } return true; @@ -251,7 +251,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity { final String cacheSize = cache.getSize() != CacheSize.UNKNOWN ? " (" + cache.getSize().getL10n() + ")" : ""; details.add(R.string.cache_type, cacheType + cacheSize); - details.add(R.string.cache_geocode, cache.getGeocode().toUpperCase()); + details.add(R.string.cache_geocode, cache.getGeocode()); details.addCacheState(cache); details.addDistance(cache, cacheDistance); @@ -276,7 +276,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity { @Override public void onClick(View arg0) { - CacheDetailActivity.startActivity(AbstractPopupActivity.this, geocode.toUpperCase()); + CacheDetailActivity.startActivity(AbstractPopupActivity.this, geocode); finish(); } }); diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index ff01ab3..634eea6 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -1,10 +1,10 @@ package cgeo.geocaching; import cgeo.calendar.ICalendar; -import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.activity.AbstractViewPagerActivity; import cgeo.geocaching.activity.Progress; -import cgeo.geocaching.apps.cache.GeneralAppsFactory; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; +import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.connector.gc.GCConnector; @@ -12,10 +12,13 @@ import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.Units; import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.ui.DecryptTextClickListener; import cgeo.geocaching.ui.EditorDialog; @@ -31,18 +34,20 @@ import cgeo.geocaching.utils.GeoDirHandler; import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.ImageHelper; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import cgeo.geocaching.utils.TranslationUtils; import cgeo.geocaching.utils.UnknownTagsHandler; -import com.viewpagerindicator.TitlePageIndicator; -import com.viewpagerindicator.TitleProvider; - import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import android.R.color; +import android.app.Activity; import android.app.AlertDialog; +import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -57,10 +62,6 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.os.Parcelable; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; -import android.support.v4.view.ViewPager.OnPageChangeListener; import android.text.Editable; import android.text.Html; import android.text.Spannable; @@ -79,7 +80,6 @@ import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; -import android.view.WindowManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; @@ -88,21 +88,19 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; +import android.widget.RadioButton; import android.widget.ScrollView; import android.widget.TextView; import android.widget.TextView.BufferType; -import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; -import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -110,9 +108,8 @@ import java.util.regex.Pattern; * * e.g. details, description, logs, waypoints, inventory... */ -public class CacheDetailActivity extends AbstractActivity { +public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page> { - private static final String EXTRAS_PAGE = "page"; private static final int MENU_FIELD_COPY = 1; private static final int MENU_FIELD_TRANSLATE = 2; private static final int MENU_FIELD_TRANSLATE_EN = 3; @@ -129,6 +126,7 @@ public class CacheDetailActivity extends AbstractActivity { private static final int CONTEXT_MENU_WAYPOINT_NAVIGATE = 1238; private static final int CONTEXT_MENU_WAYPOINT_CACHES_AROUND = 1239; private static final int CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION = 1240; + private static final int CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES = 1241; private static final Pattern DARK_COLOR_PATTERN = Pattern.compile(Pattern.quote("color=\"#") + "(0[0-9]){3}" + "\""); @@ -169,33 +167,6 @@ public class CacheDetailActivity extends AbstractActivity { private int contextMenuWPIndex = -1; /** - * A {@link List} of all available pages. - * - * TODO Move to adapter - */ - private final List<Page> pageOrder = new ArrayList<Page>(); - - /** - * Instances of all {@link PageViewCreator}. - */ - private final Map<Page, PageViewCreator> viewCreators = new HashMap<Page, PageViewCreator>(); - - /** - * The {@link ViewPager} for this activity. - */ - private ViewPager viewPager; - - /** - * The {@link ViewPagerAdapter} for this activity. - */ - private ViewPagerAdapter viewPagerAdapter; - - /** - * The {@link TitlePageIndicator} for this activity. - */ - private TitlePageIndicator titleIndicator; - - /** * If another activity is called and can modify the data of this activity, we refresh it on resume. */ private boolean refreshOnResume = false; @@ -226,8 +197,6 @@ public class CacheDetailActivity extends AbstractActivity { setTitle(res.getString(R.string.cache)); String geocode = null; - String guid = null; - String name = null; // TODO Why can it happen that search is not null? onCreate should be called only once and it is not set before. if (search != null) { @@ -242,6 +211,8 @@ public class CacheDetailActivity extends AbstractActivity { final Uri uri = getIntent().getData(); // try to get data from extras + String name = null; + String guid = null; if (geocode == null && extras != null) { geocode = extras.getString("geocode"); name = extras.getString("name"); @@ -250,8 +221,8 @@ public class CacheDetailActivity extends AbstractActivity { // try to get data from URI if (geocode == null && guid == null && uri != null) { - String uriHost = uri.getHost().toLowerCase(); - String uriPath = uri.getPath().toLowerCase(); + String uriHost = uri.getHost().toLowerCase(Locale.US); + String uriPath = uri.getPath().toLowerCase(Locale.US); String uriQuery = uri.getQuery(); if (uriQuery != null) { @@ -265,11 +236,11 @@ public class CacheDetailActivity extends AbstractActivity { guid = uri.getQueryParameter("guid"); if (StringUtils.isNotBlank(geocode)) { - geocode = geocode.toUpperCase(); + geocode = geocode.toUpperCase(Locale.US); guid = null; } else if (StringUtils.isNotBlank(guid)) { geocode = null; - guid = guid.toLowerCase(); + guid = guid.toLowerCase(Locale.US); } else { showToast(res.getString(R.string.err_detail_open)); finish(); @@ -277,7 +248,7 @@ public class CacheDetailActivity extends AbstractActivity { } } else if (uriHost.contains("coord.info")) { if (uriPath != null && uriPath.startsWith("/gc")) { - geocode = uriPath.substring(1).toUpperCase(); + geocode = uriPath.substring(1).toUpperCase(Locale.US); } else { showToast(res.getString(R.string.err_detail_open)); finish(); @@ -300,7 +271,7 @@ public class CacheDetailActivity extends AbstractActivity { if (StringUtils.isNotBlank(name)) { title = name; } else if (null != geocode && StringUtils.isNotBlank(geocode)) { // can't be null, but the compiler doesn't understand StringUtils.isNotBlank() - title = geocode.toUpperCase(); + title = geocode; } progress.show(this, title, res.getString(R.string.cache_dialog_loading_details), true, loadCacheHandler.cancelMessage()); } catch (Exception e) { @@ -316,50 +287,21 @@ public class CacheDetailActivity extends AbstractActivity { } }); - // initialize ViewPager - viewPager = (ViewPager) findViewById(R.id.viewpager); - viewPagerAdapter = new ViewPagerAdapter(); - viewPager.setAdapter(viewPagerAdapter); + final int pageToOpen = Settings.isOpenLastDetailsPage() ? Settings.getLastDetailsPage() : 1; + createViewPager(pageToOpen, new OnPageSelectedListener() { - titleIndicator = (TitlePageIndicator) findViewById(R.id.pager_indicator); - titleIndicator.setViewPager(viewPager); - titleIndicator.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { if (Settings.isOpenLastDetailsPage()) { Settings.setLastDetailsPage(position); } // lazy loading of cache images - if (pageOrder.get(position) == Page.IMAGES) { + if (getPage(position) == Page.IMAGES) { loadCacheImages(); } } - - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - } - - @Override - public void onPageScrollStateChanged(int state) { - } }); - // switch to entry page (last used or 2) - int entryPageIndex; - if (extras != null && extras.get(EXTRAS_PAGE) != null) { - entryPageIndex = extras.getInt(EXTRAS_PAGE); - } - else { - entryPageIndex = Settings.isOpenLastDetailsPage() ? Settings.getLastDetailsPage() : 1; - } - if (viewPagerAdapter.getCount() < entryPageIndex) { - for (int i = 0; i <= entryPageIndex; i++) { - // we can't switch to a page that is out of bounds, so we add null-pages - pageOrder.add(null); - } - } - viewPager.setCurrentItem(entryPageIndex, false); - // Initialization done. Let's load the data with the given information. new LoadCacheThread(geocode, guid, loadCacheHandler).start(); } @@ -431,15 +373,19 @@ public class CacheDetailActivity extends AbstractActivity { final ViewGroup parent = ((ViewGroup) view.getParent()); for (int i = 0; i < parent.getChildCount(); i++) { if (parent.getChildAt(i) == view) { - final List<cgWaypoint> sortedWaypoints = new ArrayList<cgWaypoint>(cache.getWaypoints()); + final List<Waypoint> sortedWaypoints = new ArrayList<Waypoint>(cache.getWaypoints()); Collections.sort(sortedWaypoints); - final cgWaypoint waypoint = sortedWaypoints.get(i); + final Waypoint waypoint = sortedWaypoints.get(i); final int index = cache.getWaypoints().indexOf(waypoint); menu.setHeaderTitle(res.getString(R.string.waypoint)); - menu.add(CONTEXT_MENU_WAYPOINT_EDIT, index, 0, R.string.waypoint_edit); - menu.add(CONTEXT_MENU_WAYPOINT_DUPLICATE, index, 0, R.string.waypoint_duplicate); + if (waypoint.getWaypointType().equals(WaypointType.ORIGINAL)) { + menu.add(CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES, index, 0, R.string.waypoint_reset_cache_coords); + } else { + menu.add(CONTEXT_MENU_WAYPOINT_EDIT, index, 0, R.string.waypoint_edit); + menu.add(CONTEXT_MENU_WAYPOINT_DUPLICATE, index, 0, R.string.waypoint_duplicate); + } contextMenuWPIndex = index; - if (waypoint.isUserDefined()) { + if (waypoint.isUserDefined() && !waypoint.getWaypointType().equals(WaypointType.ORIGINAL)) { menu.add(CONTEXT_MENU_WAYPOINT_DELETE, index, 0, R.string.waypoint_delete); } if (waypoint.getCoords() != null) { @@ -511,54 +457,55 @@ public class CacheDetailActivity extends AbstractActivity { } break; - case CONTEXT_MENU_WAYPOINT_EDIT: { - final cgWaypoint waypoint = cache.getWaypoint(index); - if (waypoint != null) { - EditWaypointActivity.startActivityEditWaypoint(this, waypoint.getId()); + case CONTEXT_MENU_WAYPOINT_EDIT: + final Waypoint waypointEdit = cache.getWaypoint(index); + if (waypointEdit != null) { + EditWaypointActivity.startActivityEditWaypoint(this, waypointEdit.getId()); refreshOnResume = true; } break; - } case CONTEXT_MENU_WAYPOINT_DUPLICATE: - if (cache.duplicateWaypoint(index)) { - app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + final Waypoint waypointDuplicate = cache.getWaypoint(index); + if (cache.duplicateWaypoint(waypointDuplicate)) { + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); notifyDataSetChanged(); } break; case CONTEXT_MENU_WAYPOINT_DELETE: - if (cache.deleteWaypoint(index)) { - app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + final Waypoint waypointDelete = cache.getWaypoint(index); + if (cache.deleteWaypoint(waypointDelete)) { + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); notifyDataSetChanged(); } break; - case CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION: { - final cgWaypoint waypoint = cache.getWaypoint(index); - if (waypoint != null) { - NavigationAppFactory.startDefaultNavigationApplication(1, this, waypoint); + case CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION: + final Waypoint waypointNavigation = cache.getWaypoint(index); + if (waypointNavigation != null) { + NavigationAppFactory.startDefaultNavigationApplication(1, this, waypointNavigation); } - } break; - case CONTEXT_MENU_WAYPOINT_NAVIGATE: { - final cgWaypoint waypoint = cache.getWaypoint(contextMenuWPIndex); - if (waypoint != null) { - NavigationAppFactory.showNavigationMenu(this, null, waypoint, null); + case CONTEXT_MENU_WAYPOINT_NAVIGATE: + final Waypoint waypointNav = cache.getWaypoint(contextMenuWPIndex); + if (waypointNav != null) { + NavigationAppFactory.showNavigationMenu(this, null, waypointNav, null); } - } break; - case CONTEXT_MENU_WAYPOINT_CACHES_AROUND: { - final cgWaypoint waypoint = cache.getWaypoint(index); - if (waypoint != null) { - cgeocaches.startActivityCoordinates(this, waypoint.getCoords()); + case CONTEXT_MENU_WAYPOINT_CACHES_AROUND: + final Waypoint waypointAround = cache.getWaypoint(index); + if (waypointAround != null) { + cgeocaches.startActivityCoordinates(this, waypointAround.getCoords()); } - } break; - default: { + + case CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES: + new ResetCacheCoordinatesDialog(cache, cache.getWaypoint(index), this).show(); + break; + + default: if (imagesList != null && imagesList.onContextItemSelected(item)) { return true; } - return onOptionsItemSelected(item); - } } return false; } @@ -570,7 +517,6 @@ public class CacheDetailActivity extends AbstractActivity { final SubMenu subMenu = menu.addSubMenu(0, 0, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode); NavigationAppFactory.addMenuItems(subMenu, cache); - GeneralAppsFactory.addMenuItems(subMenu, cache); menu.add(0, MENU_CALENDAR, 0, res.getString(R.string.cache_menu_event)).setIcon(R.drawable.ic_menu_agenda); // add event to calendar LoggingUI.addMenuItems(menu, cache); @@ -583,10 +529,12 @@ public class CacheDetailActivity extends AbstractActivity { @Override public boolean onPrepareOptionsMenu(Menu menu) { - menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(null != cache.getCoords()); - menu.findItem(MENU_CALENDAR).setVisible(cache.canBeAddedToCalendar()); - menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround()); - menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser()); + if (cache != null) { + menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(null != cache.getCoords()); + menu.findItem(MENU_CALENDAR).setVisible(cache.canBeAddedToCalendar()); + menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround()); + menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser()); + } return super.onPrepareOptionsMenu(menu); } @@ -594,7 +542,7 @@ public class CacheDetailActivity extends AbstractActivity { public boolean onOptionsItemSelected(MenuItem item) { final int menuItem = item.getItemId(); - switch(menuItem) { + switch (menuItem) { case 0: // no menu selected, but a new sub menu shown return false; @@ -616,16 +564,14 @@ public class CacheDetailActivity extends AbstractActivity { return true; } return false; - } - if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) { - return true; - } - if (GeneralAppsFactory.onMenuItemSelected(item, this, cache)) { - return true; - } - if (LoggingUI.onMenuItemSelected(item, this, cache)) { - refreshOnResume = true; - return true; + default: + if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) { + return true; + } + if (LoggingUI.onMenuItemSelected(item, this, cache)) { + refreshOnResume = true; + return true; + } } return true; @@ -640,6 +586,7 @@ public class CacheDetailActivity extends AbstractActivity { if (search == null) { showToast(res.getString(R.string.err_dwld_details_failed)); + progress.dismiss(); finish(); return; } @@ -647,6 +594,7 @@ public class CacheDetailActivity extends AbstractActivity { if (search.getError() != null) { showToast(res.getString(R.string.err_dwld_details_failed) + " " + search.getError().getErrorString(res) + "."); + progress.dismiss(); finish(); return; } @@ -688,51 +636,18 @@ public class CacheDetailActivity extends AbstractActivity { // allow cache to notify CacheDetailActivity when it changes so it can be reloaded cache.setChangeNotificationHandler(cacheChangeNotificationHandler); - // notify all creators that the data has changed - for (PageViewCreator creator : viewCreators.values()) { - creator.notifyDataSetChanged(); - } - - // action bar: title and icon (default: mystery icon) + // action bar: title and icon if (StringUtils.isNotBlank(cache.getName())) { - setTitle(cache.getName() + " (" + cache.getGeocode().toUpperCase() + ')'); + setTitle(cache.getName() + " (" + cache.getGeocode() + ')'); } else { - setTitle(cache.getGeocode().toUpperCase()); + setTitle(cache.getGeocode()); } ((TextView) findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(cache.getType().markerId), null, null, null); - // add available pages (remove old pages first) - pageOrder.clear(); - - pageOrder.add(Page.WAYPOINTS); - pageOrder.add(Page.DETAILS); - final int detailsIndex = pageOrder.size() - 1; - pageOrder.add(Page.DESCRIPTION); - if (cache.getLogs().isNotEmpty()) { - pageOrder.add(Page.LOGS); - } - if (CollectionUtils.isNotEmpty(cache.getFriendsLogs())) { - pageOrder.add(Page.LOGSFRIENDS); - } - if (CollectionUtils.isNotEmpty(cache.getInventory())) { - pageOrder.add(Page.INVENTORY); - } - if (CollectionUtils.isNotEmpty(cache.getImages())) { - pageOrder.add(Page.IMAGES); - } - - // switch to details page, if we're out of bounds - if (viewPager.getCurrentItem() < 0 || viewPager.getCurrentItem() >= viewPagerAdapter.getCount()) { - viewPager.setCurrentItem(detailsIndex, false); - } - - // notify the adapter that the data has changed - viewPagerAdapter.notifyDataSetChanged(); - - // notify the indicator that the data has changed - titleIndicator.notifyDataSetChanged(); + reinitializeViewPager(); // rendering done! remove progress popup if any there + invalidateOptionsMenuCompatible(); progress.dismiss(); } @@ -751,6 +666,7 @@ public class CacheDetailActivity extends AbstractActivity { if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) { showToast(res.getString(R.string.err_detail_cache_forgot)); + progress.dismiss(); finish(); return; } @@ -933,7 +849,7 @@ public class CacheDetailActivity extends AbstractActivity { cgeocaches.startActivityUserName(CacheDetailActivity.this, name.toString()); return; case 2: - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + URLEncoder.encode(name.toString())))); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(name.toString())))); return; default: break; @@ -948,7 +864,7 @@ public class CacheDetailActivity extends AbstractActivity { if (imagesList != null) { return; } - PageViewCreator creator = viewCreators.get(Page.IMAGES); + PageViewCreator creator = getViewCreator(Page.IMAGES); if (creator == null) { return; } @@ -956,139 +872,17 @@ public class CacheDetailActivity extends AbstractActivity { if (imageView == null) { return; } - imagesList = new ImagesList(CacheDetailActivity.this, cache.getGeocode()); + imagesList = new ImagesList(this, cache.getGeocode()); imagesList.loadImages(imageView, cache.getImages(), ImageType.AllImages, false); } public static void startActivity(final Context context, final String geocode) { final Intent detailIntent = new Intent(context, CacheDetailActivity.class); - detailIntent.putExtra("geocode", geocode.toUpperCase()); - context.startActivity(detailIntent); - } - - public static void startActivity(final Context context, final String geocode, final int page) { - final Intent detailIntent = new Intent(context, CacheDetailActivity.class); - detailIntent.putExtra("geocode", geocode.toUpperCase()); - detailIntent.putExtra(EXTRAS_PAGE, page); + detailIntent.putExtra("geocode", geocode); context.startActivity(detailIntent); } /** - * The ViewPagerAdapter for scrolling through pages of the CacheDetailActivity. - */ - private class ViewPagerAdapter extends PagerAdapter implements TitleProvider { - - @Override - public void destroyItem(View container, int position, Object object) { - ((ViewPager) container).removeView((View) object); - } - - @Override - public void finishUpdate(View container) { - } - - @Override - public int getCount() { - return pageOrder.size(); - } - - @Override - public Object instantiateItem(View container, int position) { - final Page page = pageOrder.get(position); - - PageViewCreator creator = viewCreators.get(page); - - if (null == creator && null != page) { - // The creator is not instantiated yet, let's do it. - switch (page) { - case DETAILS: - creator = new DetailsViewCreator(); - break; - - case DESCRIPTION: - creator = new DescriptionViewCreator(); - break; - - case LOGS: - creator = new LogsViewCreator(true); - break; - - case LOGSFRIENDS: - creator = new LogsViewCreator(false); - break; - - case WAYPOINTS: - creator = new WaypointsViewCreator(); - break; - - case INVENTORY: - creator = new InventoryViewCreator(); - break; - - case IMAGES: - creator = new ImagesViewCreator(); - break; - } - viewCreators.put(page, creator); - } - - View view = null; - - try { - if (null != creator) { - // Result from getView() is maybe cached, but it should be valid because the - // creator should be informed about data-changes with notifyDataSetChanged() - view = creator.getView(); - ((ViewPager) container).addView(view, 0); - } - } catch (Exception e) { - Log.e("ViewPagerAdapter.instantiateItem ", e); - } - - return view; - } - - @Override - public boolean isViewFromObject(View view, Object object) { - return view == object; - } - - @Override - public void restoreState(Parcelable arg0, ClassLoader arg1) { - } - - @Override - public Parcelable saveState() { - return null; - } - - @Override - public void startUpdate(View arg0) { - } - - @Override - public int getItemPosition(Object object) { - // We are doing the caching. So pretend that the view is gone. - // The ViewPager will get it back in instantiateItem() - return POSITION_NONE; - } - - @Override - public String getTitle(int position) { - final Page page = pageOrder.get(position); - if (null == page) { - return ""; - } - // show number of waypoints directly in waypoint title - if (page == Page.WAYPOINTS) { - final int waypointCount = cache.getWaypoints().size(); - return res.getQuantityString(R.plurals.waypoints, waypointCount, waypointCount); - } - return res.getString(page.titleStringId); - } - } - - /** * Enum of all possible pages with methods to get the view and a title. */ public enum Page { @@ -1102,7 +896,7 @@ public class CacheDetailActivity extends AbstractActivity { final private int titleStringId; - private Page(final int titleStringId) { + Page(final int titleStringId) { this.titleStringId = titleStringId; } } @@ -1112,9 +906,7 @@ public class CacheDetailActivity extends AbstractActivity { private ViewGroup attributeDescriptionsLayout; // layout for attribute descriptions private boolean attributesShowAsIcons = true; // default: show icons /** - * True, if the cache was imported with an older version of c:geo. - * These older versions parsed the attribute description from the tooltip in the web - * page and put them into the DB. No icons can be matched for these. + * If the cache is from a non GC source, it might be without icons. Disable switching in those cases. */ private boolean noAttributeIconsFound = false; private int attributeBoxMaxWidth; @@ -1124,8 +916,7 @@ public class CacheDetailActivity extends AbstractActivity { attributeBox.removeAllViews(); // maximum width for attribute icons is screen width - paddings of parents - attributeBoxMaxWidth = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay().getWidth(); + attributeBoxMaxWidth = Compatibility.getDisplayWidth(); ViewParent child = attributeBox; do { if (child instanceof View) { @@ -1284,46 +1075,16 @@ public class CacheDetailActivity extends AbstractActivity { buffer.append(attributeName); } - if (noAttributeIconsFound) { - buffer.append("\n\n").append(res.getString(R.string.cache_attributes_no_icons)); - } - attribView.setText(buffer); return descriptions; } } - private interface PageViewCreator { - /** - * Returns a validated view. - * - * @return - */ - public View getDispatchedView(); - - /** - * Returns a (maybe cached) view. - * - * @return - */ - public View getView(); - - /** - * Handles changed data-sets. - */ - public void notifyDataSetChanged(); - } - /** * Creator for details-view. */ - private class DetailsViewCreator implements PageViewCreator { - /** - * The main view for this creator - */ - private ScrollView view; - + private class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> { /** * Reference to the details list, so that the helper-method can access it without an additional argument */ @@ -1335,22 +1096,7 @@ public class CacheDetailActivity extends AbstractActivity { private Thread watchlistThread; @Override - public void notifyDataSetChanged() { - // There is a lot of data in this view, let's update everything - view = null; - } - - @Override - public View getView() { - if (view == null) { - view = (ScrollView) getDispatchedView(); - } - - return view; - } - - @Override - public View getDispatchedView() { + public ScrollView getDispatchedView() { if (cache == null) { // something is really wrong return null; @@ -1378,7 +1124,7 @@ public class CacheDetailActivity extends AbstractActivity { details.add(R.string.cache_name, span); details.add(R.string.cache_type, cache.getType().getL10n()); details.addSize(cache); - details.add(R.string.cache_geocode, cache.getGeocode().toUpperCase()); + details.add(R.string.cache_geocode, cache.getGeocode()); details.addCacheState(cache); details.addDistance(cache, cacheDistanceView); @@ -1388,8 +1134,10 @@ public class CacheDetailActivity extends AbstractActivity { details.addTerrain(cache); details.addRating(cache); - // favourite count - details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×"); + // favorite count + if (cache.getFavoritePoints() > 0) { + details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×"); + } // own rating if (cache.getMyVote() > 0) { @@ -1428,22 +1176,22 @@ public class CacheDetailActivity extends AbstractActivity { if (cache.getCoords() != null) { TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString()); valueView.setOnClickListener(new View.OnClickListener() { - private int position = 0; - private GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] { - GeopointFormatter.Format.LAT_LON_DECMINUTE, - GeopointFormatter.Format.LAT_LON_DECSECOND, - GeopointFormatter.Format.LAT_LON_DECDEGREE - }; - - // rotate coordinate formats on click - @Override - public void onClick(View view) { - position = (position + 1) % availableFormats.length; + private int position = 0; + private GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] { + GeopointFormatter.Format.LAT_LON_DECMINUTE, + GeopointFormatter.Format.LAT_LON_DECSECOND, + GeopointFormatter.Format.LAT_LON_DECDEGREE + }; + + // rotate coordinate formats on click + @Override + public void onClick(View view) { + position = (position + 1) % availableFormats.length; - final TextView valueView = (TextView) view.findViewById(R.id.value); - valueView.setText(cache.getCoords().format(availableFormats[position])); - } - }); + final TextView valueView = (TextView) view.findViewById(R.id.value); + valueView.setText(cache.getCoords().format(availableFormats[position])); + } + }); registerForContextMenu(valueView); } @@ -1465,21 +1213,8 @@ public class CacheDetailActivity extends AbstractActivity { // favorite points Button buttonFavPointAdd = (Button) view.findViewById(R.id.add_to_favpoint); Button buttonFavPointRemove = (Button) view.findViewById(R.id.remove_from_favpoint); - buttonFavPointAdd.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - GCConnector.addToFavorites(cache); - updateFavPointBox(); - } - }); - buttonFavPointRemove.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - GCConnector.removeFromFavorites(cache); - updateFavPointBox(); - } - }); - + buttonFavPointAdd.setOnClickListener(new FavoriteAddClickListener()); + buttonFavPointRemove.setOnClickListener(new FavoriteRemoveClickListener()); updateFavPointBox(); // data license @@ -1714,6 +1449,70 @@ public class CacheDetailActivity extends AbstractActivity { } } + /** Thread to add this cache to the favourite list of the user */ + private class FavoriteAddThread extends Thread { + private final Handler handler; + + public FavoriteAddThread(Handler handler) { + this.handler = handler; + } + + @Override + public void run() { + handler.sendEmptyMessage(GCConnector.addToFavorites(cache) ? 1 : -1); + } + } + + /** Thread to remove this cache to the favourite list of the user */ + private class FavoriteRemoveThread extends Thread { + private final Handler handler; + + public FavoriteRemoveThread(Handler handler) { + this.handler = handler; + } + + @Override + public void run() { + handler.sendEmptyMessage(GCConnector.removeFromFavorites(cache) ? 1 : -1); + } + } + + private class FavoriteUpdateHandler extends Handler { + @Override + public void handleMessage(Message msg) { + progress.dismiss(); + if (msg.what == -1) { + showToast(res.getString(R.string.err_favorite_failed)); + } else { + CacheDetailActivity.this.notifyDataSetChanged(); // reload cache details + } + } + } + + /** + * Listener for "add to favourites" button + */ + private class FavoriteAddClickListener extends AbstractWatchlistClickListener { + @Override + public void onClick(View arg0) { + doExecute(R.string.cache_dialog_favourite_add_title, + R.string.cache_dialog_favourite_add_message, + new FavoriteAddThread(new FavoriteUpdateHandler())); + } + } + + /** + * Listener for "remove from favourites" button + */ + private class FavoriteRemoveClickListener extends AbstractWatchlistClickListener { + @Override + public void onClick(View arg0) { + doExecute(R.string.cache_dialog_favourite_remove_title, + R.string.cache_dialog_favourite_remove_message, + new FavoriteRemoveThread(new FavoriteUpdateHandler())); + } + } + /** * shows/hides buttons, sets text in watchlist box */ @@ -1792,7 +1591,7 @@ public class CacheDetailActivity extends AbstractActivity { if (msg.what == -1) { showToast(res.getString(R.string.err_watchlist_failed)); } else { - updateWatchlistBox(); + CacheDetailActivity.this.notifyDataSetChanged(); // reload cache details } } } @@ -1869,38 +1668,26 @@ public class CacheDetailActivity extends AbstractActivity { return; } - final Bitmap bitmap = image.getBitmap(); - if (bitmap == null || bitmap.getWidth() <= 10) { - return; - } + try { + final Bitmap bitmap = image.getBitmap(); + if (bitmap == null || bitmap.getWidth() <= 10) { + return; + } - ((ImageView) view.findViewById(R.id.map_preview)).setImageDrawable(image); - view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE); + ((ImageView) view.findViewById(R.id.map_preview)).setImageDrawable(image); + view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE); + } catch (Exception e) { + Log.e("CacheDetailActivity.PreviewMapTask", e); + } } } } - private class DescriptionViewCreator implements PageViewCreator { - - private ScrollView view; + private class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @Override - public void notifyDataSetChanged() { - view = null; - } - - @Override - public View getView() { - if (view == null) { - view = (ScrollView) getDispatchedView(); - } - - return view; - } - - @Override - public View getDispatchedView() { + public ScrollView getDispatchedView() { if (cache == null) { // something is really wrong return null; @@ -1947,7 +1734,7 @@ public class CacheDetailActivity extends AbstractActivity { public void update(CharSequence editorText) { cache.setPersonalNote(editorText.toString()); setPersonalNote(personalNoteView); - app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); } }); editor.show(); @@ -2134,7 +1921,7 @@ public class CacheDetailActivity extends AbstractActivity { backcolor = color.darker_gray; } else { - Matcher matcher = DARK_COLOR_PATTERN.matcher(text); + MatcherWrapper matcher = new MatcherWrapper(DARK_COLOR_PATTERN, text); if (matcher.find()) { backcolor = color.darker_gray; } @@ -2143,31 +1930,15 @@ public class CacheDetailActivity extends AbstractActivity { } } - private class LogsViewCreator implements PageViewCreator { - private ListView view; - private boolean allLogs; + private class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> { + private final boolean allLogs; LogsViewCreator(boolean allLogs) { - super(); this.allLogs = allLogs; } @Override - public void notifyDataSetChanged() { - view = null; - } - - @Override - public View getView() { - if (view == null) { - view = (ListView) getDispatchedView(); - } - - return view; - } - - @Override - public View getDispatchedView() { + public ListView getDispatchedView() { if (cache == null) { // something is really wrong return null; @@ -2186,7 +1957,7 @@ public class CacheDetailActivity extends AbstractActivity { } } - if (sortedLogCounts.size() > 0) { + if (!sortedLogCounts.isEmpty()) { // sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() { @@ -2240,7 +2011,7 @@ public class CacheDetailActivity extends AbstractActivity { holder.count.setVisibility(View.VISIBLE); if (log.found == -1) { holder.count.setVisibility(View.GONE); - } else { + } else { holder.count.setText(res.getQuantityString(R.plurals.cache_counts, log.found, log.found)); } @@ -2261,7 +2032,7 @@ public class CacheDetailActivity extends AbstractActivity { holder.images.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - ImagesActivity.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<cgImage>(log.getLogImages())); + ImagesActivity.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<Image>(log.getLogImages())); } }); } else { @@ -2269,23 +2040,12 @@ public class CacheDetailActivity extends AbstractActivity { } // colored marker - holder.statusMarker.setVisibility(View.VISIBLE); - if (log.type == LogType.FOUND_IT - || log.type == LogType.WEBCAM_PHOTO_TAKEN - || log.type == LogType.ATTENDED) { - holder.statusMarker.setImageResource(R.drawable.mark_green); - } else if (log.type == LogType.PUBLISH_LISTING - || log.type == LogType.ENABLE_LISTING - || log.type == LogType.OWNER_MAINTENANCE) { - holder.statusMarker.setImageResource(R.drawable.mark_green_more); - } else if (log.type == LogType.DIDNT_FIND_IT - || log.type == LogType.NEEDS_MAINTENANCE - || log.type == LogType.NEEDS_ARCHIVE) { - holder.statusMarker.setImageResource(R.drawable.mark_red); - } else if (log.type == LogType.TEMP_DISABLE_LISTING - || log.type == LogType.ARCHIVE) { - holder.statusMarker.setImageResource(R.drawable.mark_red_more); - } else { + int marker = log.type.markerId; + if (marker != 0) { + holder.statusMarker.setVisibility(View.VISIBLE); + holder.statusMarker.setImageResource(marker); + } + else { holder.statusMarker.setVisibility(View.GONE); } @@ -2325,26 +2085,10 @@ public class CacheDetailActivity extends AbstractActivity { } } - private class WaypointsViewCreator implements PageViewCreator { - - private ScrollView view; - - @Override - public void notifyDataSetChanged() { - view = null; - } + private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @Override - public View getView() { - if (view == null) { - view = (ScrollView) getDispatchedView(); - } - - return view; - } - - @Override - public View getDispatchedView() { + public ScrollView getDispatchedView() { if (cache == null) { // something is really wrong return null; @@ -2355,10 +2099,10 @@ public class CacheDetailActivity extends AbstractActivity { final LinearLayout waypoints = (LinearLayout) view.findViewById(R.id.waypoints); // sort waypoints: PP, Sx, FI, OWN - final List<cgWaypoint> sortedWaypoints = new ArrayList<cgWaypoint>(cache.getWaypoints()); + final List<Waypoint> sortedWaypoints = new ArrayList<Waypoint>(cache.getWaypoints()); Collections.sort(sortedWaypoints); - for (final cgWaypoint wpt : sortedWaypoints) { + for (final Waypoint wpt : sortedWaypoints) { final LinearLayout waypointView = (LinearLayout) getLayoutInflater().inflate(R.layout.waypoint_item, null); // coordinates @@ -2440,26 +2184,10 @@ public class CacheDetailActivity extends AbstractActivity { } } - private class InventoryViewCreator implements PageViewCreator { - - private ListView view; - - @Override - public void notifyDataSetChanged() { - view = null; - } + private class InventoryViewCreator extends AbstractCachingPageViewCreator<ListView> { @Override - public View getView() { - if (view == null) { - view = (ListView) getDispatchedView(); - } - - return view; - } - - @Override - public View getDispatchedView() { + public ListView getDispatchedView() { if (cache == null) { // something is really wrong return null; @@ -2469,14 +2197,14 @@ public class CacheDetailActivity extends AbstractActivity { // TODO: fix layout, then switch back to Android-resource and delete copied one // this copy is modified to respect the text color - view.setAdapter(new ArrayAdapter<cgTrackable>(CacheDetailActivity.this, R.layout.simple_list_item_1, cache.getInventory())); + view.setAdapter(new ArrayAdapter<Trackable>(CacheDetailActivity.this, R.layout.simple_list_item_1, cache.getInventory())); view.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { Object selection = arg0.getItemAtPosition(arg2); - if (selection instanceof cgTrackable) { - cgTrackable trackable = (cgTrackable) selection; - cgeotrackable.startActivity(CacheDetailActivity.this, trackable.getGuid(), trackable.getGeocode(), trackable.getName()); + if (selection instanceof Trackable) { + Trackable trackable = (Trackable) selection; + TrackableActivity.startActivity(CacheDetailActivity.this, trackable.getGuid(), trackable.getGeocode(), trackable.getName()); } } }); @@ -2485,23 +2213,7 @@ public class CacheDetailActivity extends AbstractActivity { } } - private class ImagesViewCreator implements PageViewCreator { - - private View view; - - @Override - public void notifyDataSetChanged() { - view = null; - } - - @Override - public View getView() { - if (view == null) { - view = getDispatchedView(); - } - - return view; - } + private class ImagesViewCreator extends AbstractCachingPageViewCreator<View> { @Override public View getDispatchedView() { @@ -2510,7 +2222,7 @@ public class CacheDetailActivity extends AbstractActivity { } view = getLayoutInflater().inflate(R.layout.caches_images, null); - if (imagesList == null && viewPager.getCurrentItem() == pageOrder.indexOf(Page.IMAGES)) { + if (imagesList == null && isCurrentPage(Page.IMAGES)) { loadCacheImages(); } return view; @@ -2530,4 +2242,184 @@ public class CacheDetailActivity extends AbstractActivity { cacheIntent.putExtra("name", cacheName); context.startActivity(cacheIntent); } + + /** + * A dialog to allow the user to select reseting coordinates local/remote/both. + */ + private class ResetCacheCoordinatesDialog extends AlertDialog { + + final RadioButton resetBoth; + final RadioButton resetLocal; + + public ResetCacheCoordinatesDialog(final cgCache cache, final Waypoint wpt, final Activity activity) { + super(activity); + + View layout = activity.getLayoutInflater().inflate(R.layout.reset_cache_coords_dialog, null); + setView(layout); + + resetLocal = (RadioButton) layout.findViewById(R.id.reset_cache_coordinates_local); + resetBoth = (RadioButton) layout.findViewById(R.id.reset_cache_coordinates_local_and_remote); + + if (ConnectorFactory.getConnector(cache).supportsOwnCoordinates()) { + resetBoth.setVisibility(View.VISIBLE); + } + + layout.findViewById(R.id.reset).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + final ProgressDialog p = ProgressDialog.show(CacheDetailActivity.this, res.getString(R.string.cache), res.getString(R.string.waypoint_reset), true); + final Handler h = new Handler() { + private boolean remoteFinished = false; + private boolean localFinished = false; + + @Override + public void handleMessage(Message msg) { + if (msg.what == ResetCoordsThread.LOCAL) { + localFinished = true; + } else { + remoteFinished = true; + } + + if ((localFinished) && (remoteFinished || !resetBoth.isChecked())) { + p.dismiss(); + notifyDataSetChanged(); + } + } + + }; + new ResetCoordsThread(cache, h, wpt, resetLocal.isChecked() || resetBoth.isChecked(), resetBoth.isChecked(), p).start(); + } + }); + } + } + + private class ResetCoordsThread extends Thread { + + private final cgCache cache; + private final Handler handler; + private final boolean local; + private final boolean remote; + private final Waypoint wpt; + private ProgressDialog progress; + public static final int LOCAL = 0; + public static final int ON_WEBSITE = 1; + + public ResetCoordsThread(cgCache cache, Handler handler, final Waypoint wpt, boolean local, boolean remote, final ProgressDialog progress) { + this.cache = cache; + this.handler = handler; + this.local = local; + this.remote = remote; + this.wpt = wpt; + this.progress = progress; + } + + @Override + public void run() { + + if (local) { + runOnUiThread(new Runnable() { + @Override + public void run() { + progress.setMessage(res.getString(R.string.waypoint_reset_cache_coords)); + } + }); + cache.setCoords(wpt.getCoords()); + cache.setUserModifiedCoords(false); + cache.deleteWaypointForce(wpt); + cgData.saveChangedCache(cache); + handler.sendEmptyMessage(LOCAL); + } + + IConnector con = ConnectorFactory.getConnector(cache); + if (remote && con.supportsOwnCoordinates()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + progress.setMessage(res.getString(R.string.waypoint_coordinates_being_reset_on_website)); + } + }); + + final boolean result = con.deleteModifiedCoordinates(cache); + + runOnUiThread(new Runnable() { + + @Override + public void run() { + if (result) { + showToast(getString(R.string.waypoint_coordinates_has_been_reset_on_website)); + } else { + showToast(getString(R.string.waypoint_coordinates_upload_error)); + } + handler.sendEmptyMessage(ON_WEBSITE); + notifyDataSetChanged(); + } + + }); + + } + } + } + + @Override + protected String getTitle(Page page) { + // show number of waypoints directly in waypoint title + if (page == Page.WAYPOINTS) { + final int waypointCount = cache.getWaypoints().size(); + return res.getQuantityString(R.plurals.waypoints, waypointCount, waypointCount); + } + return res.getString(page.titleStringId); + } + + @Override + protected Pair<List<? extends Page>, Integer> getOrderedPages() { + final ArrayList<Page> pages = new ArrayList<Page>(); + pages.add(Page.WAYPOINTS); + pages.add(Page.DETAILS); + final int detailsIndex = pages.size() - 1; + pages.add(Page.DESCRIPTION); + if (cache.getLogs().isNotEmpty()) { + pages.add(Page.LOGS); + } + if (CollectionUtils.isNotEmpty(cache.getFriendsLogs())) { + pages.add(Page.LOGSFRIENDS); + } + if (CollectionUtils.isNotEmpty(cache.getInventory())) { + pages.add(Page.INVENTORY); + } + if (CollectionUtils.isNotEmpty(cache.getImages())) { + pages.add(Page.IMAGES); + } + return new ImmutablePair<List<? extends Page>, Integer>(pages, detailsIndex); + } + + @Override + protected AbstractViewPagerActivity.PageViewCreator createViewCreator(Page page) { + switch (page) { + case DETAILS: + return new DetailsViewCreator(); + + case DESCRIPTION: + return new DescriptionViewCreator(); + + case LOGS: + return new LogsViewCreator(true); + + case LOGSFRIENDS: + return new LogsViewCreator(false); + + case WAYPOINTS: + return new WaypointsViewCreator(); + + case INVENTORY: + return new InventoryViewCreator(); + + case IMAGES: + return new ImagesViewCreator(); + + default: + throw new IllegalArgumentException(); + } + } + } diff --git a/main/src/cgeo/geocaching/CachePopup.java b/main/src/cgeo/geocaching/CachePopup.java index e01e4a0..4bda294 100644 --- a/main/src/cgeo/geocaching/CachePopup.java +++ b/main/src/cgeo/geocaching/CachePopup.java @@ -79,7 +79,7 @@ public class CachePopup extends AbstractPopupActivity { if (StringUtils.isNotBlank(cache.getName())) { setTitle(cache.getName()); } else { - setTitle(geocode.toUpperCase()); + setTitle(geocode); } // actionbar icon @@ -89,8 +89,6 @@ public class CachePopup extends AbstractPopupActivity { addCacheDetails(); - findViewById(R.id.offline_box).setVisibility(View.VISIBLE); - // offline use final TextView offlineText = (TextView) findViewById(R.id.offline_text); final Button offlineRefresh = (Button) findViewById(R.id.offline_refresh); @@ -134,7 +132,7 @@ public class CachePopup extends AbstractPopupActivity { offlineStore.setOnClickListener(new StoreCacheClickListener()); } } catch (Exception e) { - Log.e("cgeopopup.init: " + e.toString()); + Log.e("cgeopopup.init", e); } // cache is loaded. remove progress-popup if any there diff --git a/main/src/cgeo/geocaching/Destination.java b/main/src/cgeo/geocaching/Destination.java index 441e959..10d51be 100644 --- a/main/src/cgeo/geocaching/Destination.java +++ b/main/src/cgeo/geocaching/Destination.java @@ -34,7 +34,13 @@ public final class Destination implements ICoordinates { @Override public boolean equals(final Object obj) { - return obj != null && obj instanceof Destination && ((Destination) obj).coords.equals(coords); + if (this == obj) { + return true; + } + if (!(obj instanceof Destination)) { + return false; + } + return ((Destination) obj).coords.equals(coords); } public long getId() { diff --git a/main/src/cgeo/geocaching/DirectionProvider.java b/main/src/cgeo/geocaching/DirectionProvider.java index 14fd283..c1f83ac 100644 --- a/main/src/cgeo/geocaching/DirectionProvider.java +++ b/main/src/cgeo/geocaching/DirectionProvider.java @@ -14,7 +14,7 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve private final SensorManager sensorManager; - // Previous values signalled to observers to avoid resending the same value when the + // Previous values signaled to observers to avoid resending the same value when the // device doesn't change orientation. The orientation is usually given with a 1 degree // precision by Android, so it is not uncommon to obtain exactly the same value several // times. @@ -38,14 +38,14 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve @Override public void onAccuracyChanged(final Sensor sensor, int accuracy) { /* - * There is a bug in Android, which appearently causes this method to be called every - * time the sensor _value_ changed, even if the _accuracy_ did not change. So logging - * this event leads to the log being flooded with multiple entries _per second_, - * which I experienced when running cgeo in a building (with GPS and network being - * unreliable). - * - * See for example https://code.google.com/p/android/issues/detail?id=14792 - */ + * There is a bug in Android, which apparently causes this method to be called every + * time the sensor _value_ changed, even if the _accuracy_ did not change. So logging + * this event leads to the log being flooded with multiple entries _per second_, + * which I experienced when running cgeo in a building (with GPS and network being + * unreliable). + * + * See for example https://code.google.com/p/android/issues/detail?id=14792 + */ //Log.i(Settings.tag, "Compass' accuracy is low (" + accuracy + ")"); } diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java index ef2a2cc..3958d5f 100644 --- a/main/src/cgeo/geocaching/EditWaypointActivity.java +++ b/main/src/cgeo/geocaching/EditWaypointActivity.java @@ -2,6 +2,9 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.ActivityMixin; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.WaypointType; @@ -28,6 +31,7 @@ import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.EditText; +import android.widget.RadioButton; import android.widget.Spinner; import java.util.ArrayList; @@ -39,7 +43,7 @@ public class EditWaypointActivity extends AbstractActivity { private String geocode = null; private int id = -1; private ProgressDialog waitDialog = null; - private cgWaypoint waypoint = null; + private Waypoint waypoint = null; private Geopoint gpTemp = null; private WaypointType type = WaypointType.OWN; private String prefix = "OWN"; @@ -77,6 +81,8 @@ public class EditWaypointActivity extends AbstractActivity { else { ((EditText) findViewById(R.id.note)).setText(StringUtils.trimToEmpty(waypoint.getNote())); } + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_ONLY); + setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache); } if (own) { @@ -85,7 +91,7 @@ public class EditWaypointActivity extends AbstractActivity { initializeDistanceUnitSelector(); } catch (Exception e) { - Log.e("EditWaypointActivity.loadWaypointHandler: " + e.toString()); + Log.e("EditWaypointActivity.loadWaypointHandler", e); } finally { if (waitDialog != null) { waitDialog.dismiss(); @@ -100,7 +106,7 @@ public class EditWaypointActivity extends AbstractActivity { super.onCreate(savedInstanceState); setTheme(); - setContentView(R.layout.waypoint_new); + setContentView(R.layout.edit_waypoint_activity); setTitle("waypoint"); // get parameters @@ -133,7 +139,7 @@ public class EditWaypointActivity extends AbstractActivity { addWaypoint.setOnClickListener(new coordsListener()); List<String> wayPointNames = new ArrayList<String>(); - for (WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN) { + for (WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) { wayPointNames.add(wpt.getL10n()); } AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.name); @@ -152,11 +158,27 @@ public class EditWaypointActivity extends AbstractActivity { initializeWaypointTypeSelector(); } + if (geocode != null) { + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + IConnector con = ConnectorFactory.getConnector(geocode); + setCoordsModificationVisibility(con, cache); + } + initializeDistanceUnitSelector(); disableSuggestions((EditText) findViewById(R.id.distance)); } + private void setCoordsModificationVisibility(IConnector con, cgCache cache) { + if (cache != null && (cache.getType() == CacheType.MYSTERY || cache.getType() == CacheType.MULTI)) { + findViewById(R.id.modify_cache_coordinates_group).setVisibility(View.VISIBLE); + findViewById(R.id.modify_cache_coordinates_local_and_remote).setVisibility(con.supportsOwnCoordinates() ? View.VISIBLE : View.GONE); + } else { + findViewById(R.id.modify_cache_coordinates_group).setVisibility(View.GONE); + findViewById(R.id.modify_cache_coordinates_local_and_remote).setVisibility(View.GONE); + } + } + @Override public void onResume() { super.onResume(); @@ -193,7 +215,7 @@ public class EditWaypointActivity extends AbstractActivity { Spinner waypointTypeSelector = (Spinner) findViewById(R.id.type); - wpTypes = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN); + wpTypes = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL); ArrayAdapter<WaypointType> wpAdapter = new ArrayAdapter<WaypointType>(this, android.R.layout.simple_spinner_item, wpTypes.toArray(new WaypointType[wpTypes.size()])); wpAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); waypointTypeSelector.setAdapter(wpAdapter); @@ -229,7 +251,6 @@ public class EditWaypointActivity extends AbstractActivity { final private GeoDirHandler geoDirHandler = new GeoDirHandler() { @Override public void updateGeoData(final IGeoData geo) { - Log.d("EditWaypointActivity.updateLocation called"); if (geo.getCoords() == null) { return; } @@ -239,8 +260,8 @@ public class EditWaypointActivity extends AbstractActivity { Button bLon = (Button) findViewById(R.id.buttonLongitude); bLat.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW)); bLon.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW)); - } catch (Exception e) { - Log.w("Failed to update location."); + } catch (final Exception e) { + Log.e("failed to update location", e); } } }; @@ -250,11 +271,11 @@ public class EditWaypointActivity extends AbstractActivity { @Override public void run() { try { - waypoint = app.loadWaypoint(id); + waypoint = cgData.loadWaypoint(id); loadWaypointHandler.sendMessage(Message.obtain()); } catch (Exception e) { - Log.e("cgeowaypoint.loadWaypoint.run: " + e.toString()); + Log.e("cgeowaypoint.loadWaypoint.run", e); } } } @@ -269,7 +290,7 @@ public class EditWaypointActivity extends AbstractActivity { } else if (gpTemp != null) { gp = gpTemp; } - cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); cgeocoords coordsDialog = new cgeocoords(EditWaypointActivity.this, cache, gp, app.currentGeo()); coordsDialog.setCancelable(true); coordsDialog.setOnCoordinateUpdate(new cgeocoords.CoordinateUpdate() { @@ -288,7 +309,7 @@ public class EditWaypointActivity extends AbstractActivity { } } - private class changeWaypointType implements OnItemSelectedListener { + private static class changeWaypointType implements OnItemSelectedListener { private changeWaypointType(EditWaypointActivity wpView) { this.wpView = wpView; @@ -312,7 +333,7 @@ public class EditWaypointActivity extends AbstractActivity { } } - private class changeDistanceUnit implements OnItemSelectedListener { + private static class changeDistanceUnit implements OnItemSelectedListener { private changeDistanceUnit(EditWaypointActivity unitView) { this.unitView = unitView; @@ -335,6 +356,7 @@ public class EditWaypointActivity extends AbstractActivity { @Override public void onClick(View arg0) { + // TODO Show progress across whole function, it is performing very long time on slower devices final String bearingText = ((EditText) findViewById(R.id.bearing)).getText().toString(); // combine distance from EditText and distanceUnit saved from Spinner final String distanceText = ((EditText) findViewById(R.id.distance)).getText().toString() + distanceUnit; @@ -388,12 +410,12 @@ public class EditWaypointActivity extends AbstractActivity { String name = ((EditText) findViewById(R.id.name)).getText().toString().trim(); // if no name is given, just give the waypoint its number as name - if (name.length() == 0) { - name = res.getString(R.string.waypoint) + " " + String.valueOf(wpCount + 1); + if (StringUtils.isEmpty(name)) { + name = res.getString(R.string.waypoint) + " " + (wpCount + 1); } final String note = ((EditText) findViewById(R.id.note)).getText().toString().trim(); - final cgWaypoint waypoint = new cgWaypoint(name, type, own); + final Waypoint waypoint = new Waypoint(name, type, own); waypoint.setGeocode(geocode); waypoint.setPrefix(prefix); waypoint.setLookup(lookup); @@ -401,20 +423,88 @@ public class EditWaypointActivity extends AbstractActivity { waypoint.setNote(note); waypoint.setId(id); - cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); if (null != cache && cache.addOrChangeWaypoint(waypoint, true)) { - app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); StaticMapsProvider.removeWpStaticMaps(id, geocode); if (Settings.isStoreOfflineWpMaps()) { - StaticMapsProvider.storeWaypointStaticMap(cache, EditWaypointActivity.this, waypoint, false); + StaticMapsProvider.storeWaypointStaticMap(cache, waypoint, false); + } + final RadioButton modifyLocal = (RadioButton) findViewById(R.id.modify_cache_coordinates_local); + final RadioButton modifyBoth = (RadioButton) findViewById(R.id.modify_cache_coordinates_local_and_remote); + if (modifyLocal.isChecked() || modifyBoth.isChecked()) { + if (!cache.hasUserModifiedCoords()) { + final Waypoint origWaypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false); + origWaypoint.setCoords(cache.getCoords()); + cache.addOrChangeWaypoint(origWaypoint, false); + cache.setUserModifiedCoords(true); + } + cache.setCoords(waypoint.getCoords()); + cgData.saveChangedCache(cache); + } + if (modifyBoth.isChecked() && waypoint.getCoords() != null) { + if (cache.supportsOwnCoordinates()) { + final ProgressDialog progress = ProgressDialog.show(EditWaypointActivity.this, getString(R.string.cache), getString(R.string.waypoint_coordinates_uploading_to_website, waypoint.getCoords()), true); + Handler finishHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + progress.dismiss(); + finish(); + } + }; + new UploadModifiedCoordsThread(cache, waypoint.getCoords(), progress, finishHandler).start(); + } else { + showToast(getString(R.string.waypoint_coordinates_couldnt_be_modified_on_website)); + } + } else { + finish(); } - finish(); } else { showToast(res.getString(R.string.err_waypoint_add_failed)); } } } + private class UploadModifiedCoordsThread extends Thread { + + private final Geopoint waypoint_uploaded; + private final ProgressDialog progress; + private final cgCache cache; + private final Handler handler; + + public UploadModifiedCoordsThread(cgCache cache, Geopoint wpt, ProgressDialog progress, Handler finishHandler) { + this.cache = cache; + this.waypoint_uploaded = wpt; + this.progress = progress; + this.handler = finishHandler; + } + + @Override + public void run() { + boolean result = false; + IConnector con = ConnectorFactory.getConnector(cache); + if (con.supportsOwnCoordinates()) { + result = con.uploadModifiedCoordinates(cache, waypoint_uploaded); + } + final boolean res = result; + runOnUiThread(new Runnable() { + + @Override + public void run() { + if (res) { + showToast(getString(R.string.waypoint_coordinates_has_been_modified_on_website, waypoint_uploaded.getCoords().toString())); + } else { + showToast(getString(R.string.waypoint_coordinates_upload_error)); + } + if (progress != null) { + progress.dismiss(); + } + handler.sendMessage(Message.obtain()); + } + }); + } + } + @Override public void goManual(View view) { if (id >= 0) { diff --git a/main/src/cgeo/geocaching/ICache.java b/main/src/cgeo/geocaching/ICache.java index 8f8baf9..030c53f 100644 --- a/main/src/cgeo/geocaching/ICache.java +++ b/main/src/cgeo/geocaching/ICache.java @@ -112,12 +112,12 @@ public interface ICache extends IBasicCache { /** * @return the list of trackables in this cache */ - public List<cgTrackable> getInventory(); + public List<Trackable> getInventory(); /** * @return the list of spoiler images */ - public List<cgImage> getSpoilers(); + public List<Image> getSpoilers(); /** * @return a statistic how often the caches has been found, disabled, archived etc. diff --git a/main/src/cgeo/geocaching/cgImage.java b/main/src/cgeo/geocaching/Image.java index b313ef5..22c76aa 100644 --- a/main/src/cgeo/geocaching/cgImage.java +++ b/main/src/cgeo/geocaching/Image.java @@ -8,22 +8,22 @@ import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; -public class cgImage implements Parcelable { +public class Image implements Parcelable { private final String url; private final String title; private final String description; - public cgImage(final String url, final String title, final String description) { + public Image(final String url, final String title, final String description) { this.url = url; this.title = title; this.description = description; } - public cgImage(final String url, final String title) { + public Image(final String url, final String title) { this(url, title, null); } - public cgImage(final Parcel in) { + public Image(final Parcel in) { url = in.readString(); title = in.readString(); description = in.readString(); @@ -41,15 +41,15 @@ public class cgImage implements Parcelable { dest.writeString(description); } - public static final Parcelable.Creator<cgImage> CREATOR = new Parcelable.Creator<cgImage>() { + public static final Parcelable.Creator<Image> CREATOR = new Parcelable.Creator<Image>() { @Override - public cgImage createFromParcel(Parcel in) { - return new cgImage(in); + public Image createFromParcel(Parcel in) { + return new Image(in); } @Override - public cgImage[] newArray(int size) { - return new cgImage[size]; + public Image[] newArray(int size) { + return new Image[size]; } }; diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java index 0accf12..24f699e 100644 --- a/main/src/cgeo/geocaching/ImagesActivity.java +++ b/main/src/cgeo/geocaching/ImagesActivity.java @@ -24,11 +24,10 @@ public class ImagesActivity extends AbstractActivity { private static final String EXTRAS_GEOCODE = "geocode"; private boolean offline; - private ArrayList<cgImage> imageNames; + private ArrayList<Image> imageNames; private ImagesList imagesList; private ImageType imgType = ImageType.SpoilerImages; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -62,7 +61,7 @@ public class ImagesActivity extends AbstractActivity { return; } - offline = app.isOffline(geocode, null) && (imgType == ImageType.SpoilerImages || Settings.isStoreLogImages()); + offline = cgData.isOffline(geocode, null) && (imgType == ImageType.SpoilerImages || Settings.isStoreLogImages()); } @Override @@ -78,24 +77,24 @@ public class ImagesActivity extends AbstractActivity { super.onStop(); } - public static void startActivityLogImages(final Context fromActivity, final String geocode, List<cgImage> logImages) { + public static void startActivityLogImages(final Context fromActivity, final String geocode, List<Image> logImages) { startActivity(fromActivity, geocode, logImages, ImageType.LogImages); } - private static void startActivity(final Context fromActivity, final String geocode, List<cgImage> logImages, ImageType imageType) { + private static void startActivity(final Context fromActivity, final String geocode, List<Image> logImages, ImageType imageType) { final Intent logImgIntent = new Intent(fromActivity, ImagesActivity.class); // if resuming our app within this activity, finish it and return to the cache activity logImgIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) - .putExtra(EXTRAS_GEOCODE, geocode.toUpperCase()) + .putExtra(EXTRAS_GEOCODE, geocode) .putExtra(EXTRAS_TYPE, imageType); // avoid forcing the array list as parameter type - final ArrayList<cgImage> arrayList = new ArrayList<cgImage>(logImages); + final ArrayList<Image> arrayList = new ArrayList<Image>(logImages); logImgIntent.putParcelableArrayListExtra(EXTRAS_IMAGES, arrayList); fromActivity.startActivity(logImgIntent); } - public static void startActivitySpoilerImages(final Context fromActivity, String geocode, List<cgImage> spoilers) { + public static void startActivitySpoilerImages(final Context fromActivity, String geocode, List<Image> spoilers) { startActivity(fromActivity, geocode, spoilers, ImageType.SpoilerImages); } diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java index b625bb5..df1038f 100644 --- a/main/src/cgeo/geocaching/LogEntry.java +++ b/main/src/cgeo/geocaching/LogEntry.java @@ -2,6 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.utils.DateUtils; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -10,7 +11,6 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.List; -import java.util.regex.Matcher; import java.util.regex.Pattern; public final class LogEntry { @@ -25,7 +25,7 @@ public final class LogEntry { public int found = -1; /** Friend's log entry */ public boolean friend = false; - private List<cgImage> logImages = null; + private List<Image> logImages = null; public String cacheName = ""; // used for trackables public String cacheGuid = ""; // used for trackables @@ -64,9 +64,9 @@ public final class LogEntry { log.compareTo(otherLog.log) == 0; } - public void addLogImage(final cgImage image) { + public void addLogImage(final Image image) { if (logImages == null) { - logImages = new ArrayList<cgImage>(); + logImages = new ArrayList<Image>(); } logImages.add(image); } @@ -74,7 +74,7 @@ public final class LogEntry { /** * @return the log images or an empty list, never <code>null</code> */ - public List<cgImage> getLogImages() { + public List<Image> getLogImages() { if (logImages == null) { return Collections.emptyList(); } @@ -87,7 +87,7 @@ public final class LogEntry { public CharSequence getImageTitles() { final List<String> titles = new ArrayList<String>(5); - for (cgImage image : getLogImages()) { + for (Image image : getLogImages()) { if (StringUtils.isNotBlank(image.getTitle())) { titles.add(image.getTitle()); } @@ -107,9 +107,13 @@ public final class LogEntry { */ public String getDisplayText() { if (Settings.getPlainLogs()) { - Matcher matcher = PATTERN_REMOVE_COLORS.matcher(log); + MatcherWrapper matcher = new MatcherWrapper(PATTERN_REMOVE_COLORS, log); return matcher.replaceAll(""); } return log; } + + public boolean isOwn() { + return author.equalsIgnoreCase(Settings.getUsername()); + } } diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java index 4ddec72..0217c08 100644 --- a/main/src/cgeo/geocaching/LogTrackableActivity.java +++ b/main/src/cgeo/geocaching/LogTrackableActivity.java @@ -47,7 +47,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat private int attempts = 0; private CheckBox tweetCheck = null; private LinearLayout tweetBox = null; - private cgTrackable trackable; + private Trackable trackable; private Handler showProgressHandler = new Handler() { @Override @@ -127,12 +127,12 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat } } - trackable = app.getTrackableByGeocode(geocode); + trackable = cgData.loadTrackable(geocode); if (StringUtils.isNotBlank(trackable.getName())) { setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getName()); } else { - setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getGeocode().toUpperCase()); + setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getGeocode()); } if (guid == null) { @@ -207,7 +207,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat tweetCheck.setChecked(true); if (CollectionUtils.isEmpty(possibleLogTypes)) { - possibleLogTypes = cgTrackable.getPossibleLogTypes(); + possibleLogTypes = Trackable.getPossibleLogTypes(); } final Button buttonPost = (Button) findViewById(R.id.post); @@ -311,7 +311,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat possibleLogTypes.addAll(typesPre); } } catch (Exception e) { - Log.e("LogTrackableActivity.LoadDataThread.run: " + e.toString()); + Log.e("LogTrackableActivity.LoadDataThread.run", e); } loadDataHandler.sendEmptyMessage(0); @@ -349,15 +349,15 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat return status; } catch (Exception e) { - Log.e("LogTrackableActivity.postLogFn: " + e.toString()); + Log.e("LogTrackableActivity.postLogFn", e); } return StatusCode.LOG_POST_ERROR; } - public static void startActivity(final Context context, final cgTrackable trackable) { + public static void startActivity(final Context context, final Trackable trackable) { final Intent logTouchIntent = new Intent(context, LogTrackableActivity.class); - logTouchIntent.putExtra("geocode", trackable.getGeocode().toUpperCase()); + logTouchIntent.putExtra("geocode", trackable.getGeocode()); logTouchIntent.putExtra("guid", trackable.getGuid()); logTouchIntent.putExtra("trackingcode", trackable.getTrackingcode()); context.startActivity(logTouchIntent); diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java index 6194013..4c9a230 100644 --- a/main/src/cgeo/geocaching/SearchActivity.java +++ b/main/src/cgeo/geocaching/SearchActivity.java @@ -28,6 +28,8 @@ import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.EditText; +import java.util.Locale; + public class SearchActivity extends AbstractActivity { private static final String EXTRAS_KEYWORDSEARCH = "keywordsearch"; @@ -109,7 +111,7 @@ public class SearchActivity extends AbstractActivity { final IConnector connector = ConnectorFactory.getConnector(geocode); if (connector instanceof ISearchByGeocode) { final Intent cachesIntent = new Intent(this, CacheDetailActivity.class); - cachesIntent.putExtra("geocode", geocode.toUpperCase()); + cachesIntent.putExtra("geocode", geocode.toUpperCase(Locale.US)); startActivity(cachesIntent); return true; } @@ -117,8 +119,8 @@ public class SearchActivity extends AbstractActivity { // Check if the query is a TB code final String trackable = BaseUtils.getMatch(query, GCConstants.PATTERN_TB_CODE, true, 0, "", false); if (StringUtils.isNotBlank(trackable)) { - final Intent trackablesIntent = new Intent(this, cgeotrackable.class); - trackablesIntent.putExtra("geocode", trackable.toUpperCase()); + final Intent trackablesIntent = new Intent(this, TrackableActivity.class); + trackablesIntent.putExtra("geocode", trackable.toUpperCase(Locale.US)); startActivity(trackablesIntent); return true; } @@ -159,7 +161,7 @@ public class SearchActivity extends AbstractActivity { findByGeocodeFn(); } }); - addHistoryEntries(geocodeEdit, app.geocodesInCache()); + addHistoryEntries(geocodeEdit, cgData.getRecentGeocodesForSearch()); final Button displayByGeocode = (Button) findViewById(R.id.display_geocode); displayByGeocode.setOnClickListener(new findByGeocodeListener()); @@ -211,7 +213,7 @@ public class SearchActivity extends AbstractActivity { findTrackableFn(); } }); - addHistoryEntries(trackable, app.getTrackableCodes()); + addHistoryEntries(trackable, cgData.getTrackableCodes()); disableSuggestions(trackable); @@ -406,8 +408,8 @@ public class SearchActivity extends AbstractActivity { return; } - final Intent trackablesIntent = new Intent(this, cgeotrackable.class); - trackablesIntent.putExtra("geocode", trackableText.toUpperCase()); + final Intent trackablesIntent = new Intent(this, TrackableActivity.class); + trackablesIntent.putExtra("geocode", trackableText.toUpperCase(Locale.US)); startActivity(trackablesIntent); } diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index e21717d..d1b1df6 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -40,38 +40,49 @@ public class SearchResult implements Parcelable { } }; + /** + * Build a new empty search result. + */ public SearchResult() { - this((Set<String>) null); + this(new HashSet<String>()); } - public SearchResult(SearchResult searchResult) { - if (searchResult != null) { - this.geocodes = new HashSet<String>(searchResult.geocodes); - this.error = searchResult.error; - this.url = searchResult.url; - this.viewstates = searchResult.viewstates; - this.setTotal(searchResult.getTotal()); - } else { - this.geocodes = new HashSet<String>(); - } + /** + * Copy a search result, for example to apply different filters on it. + * + * @param searchResult the original search result, which cannot be null + */ + public SearchResult(final SearchResult searchResult) { + geocodes = new HashSet<String>(searchResult.geocodes); + error = searchResult.error; + url = searchResult.url; + viewstates = searchResult.viewstates; + setTotal(searchResult.getTotal()); } - public SearchResult(final Set<String> geocodes, final int total) { - if (geocodes == null) { - this.geocodes = new HashSet<String>(); - } else { - this.geocodes = new HashSet<String>(geocodes.size()); - this.geocodes.addAll(geocodes); - } + /** + * Build a search result from an existing collection of geocodes. + * + * @param geocodes a non-null collection of geocodes + * @param total the total number of geocodes (FIXME: what is the meaning of this number wrt to geocodes.size()?) + */ + public SearchResult(final Collection<String> geocodes, final int total) { + this.geocodes = new HashSet<String>(geocodes.size()); + this.geocodes.addAll(geocodes); this.setTotal(total); } + /** + * Build a search result from an existing collection of geocodes. + * + * @param geocodes a non-null set of geocodes + */ public SearchResult(final Set<String> geocodes) { - this(geocodes, geocodes == null ? 0 : geocodes.size()); + this(geocodes, geocodes.size()); } public SearchResult(final Parcel in) { - ArrayList<String> list = new ArrayList<String>(); + final ArrayList<String> list = new ArrayList<String>(); in.readStringList(list); geocodes = new HashSet<String>(list); error = (StatusCode) in.readSerializable(); @@ -84,14 +95,24 @@ public class SearchResult implements Parcelable { setTotal(in.readInt()); } - public SearchResult(cgCache cache) { - this(); - addCache(cache); + /** + * Build a search result designating a single cache. + * + * @param cache the cache to include + */ + + public SearchResult(final cgCache cache) { + this(Collections.singletonList(cache)); } - public SearchResult(Collection<cgCache> caches) { + /** + * Build a search result from a collection of caches. + * + * @param caches the non-null collection of caches to include + */ + public SearchResult(final Collection<cgCache> caches) { this(); - for (cgCache cache : caches) { + for (final cgCache cache : caches) { addCache(cache); } } @@ -148,7 +169,7 @@ public class SearchResult implements Parcelable { return; } - this.viewstates = viewstates; + System.arraycopy(viewstates, 0, this.viewstates, 0, viewstates.length); } public int getTotal() { @@ -170,8 +191,7 @@ public class SearchResult implements Parcelable { SearchResult result = new SearchResult(this); result.geocodes.clear(); final ArrayList<cgCache> cachesForVote = new ArrayList<cgCache>(); - - final Set<cgCache> caches = cgeoapplication.getInstance().loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB); + final Set<cgCache> caches = cgData.loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB); for (cgCache cache : caches) { // Is there any reason to exclude the cache from the list? final boolean excludeCache = (excludeDisabled && cache.isDisabled()) || @@ -188,13 +208,13 @@ public class SearchResult implements Parcelable { public cgCache getFirstCacheFromResult(final EnumSet<LoadFlag> loadFlags) { if (geocodes != null && geocodes.size() >= 1) { - return cgeoapplication.getInstance().loadCache((String) geocodes.toArray()[0], loadFlags); + return cgData.loadCache((String) geocodes.toArray()[0], loadFlags); } return null; } public Set<cgCache> getCachesFromSearchResult(final EnumSet<LoadFlag> loadFlags) { - return cgeoapplication.getInstance().loadCaches(geocodes, loadFlags); + return cgData.loadCaches(geocodes, loadFlags); } /** Add the geocode to the search. No cache is loaded into the CacheCache */ @@ -213,11 +233,20 @@ public class SearchResult implements Parcelable { /** Add the cache geocode to the search and store the cache in the CacheCache */ public boolean addCache(final cgCache cache) { addGeocode(cache.getGeocode()); - return cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE)); + return cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE)); } public boolean isEmpty() { return geocodes.isEmpty(); } + public boolean hasUnsavedCaches() { + for (final String geocode : getGeocodes()) { + if (!cgData.isOffline(geocode, null)) { + return true; + } + } + return false; + } + } diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java index 7e6f91f..96aab88 100644 --- a/main/src/cgeo/geocaching/Settings.java +++ b/main/src/cgeo/geocaching/Settings.java @@ -75,7 +75,6 @@ public final class Settings { private static final String KEY_AUTO_VISIT_TRACKABLES = "trackautovisit"; private static final String KEY_AUTO_INSERT_SIGNATURE = "sigautoinsert"; private static final String KEY_ALTITUDE_CORRECTION = "altcorrection"; - private static final String KEY_USE_GOOGLE_NAVIGATION = "usegnav"; 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"; @@ -110,6 +109,8 @@ public final class Settings { private static final String KEY_PLAIN_LOGS = "plainLogs"; private static final String KEY_NATIVE_UA = "nativeUa"; private static final String KEY_MAP_DIRECTORY = "mapDirectory"; + private static final String KEY_CONNECTOR_OC_ACTIVE = "connectorOCActive"; + private static final String KEY_CONNECTOR_OC_USER = "connectorOCUser"; private final static int unitsMetric = 1; @@ -192,7 +193,6 @@ public final class Settings { 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_USE_GOOGLE_NAVIGATION, 0 != old.getInt(KEY_USE_GOOGLE_NAVIGATION, 1)); 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)); @@ -307,6 +307,42 @@ public final class Settings { }); } + public static boolean isOCConnectorActive() { + return sharedPrefs.getBoolean(KEY_CONNECTOR_OC_ACTIVE, false); + } + + public static boolean setOCConnectorActive(final boolean isActive) { + return editSharedSettings(new PrefRunnable() { + + @Override + public void edit(Editor edit) { + edit.putBoolean(KEY_CONNECTOR_OC_ACTIVE, isActive); + } + }); + } + + public static String getOCConnectorUserName() { + String ocConnectorUser = sharedPrefs.getString(KEY_CONNECTOR_OC_USER, null); + if (StringUtils.isBlank(ocConnectorUser)) { + return StringUtils.EMPTY; + } + return ocConnectorUser; + } + + public static boolean setOCConnectorUserName(final String userName) { + return editSharedSettings(new PrefRunnable() { + + @Override + public void edit(Editor edit) { + if (StringUtils.isBlank(userName)) { + edit.remove(KEY_CONNECTOR_OC_USER); + } else { + edit.putString(KEY_CONNECTOR_OC_USER, userName); + } + } + }); + } + public static boolean isGCvoteLogin() { final String preUsername = sharedPrefs.getString(KEY_USERNAME, null); final String prePassword = sharedPrefs.getString(KEY_GCVOTE_PASSWORD, null); @@ -672,20 +708,6 @@ public final class Settings { }); } - public static boolean isUseGoogleNavigation() { - return sharedPrefs.getBoolean(KEY_USE_GOOGLE_NAVIGATION, true); - } - - public static void setUseGoogleNavigation(final boolean useGoogleNavigation) { - editSharedSettings(new PrefRunnable() { - - @Override - public void edit(Editor edit) { - edit.putBoolean(KEY_USE_GOOGLE_NAVIGATION, useGoogleNavigation); - } - }); - } - public static boolean isAutoLoadDescription() { return sharedPrefs.getBoolean(KEY_LOAD_DESCRIPTION, false); } @@ -1331,7 +1353,7 @@ public final class Settings { FileUtils.listDir(result, directory, new ExtensionsBasedFileSelector(new String[] { "xml" }), null); - return result.toArray(new File[] {}); + return result.toArray(new File[result.size()]); } private static class ExtensionsBasedFileSelector extends FileSelector { diff --git a/main/src/cgeo/geocaching/SettingsActivity.java b/main/src/cgeo/geocaching/SettingsActivity.java index 823b52f..64a086d 100644 --- a/main/src/cgeo/geocaching/SettingsActivity.java +++ b/main/src/cgeo/geocaching/SettingsActivity.java @@ -5,7 +5,6 @@ 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.enumerations.CacheType; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.files.SimpleDirChooser; import cgeo.geocaching.maps.MapProviderFactory; @@ -24,6 +23,7 @@ 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; @@ -84,7 +84,7 @@ public class SettingsActivity extends AbstractActivity { } catch (Exception e) { showToast(res.getString(R.string.err_login_failed)); - Log.e("SettingsActivity.logInHandler: " + e.toString()); + Log.e("SettingsActivity.logInHandler", e); } if (loginDialog != null && loginDialog.isShowing()) { @@ -112,7 +112,7 @@ public class SettingsActivity extends AbstractActivity { } catch (Exception e) { showToast(res.getString(R.string.init_sendToCgeo_register_fail)); - Log.e("SettingsActivity.webHandler: " + e.toString()); + Log.e("SettingsActivity.webHandler", e); } if (webDialog != null && webDialog.isShowing()) { @@ -242,6 +242,21 @@ public class SettingsActivity extends AbstractActivity { } }); + // 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()); + } + }); + EditText ocUserEdit = (EditText) findViewById(R.id.oc_username); + if (ocUserEdit.getText().length() == 0) { + ocUserEdit.setText(Settings.getOCConnectorUserName()); + } + // gcvote settings final ImmutablePair<String, String> gcvoteLogin = Settings.getGCvoteLogin(); if (null != gcvoteLogin && null != gcvoteLogin.right) { @@ -495,16 +510,6 @@ public class SettingsActivity extends AbstractActivity { } }); - final CheckBox gnavButton = (CheckBox) findViewById(R.id.gnav); - gnavButton.setChecked(Settings.isUseGoogleNavigation()); - gnavButton.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - Settings.setUseGoogleNavigation(gnavButton.isChecked()); - } - }); - final CheckBox logOffline = (CheckBox) findViewById(R.id.log_offline); logOffline.setChecked(Settings.getLogOffline()); logOffline.setOnClickListener(new View.OnClickListener() { @@ -577,9 +582,7 @@ public class SettingsActivity extends AbstractActivity { @Override public void onClick(View v) { - Intent dirChooser = new Intent(SettingsActivity.this, SimpleDirChooser.class); - dirChooser.putExtra(SimpleDirChooser.START_DIR, Settings.getCustomRenderThemeBaseFolder()); - startActivityForResult(dirChooser, SELECT_THEMEFOLDER_REQUEST); + selectDirectory(Settings.getCustomRenderThemeBaseFolder(), SELECT_THEMEFOLDER_REQUEST); } }); @@ -591,9 +594,7 @@ public class SettingsActivity extends AbstractActivity { @Override public void onClick(View v) { - Intent dirChooser = new Intent(SettingsActivity.this, SimpleDirChooser.class); - dirChooser.putExtra(SimpleDirChooser.START_DIR, Settings.getGpxExportDir()); - startActivityForResult(dirChooser, SELECT_GPX_EXPORT_REQUEST); + selectDirectory(Settings.getGpxExportDir(), SELECT_GPX_EXPORT_REQUEST); } }); @@ -605,9 +606,7 @@ public class SettingsActivity extends AbstractActivity { @Override public void onClick(View v) { - Intent dirChooser = new Intent(SettingsActivity.this, SimpleDirChooser.class); - dirChooser.putExtra(SimpleDirChooser.START_DIR, Settings.getGpxImportDir()); - startActivityForResult(dirChooser, SELECT_GPX_IMPORT_REQUEST); + selectDirectory(Settings.getGpxImportDir(), SELECT_GPX_IMPORT_REQUEST); } }); @@ -775,7 +774,7 @@ public class SettingsActivity extends AbstractActivity { */ public void backup(View view) { // avoid overwriting an existing backup with an empty database (can happen directly after reinstalling the app) - if (app.getAllStoredCachesCount(true, CacheType.ALL) == 0) { + if (cgData.getAllCachesCount() == 0) { helpDialog(res.getString(R.string.init_backup), res.getString(R.string.init_backup_unnecessary)); return; } @@ -784,7 +783,7 @@ public class SettingsActivity extends AbstractActivity { new Thread() { @Override public void run() { - final String backupFileName = app.backupDatabase(); + final String backupFileName = cgData.backupDatabase(); runOnUiThread(new Runnable() { @Override public void run() { @@ -800,7 +799,7 @@ public class SettingsActivity extends AbstractActivity { private void refreshBackupLabel() { TextView lastBackup = (TextView) findViewById(R.id.backup_last); - File lastBackupFile = cgeoapplication.isRestoreFile(); + 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 { @@ -829,6 +828,7 @@ public class SettingsActivity extends AbstractActivity { 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 ocUserName = StringUtils.trimToEmpty(((EditText) findViewById(R.id.oc_username)).getText().toString()); String altitudeNew = StringUtils.trimToNull(((EditText) findViewById(R.id.altitude)).getText().toString()); int altitudeNewInt = parseNumber(altitudeNew, 0); @@ -842,6 +842,7 @@ public class SettingsActivity extends AbstractActivity { final boolean status4 = Settings.setAltCorrection(altitudeNewInt); final boolean status5 = Settings.setMapFileDirectory(mapDirectoryNew); final boolean status6 = Settings.setCustomRenderThemeBaseFolder(themesDirectoryNew); + final boolean status7 = Settings.setOCConnectorUserName(ocUserName); Settings.setShowWaypointsThreshold(waypointThreshold); String importNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.gpx_importdir)).getText().toString()); @@ -849,7 +850,7 @@ public class SettingsActivity extends AbstractActivity { Settings.setGpxImportDir(importNew); Settings.setGpxExportDir(exportNew); - return status1 && status2 && status3 && status4 && status5 && status6; + return status1 && status2 && status3 && status4 && status5 && status6 && status7; } /** @@ -951,7 +952,7 @@ public class SettingsActivity extends AbstractActivity { try { pin = Integer.parseInt(strings[1].trim()); } catch (Exception e) { - Log.e("webDialog: " + e.toString()); + Log.e("webDialog", e); } String code = strings[0]; Settings.setWebNameCode(nam, code); @@ -966,9 +967,12 @@ public class SettingsActivity extends AbstractActivity { @Override protected void onActivityResult(int requestCode, int resultCode, final Intent data) { super.onActivityResult(requestCode, resultCode, data); + if (resultCode != RESULT_OK) { + return; + } - if (requestCode == SELECT_MAPFILE_REQUEST) { - if (resultCode == RESULT_OK) { + switch (requestCode) { + case SELECT_MAPFILE_REQUEST: if (data.hasExtra("mapfile")) { final String mapFile = data.getStringExtra("mapfile"); Settings.setMapFile(mapFile); @@ -976,48 +980,72 @@ public class SettingsActivity extends AbstractActivity { showToast(res.getString(R.string.warn_invalid_mapfile)); } } - } - updateMapSourceMenu(); - initMapDirectoryEdittext(true); - } - if (requestCode == SELECT_GPX_EXPORT_REQUEST) { - checkDirectory(resultCode, data, R.id.gpx_exportdir, new RunnableWithArgument<String>() { + 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); - } - }); - } - if (requestCode == SELECT_GPX_IMPORT_REQUEST) { - checkDirectory(resultCode, data, R.id.gpx_importdir, 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); - } - }); - } - if (requestCode == SELECT_THEMEFOLDER_REQUEST) { - checkDirectory(resultCode, data, R.id.themefolder, 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); - } - }); + @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) { - if (data.hasExtra(SimpleDirChooser.EXTRA_CHOSEN_DIR)) { - final String directory = data.getStringExtra(SimpleDirChooser.EXTRA_CHOSEN_DIR); - runnableSetDir.run(directory); - EditText directoryText = (EditText) findViewById(textField); - directoryText.setText(directory); - directoryText.requestFocus(); + if (resultCode != RESULT_OK) { + return; + } + // we may come back from either our selfmade chooser or from the Open Intent manager + final String directory = data.hasExtra(SimpleDirChooser.EXTRA_CHOSEN_DIR) ? + data.getStringExtra(SimpleDirChooser.EXTRA_CHOSEN_DIR) : + 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) { + Intent dirChooser; + try { + dirChooser = new Intent(FileManagerIntents.ACTION_PICK_DIRECTORY); + if (StringUtils.isNotBlank(startDirectory)) { + dirChooser.setData(Uri.parse("file://" + new File(startDirectory).getAbsolutePath())); } + 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 + dirChooser = new Intent(this, SimpleDirChooser.class); + dirChooser.putExtra(SimpleDirChooser.START_DIR, startDirectory); + startActivityForResult(dirChooser, directoryKind); } } diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java index 05a18f2..263b6b8 100644 --- a/main/src/cgeo/geocaching/StaticMapsActivity.java +++ b/main/src/cgeo/geocaching/StaticMapsActivity.java @@ -10,7 +10,6 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -36,7 +35,6 @@ public class StaticMapsActivity extends AbstractActivity { private LayoutInflater inflater = null; private ProgressDialog waitDialog = null; private LinearLayout smapsView = null; - private BitmapFactory factory = null; private final Handler loadMapsHandler = new Handler() { @Override @@ -61,7 +59,7 @@ public class StaticMapsActivity extends AbstractActivity { showStaticMaps(); } } catch (Exception e) { - Log.e("StaticMapsActivity.loadMapsHandler: " + e.toString()); + Log.e("StaticMapsActivity.loadMapsHandler", e); } } }; @@ -131,10 +129,6 @@ public class StaticMapsActivity extends AbstractActivity { @Override public void run() { try { - if (factory == null) { - factory = new BitmapFactory(); - } - // try downloading 2 times for (int trials = 0; trials < 2; trials++) { for (int level = 1; level <= 5; level++) { @@ -151,7 +145,7 @@ public class StaticMapsActivity extends AbstractActivity { } } } catch (Exception e) { - Log.e("StaticMapsActivity.LoadMapsThread.run: " + e.toString()); + Log.e("StaticMapsActivity.LoadMapsThread.run", e); } } if (!maps.isEmpty()) { @@ -161,7 +155,7 @@ public class StaticMapsActivity extends AbstractActivity { loadMapsHandler.sendMessage(Message.obtain()); } catch (Exception e) { - Log.e("StaticMapsActivity.LoadMapsThread.run: " + e.toString()); + Log.e("StaticMapsActivity.LoadMapsThread.run", e); } } } @@ -183,23 +177,23 @@ public class StaticMapsActivity extends AbstractActivity { } private boolean downloadStaticMaps() { - final cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + final cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); if (waypoint_id == null) { showToast(res.getString(R.string.info_storing_static_maps)); - StaticMapsProvider.storeCacheStaticMap(cache, this, true); + StaticMapsProvider.storeCacheStaticMap(cache, true); return cache.hasStaticMap(); } - final cgWaypoint waypoint = cache.getWaypointById(waypoint_id); + final Waypoint waypoint = cache.getWaypointById(waypoint_id); if (waypoint != null) { showToast(res.getString(R.string.info_storing_static_maps)); - StaticMapsProvider.storeWaypointStaticMap(cache, this, waypoint, true); + StaticMapsProvider.storeWaypointStaticMap(cache, waypoint, true); return StaticMapsProvider.hasStaticMapForWaypoint(geocode, waypoint_id); } showToast(res.getString(R.string.err_detail_not_load_map_static)); return false; } - public static void startActivity(final Context activity, final String geocode, final boolean download, final cgWaypoint waypoint) { + public static void startActivity(final Context activity, final String geocode, final boolean download, final Waypoint waypoint) { final Intent intent = new Intent(activity, StaticMapsActivity.class); // if resuming our app within this activity, finish it and return to the cache activity intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 87a04fa..b418400 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -1,5 +1,6 @@ package cgeo.geocaching; +import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.concurrent.BlockingThreadPool; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.geopoint.GeopointFormatter.Format; @@ -12,10 +13,10 @@ import ch.boye.httpclientandroidlib.HttpResponse; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Point; import android.util.DisplayMetrics; import android.view.Display; import android.view.WindowManager; @@ -61,30 +62,25 @@ public class StaticMapsProvider { } final HttpResponse httpResponse = Network.getRequest(GOOGLE_STATICMAP_URL, params); - if (httpResponse != null) { - if (httpResponse.getStatusLine().getStatusCode() == 200) { - final File file = getMapFile(geocode, prefix, true); - if (LocalStorage.saveEntityToFile(httpResponse, file)) { - // Delete image if it has no contents - final long fileSize = file.length(); - if (fileSize < MIN_MAP_IMAGE_BYTES) { - file.delete(); - } - } - } else { - Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode()); - } - } else { + if (httpResponse == null) { Log.e("StaticMapsProvider.downloadMap: httpResponse is null"); + return; + } + if (httpResponse.getStatusLine().getStatusCode() != 200) { + Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode()); + return; + } + final File file = getMapFile(geocode, prefix, true); + if (LocalStorage.saveEntityToFile(httpResponse, file)) { + // Delete image if it has no contents + final long fileSize = file.length(); + if (fileSize < MIN_MAP_IMAGE_BYTES) { + file.delete(); + } } } public static void downloadMaps(cgCache cache) { - final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); - downloadMaps(cache, display); - } - - private static void downloadMaps(cgCache cache, Display display) { if (cache == null) { Log.e("downloadMaps - missing input parameter cache"); return; @@ -92,7 +88,7 @@ public class StaticMapsProvider { if ((!Settings.isStoreOfflineMaps() && !Settings.isStoreOfflineWpMaps()) || StringUtils.isBlank(cache.getGeocode())) { return; } - int edge = guessMaxDisplaySide(display); + int edge = guessMaxDisplaySide(); if (Settings.isStoreOfflineMaps() && cache.getCoords() != null) { storeCachePreviewMap(cache); @@ -103,18 +99,18 @@ public class StaticMapsProvider { if (Settings.isStoreOfflineWpMaps() && CollectionUtils.isNotEmpty(cache.getWaypoints())) { // remove all waypoint static map files due to origin cache waypoint id changed on saveCache LocalStorage.deleteFilesWithPrefix(cache.getGeocode(), MAP_FILENAME_PREFIX + WAYPOINT_PREFIX); - for (cgWaypoint waypoint : cache.getWaypoints()) { + for (Waypoint waypoint : cache.getWaypoints()) { storeWaypointStaticMap(cache.getGeocode(), edge, waypoint, false); } } } - public static void storeWaypointStaticMap(cgCache cache, Activity activity, cgWaypoint waypoint, boolean waitForResult) { - int edge = StaticMapsProvider.guessMaxDisplaySide(activity); + public static void storeWaypointStaticMap(cgCache cache, Waypoint waypoint, boolean waitForResult) { + int edge = StaticMapsProvider.guessMaxDisplaySide(); storeWaypointStaticMap(cache.getGeocode(), edge, waypoint, waitForResult); } - private static void storeWaypointStaticMap(final String geocode, int edge, cgWaypoint waypoint, final boolean waitForResult) { + private static void storeWaypointStaticMap(final String geocode, int edge, Waypoint waypoint, final boolean waitForResult) { if (geocode == null) { Log.e("storeWaypointStaticMap - missing input parameter geocode"); return; @@ -132,15 +128,15 @@ public class StaticMapsProvider { downloadMaps(geocode, wpMarkerUrl, WAYPOINT_PREFIX + waypoint.getId() + '_', wpLatlonMap, edge, null, waitForResult); } - public static void storeCacheStaticMap(cgCache cache, Activity activity, final boolean waitForResult) { - int edge = guessMaxDisplaySide(activity); + public static void storeCacheStaticMap(cgCache cache, final boolean waitForResult) { + int edge = guessMaxDisplaySide(); storeCacheStaticMap(cache, edge, waitForResult); } private static void storeCacheStaticMap(final cgCache cache, final int edge, final boolean waitForResult) { final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); final Parameters waypoints = new Parameters(); - for (final cgWaypoint waypoint : cache.getWaypoints()) { + for (final Waypoint waypoint : cache.getWaypoints()) { if (waypoint.getCoords() == null) { continue; } @@ -158,28 +154,25 @@ public class StaticMapsProvider { return; } final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); - final String markerUrl = MARKERS_URL + "my_location_mdpi.png"; final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); final int width = metrics.widthPixels; final int height = (int) (110 * metrics.density); + final String markerUrl = MARKERS_URL + "my_location_mdpi.png"; downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, width, height, null); } - private static int guessMaxDisplaySide(Display display) { - final int maxWidth = display.getWidth() - 25; - final int maxHeight = display.getHeight() - 25; + private static int guessMaxDisplaySide() { + Point displaySize = Compatibility.getDisplaySize(); + final int maxWidth = displaySize.x - 25; + final int maxHeight = displaySize.y - 25; if (maxWidth > maxHeight) { return maxWidth; } return maxHeight; } - private static int guessMaxDisplaySide(Activity activity) { - return guessMaxDisplaySide(((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()); - } - private static void downloadMaps(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int edge, final Parameters waypoints, boolean waitForResult) { if (waitForResult) { @@ -195,7 +188,7 @@ public class StaticMapsProvider { try { pool.add(currentTask, 20, TimeUnit.SECONDS); } catch (InterruptedException e) { - Log.e("StaticMapsProvider.downloadMaps error adding task: " + e.toString()); + Log.e("StaticMapsProvider.downloadMaps error adding task", e); } } } @@ -212,7 +205,7 @@ public class StaticMapsProvider { return url.toString(); } - private static String getWpMarkerUrl(final cgWaypoint waypoint) { + private static String getWpMarkerUrl(final Waypoint waypoint) { String type = waypoint.getWaypointType() != null ? waypoint.getWaypointType().id : null; return MARKERS_URL + "marker_waypoint_" + type + ".png"; } @@ -225,7 +218,7 @@ public class StaticMapsProvider { try { StaticMapsProvider.getMapFile(geocode, WAYPOINT_PREFIX + wp_id + '_' + level, false).delete(); } catch (Exception e) { - Log.e("StaticMapsProvider.removeWpStaticMaps: " + e.toString()); + Log.e("StaticMapsProvider.removeWpStaticMaps", e); } } } diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java new file mode 100644 index 0000000..5a9a5b4 --- /dev/null +++ b/main/src/cgeo/geocaching/StatusFragment.java @@ -0,0 +1,110 @@ +package cgeo.geocaching; + +import cgeo.geocaching.network.StatusUpdater.Status; +import cgeo.geocaching.utils.IObserver; +import cgeo.geocaching.utils.Log; + +import android.content.Intent; +import android.content.res.Resources; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +public class StatusFragment extends Fragment { + + private ViewGroup status; + private ImageView statusIcon; + private TextView statusMessage; + + final private StatusHandler statusHandler = new StatusHandler(); + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + status = (ViewGroup) inflater.inflate(R.layout.status, container, false); + statusIcon = (ImageView) status.findViewById(R.id.status_icon); + statusMessage = (TextView) status.findViewById(R.id.status_message); + return status; + } + + @Override + public void onResume() { + super.onResume(); + cgeoapplication.getInstance().getStatusUpdater().addObserver(statusHandler); + } + + @Override + public void onPause() { + cgeoapplication.getInstance().getStatusUpdater().deleteObserver(statusHandler); + super.onPause(); + } + + private class StatusHandler extends Handler implements IObserver<Status> { + + @Override + public void update(final Status data) { + obtainMessage(0, data).sendToTarget(); + } + + @Override + public void handleMessage(final Message msg) { + final Status data = (Status) msg.obj; + updateDisplay(data != null && data.message != null ? data : null); + } + + private void updateDisplay(final Status data) { + + if (data == null) { + status.setVisibility(View.INVISIBLE); + return; + } + + final Resources res = getResources(); + final String packageName = getActivity().getPackageName(); + + if (data.icon != null) { + final int iconId = res.getIdentifier(data.icon, "drawable", packageName); + if (iconId != 0) { + statusIcon.setImageResource(iconId); + statusIcon.setVisibility(View.VISIBLE); + } else { + Log.w("StatusHandler: could not find icon corresponding to @drawable/" + data.icon); + statusIcon.setVisibility(View.GONE); + } + } else { + statusIcon.setVisibility(View.GONE); + } + + String message = data.message; + if (data.messageId != null) { + final int messageId = res.getIdentifier(data.messageId, "string", packageName); + if (messageId != 0) { + message = res.getString(messageId); + } + } + + statusMessage.setText(message); + status.setVisibility(View.VISIBLE); + + if (data.url != null) { + status.setOnClickListener(new OnClickListener() { + @Override + public void onClick(final View v) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(data.url))); + } + }); + } else { + status.setClickable(false); + } + } + + } +} diff --git a/main/src/cgeo/geocaching/StoredList.java b/main/src/cgeo/geocaching/StoredList.java index cdff1cb..d6f0993 100644 --- a/main/src/cgeo/geocaching/StoredList.java +++ b/main/src/cgeo/geocaching/StoredList.java @@ -34,6 +34,29 @@ public class StoredList { return title + " [" + count + "]"; } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof StoredList)) { + return false; + } + StoredList other = (StoredList) obj; + if (id != other.id) { + return false; + } + return true; + } + public static class UserInterface { private final IAbstractActivity activity; private final cgeoapplication app; @@ -46,16 +69,23 @@ public class StoredList { } public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards) { - promptForListSelection(titleId, runAfterwards, false); + promptForListSelection(titleId, runAfterwards, false, -1); } - public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyMoveTargets) { - final List<StoredList> lists = app.getLists(); + public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyMoveTargets, final int exceptListId) { + final List<StoredList> lists = cgData.getLists(); if (lists == null) { return; } + if (exceptListId > StoredList.TEMPORARY_LIST_ID) { + StoredList exceptList = cgData.getList(exceptListId); + if (exceptList != null) { + lists.remove(exceptList); + } + } + final List<CharSequence> listsTitle = new ArrayList<CharSequence>(); for (StoredList list : lists) { listsTitle.add(list.getTitleAndCount()); @@ -94,7 +124,7 @@ public class StoredList { @Override public void run(final String listName) { - final int newId = app.createList(listName); + final int newId = cgData.createList(listName); if (newId >= cgData.customListIdOffset) { activity.showToast(res.getString(R.string.list_dialog_create_ok)); @@ -137,12 +167,12 @@ public class StoredList { } public void promptForListRename(final int listId, final Runnable runAfterRename) { - final StoredList list = app.getList(listId); + final StoredList list = cgData.getList(listId); handleListNameInput(list.title, R.string.list_dialog_rename_title, R.string.list_dialog_rename, new RunnableWithArgument<String>() { @Override public void run(final String listName) { - app.renameList(listId, listName); + cgData.renameList(listId, listName); if (runAfterRename != null) { runAfterRename.run(); } diff --git a/main/src/cgeo/geocaching/cgTrackable.java b/main/src/cgeo/geocaching/Trackable.java index 7ed3424..f777351 100644 --- a/main/src/cgeo/geocaching/cgTrackable.java +++ b/main/src/cgeo/geocaching/Trackable.java @@ -11,7 +11,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -public class cgTrackable implements ILogable { +public class Trackable implements ILogable { static final public int SPOTTED_UNSET = 0; static final public int SPOTTED_CACHE = 1; static final public int SPOTTED_USER = 2; @@ -38,17 +38,17 @@ public class cgTrackable implements ILogable { private String trackingcode = null; public String getUrl() { - if (StringUtils.startsWithIgnoreCase(geocode, "GK")) { - String hex = geocode.substring(3); + if (StringUtils.startsWithIgnoreCase(getGeocode(), "GK")) { + String hex = getGeocode().substring(3); try { int id = Integer.parseInt(hex, 16); return "http://geokrety.org/konkret.php?id=" + id; } catch (NumberFormatException e) { - Log.e("cgTrackable.getUrl", e); + Log.e("Trackable.getUrl", e); return null; } } - return "http://www.geocaching.com//track/details.aspx?tracker=" + geocode.toUpperCase(); + return "http://www.geocaching.com//track/details.aspx?tracker=" + geocode; } public String getGuid() { @@ -65,7 +65,7 @@ public class cgTrackable implements ILogable { } public void setGeocode(String geocode) { - this.geocode = geocode; + this.geocode = StringUtils.upperCase(geocode); } public String getIconUrl() { @@ -208,7 +208,7 @@ public class cgTrackable implements ILogable { } public boolean isLoggable() { - return !StringUtils.startsWithIgnoreCase(geocode, "GK"); + return !StringUtils.startsWithIgnoreCase(getGeocode(), "GK"); } public String getTrackingcode() { diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java new file mode 100644 index 0000000..df3c6e4 --- /dev/null +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -0,0 +1,677 @@ +package cgeo.geocaching; + +import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.activity.AbstractViewPagerActivity; +import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.network.Network; +import cgeo.geocaching.ui.AbstractCachingPageViewCreator; +import cgeo.geocaching.ui.CacheDetailsCreator; +import cgeo.geocaching.ui.Formatter; +import cgeo.geocaching.utils.BaseUtils; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.UnknownTagsHandler; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.drawable.BitmapDrawable; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivity.Page> { + + public enum Page { + DETAILS(R.string.detail), + LOGS(R.string.cache_logs); + + private final int resId; + + private Page(final int resId) { + this.resId = resId; + } + } + private static final int MENU_LOG_TOUCH = 1; + private static final int MENU_BROWSER_TRACKABLE = 2; + private Trackable trackable = null; + private String geocode = null; + private String name = null; + private String guid = null; + private String id = null; + private String contextMenuUser = null; + private LayoutInflater inflater = null; + private ProgressDialog waitDialog = null; + private Handler loadTrackableHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + if (trackable == null) { + if (waitDialog != null) { + waitDialog.dismiss(); + } + + if (StringUtils.isNotBlank(geocode)) { + showToast(res.getString(R.string.err_tb_find) + " " + geocode + "."); + } else { + showToast(res.getString(R.string.err_tb_find_that)); + } + + finish(); + return; + } + + try { + inflater = getLayoutInflater(); + geocode = trackable.getGeocode(); + + if (StringUtils.isNotBlank(trackable.getName())) { + setTitle(Html.fromHtml(trackable.getName()).toString()); + } else { + setTitle(trackable.getName()); + } + + invalidateOptionsMenuCompatible(); + reinitializeViewPager(); + + } catch (Exception e) { + Log.e("TrackableActivity.loadTrackableHandler: ", e); + } + + if (waitDialog != null) { + waitDialog.dismiss(); + } + } + }; + + public TrackableActivity() { + super("c:geo-trackable-details"); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(); + setContentView(R.layout.trackable_activity); + setTitle(res.getString(R.string.trackable)); + + // get parameters + Bundle extras = getIntent().getExtras(); + Uri uri = getIntent().getData(); + + // try to get data from extras + if (extras != null) { + geocode = extras.getString("geocode"); + name = extras.getString("name"); + guid = extras.getString("guid"); + id = extras.getString("id"); + } + + // try to get data from URI + if (geocode == null && guid == null && id == null && uri != null) { + String uriHost = uri.getHost().toLowerCase(Locale.US); + if (uriHost.contains("geocaching.com")) { + geocode = uri.getQueryParameter("tracker"); + guid = uri.getQueryParameter("guid"); + id = uri.getQueryParameter("id"); + + if (StringUtils.isNotBlank(geocode)) { + geocode = geocode.toUpperCase(Locale.US); + guid = null; + id = null; + } else if (StringUtils.isNotBlank(guid)) { + geocode = null; + guid = guid.toLowerCase(Locale.US); + id = null; + } else if (StringUtils.isNotBlank(id)) { + geocode = null; + guid = null; + id = id.toLowerCase(Locale.US); + } else { + showToast(res.getString(R.string.err_tb_details_open)); + finish(); + return; + } + } else if (uriHost.contains("coord.info")) { + String uriPath = uri.getPath().toLowerCase(Locale.US); + if (uriPath != null && uriPath.startsWith("/tb")) { + geocode = uriPath.substring(1).toUpperCase(Locale.US); + guid = null; + id = null; + } else { + showToast(res.getString(R.string.err_tb_details_open)); + finish(); + return; + } + } + } + + // no given data + if (geocode == null && guid == null && id == null) { + showToast(res.getString(R.string.err_tb_display)); + finish(); + return; + } + + String message; + if (StringUtils.isNotBlank(name)) { + message = Html.fromHtml(name).toString(); + } else if (StringUtils.isNotBlank(geocode)) { + message = geocode; + } else { + message = res.getString(R.string.trackable); + } + waitDialog = ProgressDialog.show(this, message, res.getString(R.string.trackable_details_loading), true, true); + + createViewPager(0, null); + LoadTrackableThread thread = new LoadTrackableThread(loadTrackableHandler, geocode, guid, id); + thread.start(); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) { + super.onCreateContextMenu(menu, view, info); + final int viewId = view.getId(); + + if (viewId == R.id.author) { // Log item author + contextMenuUser = ((TextView) view).getText().toString(); + } else { // Trackable owner, and user holding trackable now + RelativeLayout itemLayout = (RelativeLayout) view.getParent(); + TextView itemName = (TextView) itemLayout.findViewById(R.id.name); + + String selectedName = itemName.getText().toString(); + if (selectedName.equals(res.getString(R.string.trackable_owner))) { + contextMenuUser = trackable.getOwner(); + } else if (selectedName.equals(res.getString(R.string.trackable_spotted))) { + contextMenuUser = trackable.getSpottedName(); + } + } + + menu.setHeaderTitle(res.getString(R.string.user_menu_title) + " " + contextMenuUser); + menu.add(viewId, 1, 0, res.getString(R.string.user_menu_view_hidden)); + menu.add(viewId, 2, 0, res.getString(R.string.user_menu_view_found)); + menu.add(viewId, 3, 0, res.getString(R.string.user_menu_open_browser)); + } + + @Override + public boolean onContextItemSelected(final MenuItem item) { + switch (item.getItemId()) { + case 1: + cgeocaches.startActivityOwner(this, contextMenuUser); + return true; + case 2: + cgeocaches.startActivityUserName(this, contextMenuUser); + return true; + case 3: + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(contextMenuUser)))); + return true; + default: + return false; + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, MENU_LOG_TOUCH, 0, res.getString(R.string.trackable_log_touch)).setIcon(R.drawable.ic_menu_agenda); // log touch + menu.add(0, MENU_BROWSER_TRACKABLE, 0, res.getString(R.string.trackable_browser_open)).setIcon(R.drawable.ic_menu_info_details); // browser + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_LOG_TOUCH: + LogTrackableActivity.startActivity(this, trackable); + return true; + case MENU_BROWSER_TRACKABLE: + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl()))); + return true; + default: + return false; + } + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + if (trackable != null) { + menu.findItem(MENU_LOG_TOUCH).setEnabled(StringUtils.isNotBlank(geocode) && trackable.isLoggable()); + menu.findItem(MENU_BROWSER_TRACKABLE).setEnabled(StringUtils.isNotBlank(trackable.getUrl())); + } + return super.onPrepareOptionsMenu(menu); + } + + private class LoadTrackableThread extends Thread { + final private Handler handler; + final private String geocode; + final private String guid; + final private String id; + + public LoadTrackableThread(Handler handlerIn, String geocodeIn, String guidIn, String idIn) { + handler = handlerIn; + geocode = geocodeIn; + guid = guidIn; + id = idIn; + } + + @Override + public void run() { + trackable = cgData.loadTrackable(geocode); + + if ((trackable == null || trackable.isLoggable()) && !StringUtils.startsWithIgnoreCase(geocode, "GK")) { + trackable = GCParser.searchTrackable(geocode, guid, id); + } + handler.sendMessage(Message.obtain()); + } + } + + private class UserActionsListener implements View.OnClickListener { + + @Override + public void onClick(View view) { + if (view == null) { + return; + } + + try { + registerForContextMenu(view); + openContextMenu(view); + } catch (Exception e) { + Log.e("TrackableActivity.UserActionsListener.onClick ", e); + } + } + } + + private class TrackableIconThread extends Thread { + final private String url; + final private Handler handler; + + public TrackableIconThread(String urlIn, Handler handlerIn) { + url = urlIn; + handler = handlerIn; + } + + @Override + public void run() { + if (url == null || handler == null) { + return; + } + + try { + HtmlImage imgGetter = new HtmlImage(trackable.getGeocode(), false, 0, false); + + BitmapDrawable image = imgGetter.getDrawable(url); + Message message = handler.obtainMessage(0, image); + handler.sendMessage(message); + } catch (Exception e) { + Log.e("TrackableActivity.TrackableIconThread.run: ", e); + } + } + } + + private static class TrackableIconHandler extends Handler { + final private TextView view; + + public TrackableIconHandler(TextView viewIn) { + view = viewIn; + } + + @Override + public void handleMessage(Message message) { + final BitmapDrawable image = (BitmapDrawable) message.obj; + if (image != null && view != null) { + image.setBounds(0, 0, view.getHeight(), view.getHeight()); + view.setCompoundDrawables(image, null, null, null); + } + } + } + + public static void startActivity(final AbstractActivity fromContext, + final String guid, final String geocode, final String name) { + final Intent trackableIntent = new Intent(fromContext, TrackableActivity.class); + trackableIntent.putExtra("guid", guid); + trackableIntent.putExtra("geocode", geocode); + trackableIntent.putExtra("name", name); + fromContext.startActivity(trackableIntent); + } + + @Override + protected PageViewCreator createViewCreator(Page page) { + switch (page) { + case DETAILS: + return new DetailsViewCreator(); + case LOGS: + return new LogsViewCreator(); + default: + throw new IllegalArgumentException(); + } + } + + @Override + protected String getTitle(Page page) { + return res.getString(page.resId); + } + + @Override + protected Pair<List<? extends Page>, Integer> getOrderedPages() { + List<Page> pages = new ArrayList<TrackableActivity.Page>(); + pages.add(Page.DETAILS); + if (!trackable.getLogs().isEmpty()) { + pages.add(Page.LOGS); + } + return new ImmutablePair<List<? extends Page>, Integer>(pages, 0); + } + + public class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> { + + private class LogViewHolder { + + private final TextView added; + private final TextView type; + private final TextView author; + private final TextView location; + private final TextView log; + private final ImageView marker; + private final LinearLayout logImages; + + public LogViewHolder(View rowView) { + added = ((TextView) rowView.findViewById(R.id.added)); + type = ((TextView) rowView.findViewById(R.id.type)); + author = ((TextView) rowView.findViewById(R.id.author)); + location = ((TextView) rowView.findViewById(R.id.location)); + log = (TextView) rowView.findViewById(R.id.log); + marker = (ImageView) rowView.findViewById(R.id.log_mark); + logImages = (LinearLayout) rowView.findViewById(R.id.log_layout); + } + } + + @Override + public ListView getDispatchedView() { + view = (ListView) getLayoutInflater().inflate(R.layout.trackable_logs_view, null); + + if (trackable != null && trackable.getLogs() != null) { + view.setAdapter(new ArrayAdapter<LogEntry>(TrackableActivity.this, R.layout.trackable_logs_item, trackable.getLogs()) { + @Override + public View getView(int position, View convertView, android.view.ViewGroup parent) { + View rowView = convertView; + if (null == rowView) { + rowView = getLayoutInflater().inflate(R.layout.trackable_logs_item, null); + } + LogViewHolder holder = (LogViewHolder) rowView.getTag(); + if (null == holder) { + holder = new LogViewHolder(rowView); + rowView.setTag(holder); + } + + final LogEntry log = getItem(position); + fillViewHolder(holder, log); + return rowView; + } + }); + } + return view; + } + + protected void fillViewHolder(LogViewHolder holder, LogEntry log) { + if (log.date > 0) { + holder.added.setText(Formatter.formatShortDate(log.date)); + } + + holder.type.setText(log.type.getL10n()); + holder.author.setText(Html.fromHtml(log.author), TextView.BufferType.SPANNABLE); + + if (StringUtils.isBlank(log.cacheName)) { + holder.location.setVisibility(View.GONE); + } else { + holder.location.setText(Html.fromHtml(log.cacheName)); + final String cacheGuid = log.cacheGuid; + final String cacheName = log.cacheName; + holder.location.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View arg0) { + CacheDetailActivity.startActivityGuid(TrackableActivity.this, cacheGuid, Html.fromHtml(cacheName).toString()); + } + }); + } + + TextView logView = holder.log; + logView.setMovementMethod(LinkMovementMethod.getInstance()); + + String logText = log.log; + if (BaseUtils.containsHtml(logText)) { + logText = log.getDisplayText(); + logView.setText(Html.fromHtml(logText, new HtmlImage(null, false, StoredList.TEMPORARY_LIST_ID, false), null), TextView.BufferType.SPANNABLE); + } + else { + logView.setText(logText); + } + + ImageView statusMarker = holder.marker; + // colored marker + int marker = log.type.markerId; + if (marker != 0) { + statusMarker.setVisibility(View.VISIBLE); + statusMarker.setImageResource(marker); + } + else { + statusMarker.setVisibility(View.GONE); + } + + // add LogImages + LinearLayout logLayout = holder.logImages; + + if (log.hasLogImages()) { + + final ArrayList<Image> logImages = new ArrayList<Image>(log.getLogImages()); + + final View.OnClickListener listener = new View.OnClickListener() { + @Override + public void onClick(View v) { + ImagesActivity.startActivityLogImages(TrackableActivity.this, trackable.getGeocode(), logImages); + } + }; + + LinearLayout log_imgView = (LinearLayout) getLayoutInflater().inflate(R.layout.trackable_logs_img, null); + TextView log_img_title = (TextView) log_imgView.findViewById(R.id.title); + log_img_title.setText(log.getImageTitles()); + log_img_title.setOnClickListener(listener); + logLayout.addView(log_imgView); + } + + holder.author.setOnClickListener(new UserActionsListener()); + } + + } + + public class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> { + + @Override + public ScrollView getDispatchedView() { + view = (ScrollView) getLayoutInflater().inflate(R.layout.trackable_details_view, null); + final CacheDetailsCreator details = new CacheDetailsCreator(TrackableActivity.this, (LinearLayout) view.findViewById(R.id.details_list)); + + // action bar icon + if (StringUtils.isNotBlank(trackable.getIconUrl())) { + final TrackableIconHandler iconHandler = new TrackableIconHandler(((TextView) findViewById(R.id.actionbar_title))); + final TrackableIconThread iconThread = new TrackableIconThread(trackable.getIconUrl(), iconHandler); + iconThread.start(); + } + + // trackable name + details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown)); + + // trackable type + String tbType; + if (StringUtils.isNotBlank(trackable.getType())) { + tbType = Html.fromHtml(trackable.getType()).toString(); + } else { + tbType = res.getString(R.string.trackable_unknown); + } + details.add(R.string.trackable_type, tbType); + + // trackable geocode + details.add(R.string.trackable_code, trackable.getGeocode()); + + // trackable owner + TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown)); + if (StringUtils.isNotBlank(trackable.getOwner())) { + owner.setText(Html.fromHtml(trackable.getOwner()), TextView.BufferType.SPANNABLE); + owner.setOnClickListener(new UserActionsListener()); + } + + // trackable spotted + if (StringUtils.isNotBlank(trackable.getSpottedName()) || + trackable.getSpottedType() == Trackable.SPOTTED_UNKNOWN || + trackable.getSpottedType() == Trackable.SPOTTED_OWNER) { + boolean showTimeSpan = true; + StringBuilder text; + + if (trackable.getSpottedType() == Trackable.SPOTTED_CACHE) { + text = new StringBuilder(res.getString(R.string.trackable_spotted_in_cache) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString()); + } else if (trackable.getSpottedType() == Trackable.SPOTTED_USER) { + text = new StringBuilder(res.getString(R.string.trackable_spotted_at_user) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString()); + } else if (trackable.getSpottedType() == Trackable.SPOTTED_UNKNOWN) { + text = new StringBuilder(res.getString(R.string.trackable_spotted_unknown_location)); + } else if (trackable.getSpottedType() == Trackable.SPOTTED_OWNER) { + text = new StringBuilder(res.getString(R.string.trackable_spotted_owner)); + } else { + text = new StringBuilder("N/A"); + showTimeSpan = false; + } + + // days since last spotting + if (showTimeSpan && trackable.getLogs() != null) { + for (LogEntry log : trackable.getLogs()) { + if (log.type == LogType.RETRIEVED_IT || log.type == LogType.GRABBED_IT || log.type == LogType.DISCOVERED_IT || log.type == LogType.PLACED_IT) { + final int days = log.daysSinceLog(); + text.append(" (").append(res.getQuantityString(R.plurals.days_ago, days, days)).append(')'); + break; + } + } + } + + final TextView spotted = details.add(R.string.trackable_spotted, text.toString()); + spotted.setClickable(true); + if (Trackable.SPOTTED_CACHE == trackable.getSpottedType()) { + spotted.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View arg0) { + CacheDetailActivity.startActivityGuid(TrackableActivity.this, trackable.getSpottedGuid(), trackable.getSpottedName()); + } + }); + } else if (Trackable.SPOTTED_USER == trackable.getSpottedType()) { + spotted.setOnClickListener(new UserActionsListener()); + } + } + + // trackable origin + if (StringUtils.isNotBlank(trackable.getOrigin())) { + TextView origin = details.add(R.string.trackable_origin, ""); + origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE); + } + + // trackable released + if (trackable.getReleased() != null) { + details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime())); + } + + // trackable distance + if (trackable.getDistance() >= 0) { + details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance())); + } + + // trackable goal + if (StringUtils.isNotBlank(trackable.getGoal())) { + view.findViewById(R.id.goal_box).setVisibility(View.VISIBLE); + TextView descView = (TextView) view.findViewById(R.id.goal); + descView.setVisibility(View.VISIBLE); + descView.setText(Html.fromHtml(trackable.getGoal(), new HtmlImage(geocode, true, 0, false), null), TextView.BufferType.SPANNABLE); + descView.setMovementMethod(LinkMovementMethod.getInstance()); + } + + // trackable details + if (StringUtils.isNotBlank(trackable.getDetails())) { + view.findViewById(R.id.details_box).setVisibility(View.VISIBLE); + TextView descView = (TextView) view.findViewById(R.id.details); + descView.setVisibility(View.VISIBLE); + descView.setText(Html.fromHtml(trackable.getDetails(), new HtmlImage(geocode, true, 0, false), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE); + descView.setMovementMethod(LinkMovementMethod.getInstance()); + } + + // trackable image + if (StringUtils.isNotBlank(trackable.getImage())) { + view.findViewById(R.id.image_box).setVisibility(View.VISIBLE); + LinearLayout imgView = (LinearLayout) view.findViewById(R.id.image); + + final ImageView trackableImage = (ImageView) inflater.inflate(R.layout.trackable_image, null); + + trackableImage.setImageResource(R.drawable.image_not_loaded); + trackableImage.setClickable(true); + trackableImage.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View arg0) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getImage()))); + } + }); + + // try to load image + final Handler handler = new Handler() { + + @Override + public void handleMessage(Message message) { + BitmapDrawable image = (BitmapDrawable) message.obj; + if (image != null) { + trackableImage.setImageDrawable((BitmapDrawable) message.obj); + } + } + }; + + new Thread() { + + @Override + public void run() { + try { + HtmlImage imgGetter = new HtmlImage(geocode, true, 0, false); + + BitmapDrawable image = imgGetter.getDrawable(trackable.getImage()); + Message message = handler.obtainMessage(0, image); + handler.sendMessage(message); + } catch (Exception e) { + Log.e("cgeospoilers.onCreate.onClick.run: ", e); + } + } + }.start(); + + imgView.addView(trackableImage); + } + return view; + } + + } + +} diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java index 443ef3a..a29256c 100644 --- a/main/src/cgeo/geocaching/VisitCacheActivity.java +++ b/main/src/cgeo/geocaching/VisitCacheActivity.java @@ -7,7 +7,7 @@ import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.LogTypeTrackable; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.gcvote.GCVote; -import cgeo.geocaching.network.Network; +import cgeo.geocaching.loaders.UrlLoader; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.twitter.Twitter; import cgeo.geocaching.ui.DateDialog; @@ -19,14 +19,19 @@ import cgeo.geocaching.utils.LogTemplateProvider.LogContext; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; import android.app.Dialog; import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; import android.content.Intent; -import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.view.ContextMenu; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; +import android.util.SparseArray; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -42,14 +47,16 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Locale; -public class VisitCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent { - static final String EXTRAS_FOUND = "found"; - static final String EXTRAS_TEXT = "text"; +public class VisitCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent, LoaderManager.LoaderCallbacks<String> { static final String EXTRAS_GEOCODE = "geocode"; static final String EXTRAS_ID = "id"; private static final int SUBMENU_VOTE = 3; + private static final String SAVED_STATE_RATING = "cgeo.geocaching.saved_state_rating"; + private static final String SAVED_STATE_TYPE = "cgeo.geocaching.saved_state_type"; + private static final String SAVED_STATE_DATE = "cgeo.geocaching.saved_state_date"; private LayoutInflater inflater = null; private cgCache cache = null; @@ -57,119 +64,133 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD private String cacheid = null; private String geocode = null; private String text = null; - private boolean alreadyFound = false; private List<LogType> possibleLogTypes = new ArrayList<LogType>(); private String[] viewstates = null; - private boolean gettingViewstate = true; private List<TrackableLog> trackables = null; - private Calendar date = Calendar.getInstance(); - private LogType typeSelected = LogType.UNKNOWN; - private int attempts = 0; private Button postButton = null; - private Button clearButton = null; private CheckBox tweetCheck = null; private LinearLayout tweetBox = null; - private double rating = 0.0; private boolean tbChanged = false; + private SparseArray<TrackableLog> actionButtons; - // handlers - private final Handler loadDataHandler = new Handler() { + // Data to be saved while reconfiguring + private double rating; + private LogType typeSelected; + private Calendar date; - @Override - public void handleMessage(Message msg) { - if (!possibleLogTypes.contains(typeSelected)) { - typeSelected = possibleLogTypes.get(0); - setType(typeSelected); + @Override + public Loader<String> onCreateLoader(final int id, final Bundle args) { + if (!Settings.isLogin()) { // allow offline logging + showToast(res.getString(R.string.err_login)); + return null; + } + return new UrlLoader(getBaseContext(), "http://www.geocaching.com/seek/log.aspx", new Parameters("ID", cacheid)); + } - showToast(res.getString(R.string.info_log_type_changed)); - } + @Override + public void onLoaderReset(final Loader<String> loader) { + // Nothing to do + } - if (Login.isEmpty(viewstates)) { - if (attempts < 2) { - new LoadDataThread().start(); - } else { - showToast(res.getString(R.string.err_log_load_data)); - showProgress(false); - } - return; + @Override + public void onLoadFinished(final Loader<String> loader, final String page) { + if (page == null) { + showToast(res.getString(R.string.err_log_load_data)); + showProgress(false); + return; + } + + viewstates = Login.getViewstates(page); + trackables = GCParser.parseTrackableLog(page); + possibleLogTypes = GCParser.parseTypes(page); + possibleLogTypes.remove(LogType.UPDATE_COORDINATES); + + if (!possibleLogTypes.contains(typeSelected)) { + typeSelected = possibleLogTypes.get(0); + setType(typeSelected); + + showToast(res.getString(R.string.info_log_type_changed)); + } + + enablePostButton(true); + + initializeTrackablesAction(); + updateTrackablesList(); + + showProgress(false); + } + + private void initializeTrackablesAction() { + if (Settings.isTrackableAutoVisit()) { + for (TrackableLog trackable : trackables) { + trackable.action = LogTypeTrackable.VISITED; + tbChanged = true; } + } + } - gettingViewstate = false; // we're done, user can post log + private void updateTrackablesList() { + if (CollectionUtils.isEmpty(trackables)) { + return; + } + if (inflater == null) { + inflater = getLayoutInflater(); + } + actionButtons = new SparseArray<TrackableLog>(); - enablePostButton(true); + final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory); + inventoryView.removeAllViews(); - // add trackables - if (CollectionUtils.isNotEmpty(trackables)) { - if (inflater == null) { - inflater = getLayoutInflater(); - } + for (TrackableLog tb : trackables) { + LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.visit_trackable, null); - final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory); - inventoryView.removeAllViews(); + ((TextView) inventoryItem.findViewById(R.id.trackcode)).setText(tb.trackCode); + ((TextView) inventoryItem.findViewById(R.id.name)).setText(tb.name); + final TextView actionButton = (TextView) inventoryItem.findViewById(R.id.action); + actionButton.setId(tb.id); + actionButtons.put(actionButton.getId(), tb); + actionButton.setText(res.getString(tb.action.resourceId) + " ▼"); + actionButton.setOnClickListener(new View.OnClickListener() { - for (TrackableLog tb : trackables) { - LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.visit_trackable, null); - - ((TextView) inventoryItem.findViewById(R.id.trackcode)).setText(tb.trackCode); - ((TextView) inventoryItem.findViewById(R.id.name)).setText(tb.name); - ((TextView) inventoryItem.findViewById(R.id.action)) - .setText(res.getString(Settings.isTrackableAutoVisit() - ? LogTypeTrackable.VISITED.resourceId - : LogTypeTrackable.DO_NOTHING.resourceId) - + " ▼"); - - inventoryItem.setId(tb.id); - final String tbCode = tb.trackCode; - inventoryItem.setClickable(true); - registerForContextMenu(inventoryItem); - inventoryItem.findViewById(R.id.info).setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View view) { - final Intent trackablesIntent = new Intent(VisitCacheActivity.this, cgeotrackable.class); - trackablesIntent.putExtra(EXTRAS_GEOCODE, tbCode); - startActivity(trackablesIntent); - } - }); - inventoryItem.findViewById(R.id.action).setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View view) { - openContextMenu(view); - } - }); - - inventoryView.addView(inventoryItem); - - if (Settings.isTrackableAutoVisit()) { - tb.action = LogTypeTrackable.VISITED; - tbChanged = true; - } + @Override + public void onClick(View view) { + selectTrackableAction(view); } + }); - if (inventoryView.getChildCount() > 0) { - findViewById(R.id.inventory_box).setVisibility(View.VISIBLE); + final String tbCode = tb.trackCode; + inventoryItem.setClickable(true); + inventoryItem.findViewById(R.id.info).setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View view) { + final Intent trackablesIntent = new Intent(VisitCacheActivity.this, TrackableActivity.class); + trackablesIntent.putExtra(EXTRAS_GEOCODE, tbCode); + startActivity(trackablesIntent); } - if (inventoryView.getChildCount() > 1) { - final LinearLayout inventoryChangeAllView = (LinearLayout) findViewById(R.id.inventory_changeall); + }); + + inventoryView.addView(inventoryItem); + } - final Button changeButton = (Button) inventoryChangeAllView.findViewById(R.id.changebutton); - registerForContextMenu(changeButton); - changeButton.setOnClickListener(new View.OnClickListener() { + if (inventoryView.getChildCount() > 0) { + findViewById(R.id.inventory_box).setVisibility(View.VISIBLE); + } + if (inventoryView.getChildCount() > 1) { + final LinearLayout inventoryChangeAllView = (LinearLayout) findViewById(R.id.inventory_changeall); - @Override - public void onClick(View view) { - openContextMenu(view); - } - }); + final Button changeButton = (Button) inventoryChangeAllView.findViewById(R.id.changebutton); + changeButton.setOnClickListener(new View.OnClickListener() { - inventoryChangeAllView.setVisibility(View.VISIBLE); + @Override + public void onClick(View view) { + selectAllTrackablesAction(); } - } + }); - showProgress(false); + inventoryChangeAllView.setVisibility(View.VISIBLE); } - }; + } private void enablePostButton(boolean enabled) { postButton.setEnabled(enabled); @@ -184,20 +205,20 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } private void updatePostButtonText() { - if (postButton.isEnabled()) { - if (typeSelected == LogType.FOUND_IT && Settings.isGCvoteLogin()) { - if (rating == 0) { - postButton.setText(res.getString(R.string.log_post_no_rate)); - } else { - postButton.setText(res.getString(R.string.log_post_rate) + " " + ratingTextValue(rating) + "*"); - } - } else { - postButton.setText(res.getString(R.string.log_post)); - } + postButton.setText(getPostButtonText()); + } + + private String getPostButtonText() { + if (!postButton.isEnabled()) { + return res.getString(R.string.log_post_not_possible); } - else { - postButton.setText(res.getString(R.string.log_post_not_possible)); + if (typeSelected != LogType.FOUND_IT || !Settings.isGCvoteLogin()) { + return res.getString(R.string.log_post); } + if (rating == 0) { + return res.getString(R.string.log_post_no_rate); + } + return res.getString(R.string.log_post_rate) + " " + ratingTextValue(rating) + "*"; } private final Handler postLogHandler = new Handler() { @@ -233,44 +254,140 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTheme(); setContentView(R.layout.visit); setTitle(res.getString(R.string.log_new_log)); - // get parameters + // Get parameters from intent and basic cache information from database final Bundle extras = getIntent().getExtras(); if (extras != null) { cacheid = extras.getString(EXTRAS_ID); geocode = extras.getString(EXTRAS_GEOCODE); - text = extras.getString(EXTRAS_TEXT); - alreadyFound = extras.getBoolean(EXTRAS_FOUND); } if ((StringUtils.isBlank(cacheid)) && StringUtils.isNotBlank(geocode)) { - cacheid = app.getCacheid(geocode); + cacheid = cgData.getCacheidForGeocode(geocode); } if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(cacheid)) { - geocode = app.getGeocode(cacheid); + geocode = cgData.getGeocodeForGuid(cacheid); } - cache = cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + possibleLogTypes = cache.getPossibleLogTypes(); if (StringUtils.isNotBlank(cache.getName())) { setTitle(res.getString(R.string.log_new_log) + ": " + cache.getName()); } else { - setTitle(res.getString(R.string.log_new_log) + ": " + cache.getGeocode().toUpperCase()); + setTitle(res.getString(R.string.log_new_log) + ": " + cache.getGeocode()); + } + + // Get ids for later use + postButton = (Button) findViewById(R.id.post); + tweetBox = (LinearLayout) findViewById(R.id.tweet_box); + tweetCheck = (CheckBox) findViewById(R.id.tweet); + + // initialize with default values + setDefaultValues(); + + // Restore previous state + if (savedInstanceState != null) { + rating = savedInstanceState.getDouble(SAVED_STATE_RATING); + typeSelected = LogType.getById(savedInstanceState.getInt(SAVED_STATE_TYPE)); + date.setTimeInMillis(savedInstanceState.getLong(SAVED_STATE_DATE)); + } else { + // If log had been previously saved, load it now, otherwise initialize signature as needed + final LogEntry log = cgData.loadLogOffline(geocode); + if (log != null) { + typeSelected = log.type; + date.setTime(new Date(log.date)); + text = log.log; + } else if (StringUtils.isNotBlank(Settings.getSignature()) + && Settings.isAutoInsertSignature() + && StringUtils.isBlank(currentLogText())) { + insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache)), false); + } + } + updatePostButtonText(); + enablePostButton(false); + + final Button typeButton = (Button) findViewById(R.id.type); + typeButton.setText(typeSelected.getL10n()); + typeButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View view) { + selectLogType(); + } + }); + + final Button dateButton = (Button) findViewById(R.id.date); + setDate(date); + dateButton.setOnClickListener(new DateListener()); + + final EditText logView = (EditText) findViewById(R.id.log); + if (StringUtils.isBlank(currentLogText()) && StringUtils.isNotBlank(text)) { + logView.setText(text); } - init(); + tweetCheck.setChecked(true); + + final Button saveButton = (Button) findViewById(R.id.save); + saveButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + saveLog(true); + } + }); + + final Button clearButton = (Button) findViewById(R.id.clear); + clearButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + clearLog(); + } + }); + + getSupportLoaderManager().initLoader(0, null, this); } - @Override - public void onResume() { - super.onResume(); + private void setDefaultValues() { + date = Calendar.getInstance(); + rating = 0.0; + if (cache.isEventCache()) { + if (cache.hasOwnLog(LogType.WILL_ATTEND)) { + typeSelected = LogType.ATTENDED; + } + else { + typeSelected = LogType.WILL_ATTEND; + } + } + else { + if (cache.isFound()) { + typeSelected = LogType.NOTE; + } else { + typeSelected = LogType.FOUND_IT; + } + } + text = null; + } + + private void clearLog() { + cgData.clearLogOffline(geocode); + + setDefaultValues(); + + setType(typeSelected); + setDate(date); + + final EditText logView = (EditText) findViewById(R.id.log); + logView.setText(StringUtils.EMPTY); + showToast(res.getString(R.string.info_log_cleared)); } @Override @@ -280,13 +397,6 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - init(); - } - - @Override public boolean onCreateOptionsMenu(final Menu menu) { super.onCreateOptionsMenu(menu); @@ -335,184 +445,15 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } private static String ratingTextValue(final double rating) { - return String.format("%.1f", rating); + return String.format(Locale.getDefault(), "%.1f", rating); } @Override - public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) { - super.onCreateContextMenu(menu, view, info); - final int viewId = view.getId(); - - if (viewId == R.id.type) { - for (final LogType typeOne : possibleLogTypes) { - menu.add(viewId, typeOne.id, 0, typeOne.getL10n()); - Log.w("Adding " + typeOne + " " + typeOne.getL10n()); - } - } else if (viewId == R.id.changebutton) { - final int textId = findViewById(viewId).getId(); - - menu.setHeaderTitle(res.getString(R.string.log_tb_changeall)); - for (LogTypeTrackable logType : LogTypeTrackable.values()) { - menu.add(textId, logType.id, 0, res.getString(logType.resourceId)); - } - } else { - final int realViewId = findViewById(viewId).getId(); - - for (final TrackableLog tb : trackables) { - if (tb.id == realViewId) { - menu.setHeaderTitle(tb.name); - } - } - for (LogTypeTrackable logType : LogTypeTrackable.values()) { - menu.add(realViewId, logType.id, 0, res.getString(logType.resourceId)); - } - } - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - final int group = item.getGroupId(); - final int id = item.getItemId(); - - if (group == R.id.type) { - setType(LogType.getById(id)); - return true; - } - - if (group == R.id.changebutton) { - try { - final LogTypeTrackable logType = LogTypeTrackable.findById(id); - if (logType != null) { - final LinearLayout inventView = (LinearLayout) findViewById(R.id.inventory); - for (int count = 0; count < inventView.getChildCount(); count++) { - final LinearLayout tbView = (LinearLayout) inventView.getChildAt(count); - if (tbView == null) { - return false; - } - - final TextView tbText = (TextView) tbView.findViewById(R.id.action); - if (tbText == null) { - return false; - } - tbText.setText(res.getString(logType.resourceId) + " ▼"); - } - for (TrackableLog tb : trackables) { - tb.action = logType; - } - tbChanged = true; - return true; - } - } catch (Exception e) { - Log.e("cgeovisit.onContextItemSelected: " + e.toString()); - } - } else { - try { - final LogTypeTrackable logType = LogTypeTrackable.findById(id); - if (logType != null) { - final LinearLayout tbView = (LinearLayout) findViewById(group); - if (tbView == null) { - return false; - } - - final TextView tbText = (TextView) tbView.findViewById(R.id.action); - if (tbText == null) { - return false; - } - - for (TrackableLog tb : trackables) { - if (tb.id == group) { - tbChanged = true; - - tb.action = logType; - tbText.setText(res.getString(logType.resourceId) + " ▼"); - - Log.i("Trackable " + tb.trackCode + " (" + tb.name + ") has new action: #" + id); - } - } - - return true; - } - } catch (Exception e) { - Log.e("cgeovisit.onContextItemSelected: " + e.toString()); - } - } - - return false; - } - - public void init() { - postButton = (Button) findViewById(R.id.post); - tweetBox = (LinearLayout) findViewById(R.id.tweet_box); - tweetCheck = (CheckBox) findViewById(R.id.tweet); - clearButton = (Button) findViewById(R.id.clear); - final Button saveButton = (Button) findViewById(R.id.save); - - possibleLogTypes = cache.getPossibleLogTypes(); - - final LogEntry log = app.loadLogOffline(geocode); - if (log != null) { - typeSelected = log.type; - date.setTime(new Date(log.date)); - text = log.log; - updatePostButtonText(); - } else if (StringUtils.isNotBlank(Settings.getSignature()) - && Settings.isAutoInsertSignature() - && StringUtils.isBlank(((EditText) findViewById(R.id.log)).getText())) { - insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache)), false); - } - - if (!possibleLogTypes.contains(typeSelected)) { - if (alreadyFound) { - typeSelected = LogType.NOTE; - } else { - typeSelected = possibleLogTypes.get(0); - } - setType(typeSelected); - } - - final Button typeButton = (Button) findViewById(R.id.type); - registerForContextMenu(typeButton); - typeButton.setText(typeSelected.getL10n()); - typeButton.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View view) { - openContextMenu(view); - } - }); - - final Button dateButton = (Button) findViewById(R.id.date); - setDate(date); - dateButton.setOnClickListener(new DateListener()); - - final EditText logView = (EditText) findViewById(R.id.log); - if (StringUtils.isBlank(logView.getText()) && StringUtils.isNotBlank(text)) { - logView.setText(text); - } - - tweetCheck.setChecked(true); - - final ActivityState lastState = (ActivityState) getLastNonConfigurationInstance(); - if (lastState != null) { - lastState.restore(this); - } - - if (Login.isEmpty(viewstates)) { - enablePostButton(false); - new LoadDataThread().start(); - } else { - enablePostButton(true); - } - - saveButton.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - saveLog(true); - } - }); - - clearButton.setOnClickListener(new ClearListener()); + protected void onSaveInstanceState(final Bundle outState) { + super.onSaveInstanceState(outState); + outState.putDouble(SAVED_STATE_RATING, rating); + outState.putInt(SAVED_STATE_TYPE, typeSelected.id); + outState.putLong(SAVED_STATE_DATE, date.getTimeInMillis()); } @Override @@ -554,102 +495,13 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } private class PostListener implements View.OnClickListener { - - @Override - public void onClick(View arg0) { - if (!gettingViewstate) { - waitDialog = ProgressDialog.show(VisitCacheActivity.this, null, res.getString(R.string.log_saving), true); - waitDialog.setCancelable(true); - - final String log = ((EditText) findViewById(R.id.log)).getText().toString(); - final Thread thread = new PostLogThread(postLogHandler, log); - thread.start(); - } else { - showToast(res.getString(R.string.err_log_load_data_still)); - } - } - } - - private class ClearListener implements View.OnClickListener { - @Override public void onClick(View arg0) { - //TODO: unify this method and the code in init() - app.clearLogOffline(geocode); - - if (alreadyFound) { - typeSelected = LogType.NOTE; - } else { - typeSelected = possibleLogTypes.get(0); - } - date.setTime(new Date()); - text = null; - - setType(typeSelected); - - final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setOnClickListener(new DateListener()); - setDate(date); + waitDialog = ProgressDialog.show(VisitCacheActivity.this, null, res.getString(R.string.log_saving), true); + waitDialog.setCancelable(true); - final EditText logView = (EditText) findViewById(R.id.log); - logView.setText(""); - - clearButton.setOnClickListener(new ClearListener()); - - showToast(res.getString(R.string.info_log_cleared)); - } - } - - private class LoadDataThread extends Thread { - - public LoadDataThread() { - super("Load data for logging"); - if (cacheid == null) { - showToast(res.getString(R.string.err_detail_cache_forgot_visit)); - - finish(); - return; - } - if (!Settings.isLogin()) { // allow offline logging - showToast(res.getString(R.string.err_login)); - } - } - - @Override - public void run() { - if (!Settings.isLogin()) { - // enable only offline logging, don't get the current state of the cache - return; - } - final Parameters params = new Parameters(); - - gettingViewstate = true; - attempts++; - - try { - if (StringUtils.isNotBlank(cacheid)) { - params.put("ID", cacheid); - } else { - loadDataHandler.sendEmptyMessage(0); - return; - } - - final String page = Network.getResponseData(Network.getRequest("http://www.geocaching.com/seek/log.aspx", params)); - - viewstates = Login.getViewstates(page); - trackables = GCParser.parseTrackableLog(page); - - final List<LogType> typesPre = GCParser.parseTypes(page); - if (CollectionUtils.isNotEmpty(typesPre)) { - possibleLogTypes.clear(); - possibleLogTypes.addAll(typesPre); - possibleLogTypes.remove(LogType.UPDATE_COORDINATES); - } - } catch (Exception e) { - Log.e("cgeovisit.loadData.run: " + e.toString()); - } - - loadDataHandler.sendEmptyMessage(0); + final Thread thread = new PostLogThread(postLogHandler, currentLogText()); + thread.start(); } } @@ -686,11 +538,11 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD cache.setFound(true); } - app.updateCache(cache); + cgData.saveChangedCache(cache); } if (status == StatusCode.NO_ERROR) { - app.clearLogOffline(geocode); + cgData.clearLogOffline(geocode); } if (status == StatusCode.NO_ERROR && typeSelected == LogType.FOUND_IT && Settings.isUseTwitter() @@ -705,7 +557,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD return status; } catch (Exception e) { - Log.e("cgeovisit.postLogFn: " + e.toString()); + Log.e("cgeovisit.postLogFn", e); } return StatusCode.LOG_POST_ERROR; @@ -717,7 +569,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD // Do not erase the saved log if the user has removed all the characters // without using "Clear". This may be a manipulation mistake, and erasing // again will be easy using "Clear" while retyping the text may not be. - if (force || (log.length() > 0 && !StringUtils.equals(log, text))) { + if (force || (StringUtils.isNotEmpty(log) && !StringUtils.equals(log, text))) { cache.logOffline(this, log, date, typeSelected); } text = log; @@ -727,40 +579,76 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD return ((EditText) findViewById(R.id.log)).getText().toString(); } - private class ActivityState { - private final String[] viewstates; - private final List<TrackableLog> trackables; - private final int attempts; - private final List<LogType> possibleLogTypes; - private final LogType typeSelected; - private final double rating; - - public ActivityState() { - this.viewstates = VisitCacheActivity.this.viewstates; - this.trackables = VisitCacheActivity.this.trackables; - this.attempts = VisitCacheActivity.this.attempts; - this.possibleLogTypes = VisitCacheActivity.this.possibleLogTypes; - this.typeSelected = VisitCacheActivity.this.typeSelected; - this.rating = VisitCacheActivity.this.rating; - } - - public void restore(final VisitCacheActivity activity) { - activity.viewstates = this.viewstates; - activity.trackables = this.trackables; - activity.attempts = this.attempts; - activity.possibleLogTypes = this.possibleLogTypes; - activity.typeSelected = this.typeSelected; - activity.rating = this.rating; + @Override + protected LogContext getLogContext() { + return new LogContext(cache); + } + + private void selectAllTrackablesAction() { + Builder alert = new AlertDialog.Builder(VisitCacheActivity.this); + alert.setTitle(res.getString(R.string.log_tb_changeall)); + String[] tbLogTypes = getTBLogTypes(); + alert.setItems(tbLogTypes, new OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int position) { + final LogTypeTrackable logType = LogTypeTrackable.values()[position]; + for (TrackableLog tb : trackables) { + tb.action = logType; + } + tbChanged = true; + updateTrackablesList(); + dialog.dismiss(); + } + }); + alert.create().show(); + } + + private String[] getTBLogTypes() { + final LogTypeTrackable[] logTypeValues = LogTypeTrackable.values(); + String[] logTypes = new String[logTypeValues.length]; + for (int i = 0; i < logTypes.length; i++) { + logTypes[i] = res.getString(logTypeValues[i].resourceId); } + return logTypes; } - @Override - public Object onRetainNonConfigurationInstance() { - return new ActivityState(); + private void selectLogType() { + Builder alert = new AlertDialog.Builder(VisitCacheActivity.this); + String[] choices = new String[possibleLogTypes.size()]; + for (int i = 0; i < choices.length; i++) { + choices[i] = possibleLogTypes.get(i).getL10n(); + } + alert.setSingleChoiceItems(choices, possibleLogTypes.indexOf(typeSelected), new OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int position) { + setType(possibleLogTypes.get(position)); + dialog.dismiss(); + } + }); + alert.create().show(); } - @Override - protected LogContext getLogContext() { - return new LogContext(cache); + private void selectTrackableAction(View view) { + final int realViewId = view.getId(); + Builder alert = new AlertDialog.Builder(VisitCacheActivity.this); + final TrackableLog trackableLog = actionButtons.get(realViewId); + alert.setTitle(trackableLog.name); + String[] tbLogTypes = getTBLogTypes(); + alert.setItems(tbLogTypes, new OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int position) { + final LogTypeTrackable logType = LogTypeTrackable.values()[position]; + tbChanged = true; + trackableLog.action = logType; + Log.i("Trackable " + trackableLog.trackCode + " (" + trackableLog.name + ") has new action: #" + logType); + updateTrackablesList(); + dialog.dismiss(); + } + }); + alert.create().show(); } + } diff --git a/main/src/cgeo/geocaching/cgWaypoint.java b/main/src/cgeo/geocaching/Waypoint.java index 0e21c08..7a8b787 100644 --- a/main/src/cgeo/geocaching/cgWaypoint.java +++ b/main/src/cgeo/geocaching/Waypoint.java @@ -10,7 +10,7 @@ import android.widget.TextView; import java.util.List; -public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { +public class Waypoint implements IWaypoint, Comparable<Waypoint> { public static final String PREFIX_OWN = "OWN"; private static final int ORDER_UNDEFINED = -2; @@ -32,7 +32,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { * @param name * @param type */ - public cgWaypoint(final String name, final WaypointType type, final boolean own) { + public Waypoint(final String name, final WaypointType type, final boolean own) { this.name = name; this.waypointType = type; this.own = own; @@ -43,7 +43,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { * * @param other */ - public cgWaypoint(final cgWaypoint other) { + public Waypoint(final Waypoint other) { merge(other); this.waypointType = other.waypointType; id = 0; @@ -53,7 +53,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { nameView.setCompoundDrawablesWithIntrinsicBounds(res.getDrawable(waypointType.markerId), null, null, null); } - public void merge(final cgWaypoint old) { + public void merge(final Waypoint old) { if (StringUtils.isBlank(prefix)) { setPrefix(old.prefix); } @@ -79,15 +79,15 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { } } - public static void mergeWayPoints(List<cgWaypoint> newPoints, - List<cgWaypoint> oldPoints, boolean forceMerge) { + public static void mergeWayPoints(List<Waypoint> newPoints, + List<Waypoint> oldPoints, boolean forceMerge) { // copy user modified details of the waypoints if (newPoints != null && oldPoints != null) { - for (cgWaypoint old : oldPoints) { + for (Waypoint old : oldPoints) { if (old != null) { boolean merged = false; - if (old.name != null && old.name.length() > 0) { - for (cgWaypoint waypoint : newPoints) { + if (StringUtils.isNotEmpty(old.name)) { + for (Waypoint waypoint : newPoints) { if (waypoint != null && waypoint.name != null) { if (old.name.equalsIgnoreCase(waypoint.name)) { waypoint.merge(old); @@ -142,7 +142,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { } @Override - public int compareTo(cgWaypoint other) { + public int compareTo(Waypoint other) { return order() - other.order(); } @@ -156,7 +156,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { } public String getUrl() { - return "http://www.geocaching.com//seek/cache_details.aspx?wp=" + geocode.toUpperCase(); + return "http://www.geocaching.com//seek/cache_details.aspx?wp=" + geocode; } @Override @@ -174,7 +174,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { } public void setGeocode(String geocode) { - this.geocode = geocode; + this.geocode = StringUtils.upperCase(geocode); } @Override diff --git a/main/src/cgeo/geocaching/WaypointPopup.java b/main/src/cgeo/geocaching/WaypointPopup.java index 7fbfe10..a69b729 100644 --- a/main/src/cgeo/geocaching/WaypointPopup.java +++ b/main/src/cgeo/geocaching/WaypointPopup.java @@ -19,7 +19,7 @@ import android.widget.TextView; public class WaypointPopup extends AbstractPopupActivity { private static final String EXTRA_WAYPOINT_ID = "waypoint_id"; private int waypointId = 0; - private cgWaypoint waypoint = null; + private Waypoint waypoint = null; public WaypointPopup() { super("c:geo-waypoint-info", R.layout.waypoint_popup); @@ -38,12 +38,12 @@ public class WaypointPopup extends AbstractPopupActivity { @Override protected void init() { super.init(); - waypoint = app.loadWaypoint(waypointId); + waypoint = cgData.loadWaypoint(waypointId); try { if (StringUtils.isNotBlank(waypoint.getName())) { setTitle(waypoint.getName()); } else { - setTitle(waypoint.getGeocode().toUpperCase()); + setTitle(waypoint.getGeocode()); } // actionbar icon @@ -53,7 +53,7 @@ public class WaypointPopup extends AbstractPopupActivity { details = new CacheDetailsCreator(this, (LinearLayout) findViewById(R.id.waypoint_details_list)); //Waypoint geocode - details.add(R.string.cache_geocode, waypoint.getPrefix().toUpperCase() + waypoint.getGeocode().toUpperCase().substring(2)); + details.add(R.string.cache_geocode, waypoint.getPrefix() + waypoint.getGeocode().substring(2)); // Edit Button final Button buttonEdit = (Button) findViewById(R.id.edit); @@ -73,7 +73,7 @@ public class WaypointPopup extends AbstractPopupActivity { addCacheDetails(); } catch (Exception e) { - Log.e("cgeopopup.init: " + e.toString()); + Log.e("cgeopopup.init", e); } } diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index a648486..557665e 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -5,16 +5,16 @@ import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.network.Cookies; -import android.app.Activity; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.v4.app.FragmentActivity; import android.view.View; import android.widget.EditText; -public abstract class AbstractActivity extends Activity implements IAbstractActivity { +public abstract class AbstractActivity extends FragmentActivity implements IAbstractActivity { - private String helpTopic; + final private String helpTopic; protected cgeoapplication app = null; protected Resources res = null; diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java index dc9c0fe..f96a769 100644 --- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java @@ -3,13 +3,13 @@ package cgeo.geocaching.activity; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.compatibility.Compatibility; -import android.app.ListActivity; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.v4.app.FragmentListActivity; import android.view.View; -public abstract class AbstractListActivity extends ListActivity implements +public abstract class AbstractListActivity extends FragmentListActivity implements IAbstractActivity { private String helpTopic; diff --git a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java new file mode 100644 index 0000000..56431d4 --- /dev/null +++ b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java @@ -0,0 +1,272 @@ +package cgeo.geocaching.activity; + +import cgeo.geocaching.R; +import cgeo.geocaching.utils.Log; + +import com.viewpagerindicator.TitlePageIndicator; +import com.viewpagerindicator.TitleProvider; + +import org.apache.commons.lang3.tuple.Pair; + +import android.app.Activity; +import android.os.Parcelable; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.view.View; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Abstract activity with the ability to manage pages in a view pager. + * + * @param <Page> + * Enum listing all available pages of this activity. The pages available at a certain point of time are + * defined by overriding {@link #getOrderedPages()}. + */ +public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends AbstractActivity { + + protected AbstractViewPagerActivity(String helpTopic) { + super(helpTopic); + } + + /** + * A {@link List} of all available pages. + * + * TODO Move to adapter + */ + private final List<Page> pageOrder = new ArrayList<Page>(); + + /** + * Instances of all {@link PageViewCreator}. + */ + private final Map<Page, PageViewCreator> viewCreators = new HashMap<Page, PageViewCreator>(); + + /** + * The {@link ViewPager} for this activity. + */ + private ViewPager viewPager; + + /** + * The {@link ViewPagerAdapter} for this activity. + */ + private ViewPagerAdapter viewPagerAdapter; + + /** + * The {@link TitlePageIndicator} for this activity. + */ + private TitlePageIndicator titleIndicator; + + public interface PageViewCreator { + /** + * Returns a validated view. + * + * @return + */ + public View getDispatchedView(); + + /** + * Returns a (maybe cached) view. + * + * @return + */ + public View getView(); + + /** + * Handles changed data-sets. + */ + public void notifyDataSetChanged(); + } + + /** + * Page selection interface for the view pager. + * + */ + protected interface OnPageSelectedListener { + public void onPageSelected(int position); + } + + /** + * The ViewPagerAdapter for scrolling through pages of the CacheDetailActivity. + */ + private class ViewPagerAdapter extends PagerAdapter implements TitleProvider { + + @Override + public void destroyItem(View container, int position, Object object) { + ((ViewPager) container).removeView((View) object); + } + + @Override + public void finishUpdate(View container) { + } + + @Override + public int getCount() { + return pageOrder.size(); + } + + @Override + public Object instantiateItem(View container, int position) { + final Page page = pageOrder.get(position); + + PageViewCreator creator = viewCreators.get(page); + + if (null == creator && null != page) { + creator = AbstractViewPagerActivity.this.createViewCreator(page); + viewCreators.put(page, creator); + } + + View view = null; + + try { + if (null != creator) { + // Result from getView() is maybe cached, but it should be valid because the + // creator should be informed about data-changes with notifyDataSetChanged() + view = creator.getView(); + ((ViewPager) container).addView(view, 0); + } + } catch (Exception e) { + Log.e("ViewPagerAdapter.instantiateItem ", e); + } + + return view; + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public void restoreState(Parcelable arg0, ClassLoader arg1) { + } + + @Override + public Parcelable saveState() { + return null; + } + + @Override + public void startUpdate(View arg0) { + } + + @Override + public int getItemPosition(Object object) { + // We are doing the caching. So pretend that the view is gone. + // The ViewPager will get it back in instantiateItem() + return POSITION_NONE; + } + + @Override + public String getTitle(int position) { + final Page page = pageOrder.get(position); + if (null == page) { + return ""; + } + return AbstractViewPagerActivity.this.getTitle(page); + } + + } + + /** + * Create the view pager. Call this from the {@link Activity#onCreate} implementation. + * + * @param startPageIndex + * index of the page shown first + * @param pageSelectedListener + * page selection listener or <code>null</code> + */ + protected final void createViewPager(int startPageIndex, final OnPageSelectedListener pageSelectedListener) { + // initialize ViewPager + viewPager = (ViewPager) findViewById(R.id.viewpager); + viewPagerAdapter = new ViewPagerAdapter(); + viewPager.setAdapter(viewPagerAdapter); + + titleIndicator = (TitlePageIndicator) findViewById(R.id.pager_indicator); + titleIndicator.setViewPager(viewPager); + if (pageSelectedListener != null) { + titleIndicator.setOnPageChangeListener(new OnPageChangeListener() { + @Override + public void onPageSelected(int position) { + pageSelectedListener.onPageSelected(position); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageScrollStateChanged(int state) { + } + }); + } + + // switch to entry page (last used or 2) + if (viewPagerAdapter.getCount() < startPageIndex) { + for (int i = 0; i <= startPageIndex; i++) { + // we can't switch to a page that is out of bounds, so we add null-pages + pageOrder.add(null); + } + } + viewPager.setCurrentItem(startPageIndex, false); + } + + /** + * create the view creator for the given page + * + * @return new view creator + */ + protected abstract PageViewCreator createViewCreator(Page page); + + /** + * get the title for the given page + */ + protected abstract String getTitle(Page page); + + protected final void reinitializeViewPager() { + // notify all creators that the data has changed + for (PageViewCreator creator : viewCreators.values()) { + creator.notifyDataSetChanged(); + } + + pageOrder.clear(); + final Pair<List<? extends Page>, Integer> pagesAndIndex = getOrderedPages(); + pageOrder.addAll(pagesAndIndex.getLeft()); + + // switch to details page, if we're out of bounds + final int defaultPage = pagesAndIndex.getRight().intValue(); + if (viewPager.getCurrentItem() < 0 || viewPager.getCurrentItem() >= viewPagerAdapter.getCount()) { + viewPager.setCurrentItem(defaultPage, false); + } + + // notify the adapter that the data has changed + viewPagerAdapter.notifyDataSetChanged(); + + // notify the indicator that the data has changed + titleIndicator.notifyDataSetChanged(); + } + + /** + * @return the currently available list of ordered pages, together with the index of the default page + */ + protected abstract Pair<List<? extends Page>, Integer> getOrderedPages(); + + public final Page getPage(int position) { + return pageOrder.get(position); + } + + protected final int getPageIndex(Page page) { + return pageOrder.indexOf(page); + } + + protected final PageViewCreator getViewCreator(Page page) { + return viewCreators.get(page); + } + + protected final boolean isCurrentPage(Page page) { + return viewPager.getCurrentItem() == getPageIndex(page); + } +} diff --git a/main/src/cgeo/geocaching/activity/FilteredActivity.java b/main/src/cgeo/geocaching/activity/FilteredActivity.java new file mode 100644 index 0000000..0370d63 --- /dev/null +++ b/main/src/cgeo/geocaching/activity/FilteredActivity.java @@ -0,0 +1,11 @@ +package cgeo.geocaching.activity; + +import android.view.View; + +public interface FilteredActivity { + /** + * called from the filter bar view + */ + public void showFilterMenu(final View view); + +} diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java index ac6fc1c..ad421f6 100644 --- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java @@ -2,7 +2,7 @@ package cgeo.geocaching.apps; import cgeo.geocaching.R; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; @@ -22,6 +22,7 @@ import android.location.Location; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; /** * for the Locus API: @@ -30,7 +31,7 @@ import java.util.List; */ public abstract class AbstractLocusApp extends AbstractApp { private static final String INTENT = Intent.ACTION_VIEW; - private static final SimpleDateFormat ISO8601DATE = new SimpleDateFormat("yyyy-MM-dd'T'"); + private static final SimpleDateFormat ISO8601DATE = new SimpleDateFormat("yyyy-MM-dd'T'", Locale.US); protected AbstractLocusApp() { super(getString(R.string.caches_map_locus), INTENT); @@ -47,11 +48,11 @@ public abstract class AbstractLocusApp extends AbstractApp { /** * Display a list of caches / waypoints in Locus - * + * * @param objectsToShow * which caches/waypoints to show * @param withCacheWaypoints - * wether to give waypoints of caches to Locus or not + * Whether to give waypoints of caches to Locus or not * @param activity */ protected static boolean showInLocus(final List<?> objectsToShow, final boolean withCacheWaypoints, final boolean export, @@ -67,8 +68,8 @@ public abstract class AbstractLocusApp extends AbstractApp { // get icon and Point if (o instanceof cgCache) { p = getCachePoint((cgCache) o, withCacheWaypoints, withCacheDetails); - } else if (o instanceof cgWaypoint) { - p = getWaypointPoint((cgWaypoint) o); + } else if (o instanceof Waypoint) { + p = getWaypointPoint((Waypoint) o); } if (p != null) { pd.addPoint(p); @@ -85,7 +86,7 @@ public abstract class AbstractLocusApp extends AbstractApp { final ArrayList<PointsData> data = new ArrayList<PointsData>(); data.add(pd); DisplayData.sendDataCursor(activity, data, - "content://" + LocusDataStorageProvider.class.getCanonicalName().toLowerCase(), + "content://" + LocusDataStorageProvider.class.getCanonicalName().toLowerCase(Locale.US), export); } @@ -145,7 +146,7 @@ public abstract class AbstractLocusApp extends AbstractApp { if (withWaypoints && cache.hasWaypoints()) { pg.waypoints = new ArrayList<PointGeocachingDataWaypoint>(); - for (cgWaypoint waypoint : cache.getWaypoints()) { + for (Waypoint waypoint : cache.getWaypoints()) { if (waypoint == null || waypoint.getCoords() == null) { continue; } @@ -181,7 +182,7 @@ public abstract class AbstractLocusApp extends AbstractApp { * @param waypoint * @return null, when the <code>Point</code> could not be constructed */ - private static Point getWaypointPoint(cgWaypoint waypoint) { + private static Point getWaypointPoint(Waypoint waypoint) { if (waypoint == null || waypoint.getCoords() == null) { return null; } diff --git a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java index 61528ea..8087d6d 100644 --- a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java +++ b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java @@ -2,24 +2,23 @@ package cgeo.geocaching.apps.cache; import cgeo.geocaching.cgCache; import cgeo.geocaching.apps.AbstractApp; +import cgeo.geocaching.apps.cache.navi.CacheNavigationApp; import android.app.Activity; import android.content.Intent; -abstract class AbstractGeneralApp extends AbstractApp implements GeneralApp { +abstract class AbstractGeneralApp extends AbstractApp implements CacheNavigationApp { protected AbstractGeneralApp(String name, String packageName) { super(name, null, packageName); } @Override - public boolean invoke(Activity activity, cgCache cache) { + public void navigate(Activity activity, cgCache cache) { final Intent intent = getLaunchIntent(); if (intent != null) { intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); activity.startActivity(intent); - return true; } - return false; } } diff --git a/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java b/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java index 6e7cdca..4ba336f 100644 --- a/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java +++ b/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java @@ -6,15 +6,12 @@ import cgeo.geocaching.enumerations.CacheAttribute; public class CacheBeaconApp extends AbstractGeneralApp { - protected CacheBeaconApp() { + public CacheBeaconApp() { super(getString(R.string.cache_menu_cachebeacon), "de.fun2code.android.cachebeacon"); } @Override public boolean isEnabled(cgCache cache) { - if (cache == null) { - return false; - } return cache.hasAttribute(CacheAttribute.WIRELESS_BEACON, true); } diff --git a/main/src/cgeo/geocaching/apps/cache/GccApp.java b/main/src/cgeo/geocaching/apps/cache/GccApp.java index 9000d9e..b129b45 100644 --- a/main/src/cgeo/geocaching/apps/cache/GccApp.java +++ b/main/src/cgeo/geocaching/apps/cache/GccApp.java @@ -2,8 +2,8 @@ package cgeo.geocaching.apps.cache; import cgeo.geocaching.R; -class GccApp extends AbstractGeneralApp { - GccApp() { +public class GccApp extends AbstractGeneralApp { + public GccApp() { super(getString(R.string.cache_menu_gcc), "eisbehr.gcc"); } } diff --git a/main/src/cgeo/geocaching/apps/cache/GeneralApp.java b/main/src/cgeo/geocaching/apps/cache/GeneralApp.java deleted file mode 100644 index cdbedd5..0000000 --- a/main/src/cgeo/geocaching/apps/cache/GeneralApp.java +++ /dev/null @@ -1,12 +0,0 @@ -package cgeo.geocaching.apps.cache; - -import cgeo.geocaching.cgCache; -import cgeo.geocaching.apps.App; - -import android.app.Activity; - -interface GeneralApp extends App { - - public boolean invoke(Activity activity, cgCache cache); - -} diff --git a/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java b/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java deleted file mode 100644 index 57eb957..0000000 --- a/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -package cgeo.geocaching.apps.cache; - -import cgeo.geocaching.cgCache; -import cgeo.geocaching.apps.AbstractAppFactory; -import cgeo.geocaching.utils.Log; - -import org.apache.commons.lang3.ArrayUtils; - -import android.app.Activity; -import android.view.Menu; -import android.view.MenuItem; - -public final class GeneralAppsFactory extends AbstractAppFactory { - private static GeneralApp[] apps = new GeneralApp[] {}; - - private static GeneralApp[] getGeneralApps() { - if (ArrayUtils.isEmpty(apps)) { - apps = new GeneralApp[] { - new CacheBeaconApp(), - new GccApp(), - new WhereYouGoApp() - }; - } - return apps; - } - - public static void addMenuItems(Menu menu, cgCache cache) { - for (GeneralApp app : getGeneralApps()) { - if (app.isInstalled() && app.isEnabled(cache)) { - menu.add(0, app.getId(), 0, app.getName()); - } - } - } - - public static boolean onMenuItemSelected(final MenuItem item, Activity activity, cgCache cache) { - final GeneralApp app = (GeneralApp) getAppFromMenuItem(item, apps); - if (app == null) { - return false; - } - try { - app.invoke(activity, cache); - } catch (Exception e) { - Log.e("GeneralAppsFactory.onMenuItemSelected: " + e.toString()); - } - return true; - } - -} diff --git a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java index 8c16eaf..8c06d7a 100644 --- a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java +++ b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java @@ -4,13 +4,13 @@ import cgeo.geocaching.R; import cgeo.geocaching.cgCache; import cgeo.geocaching.enumerations.CacheType; -class WhereYouGoApp extends AbstractGeneralApp { - WhereYouGoApp() { +public class WhereYouGoApp extends AbstractGeneralApp { + public WhereYouGoApp() { super(getString(R.string.cache_menu_whereyougo), "menion.android.whereyougo"); } @Override public boolean isEnabled(cgCache cache) { - return cache != null && cache.getType() == CacheType.WHERIGO; + return cache.getType() == CacheType.WHERIGO; } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractNavigationApp.java deleted file mode 100644 index 27cb47c..0000000 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractNavigationApp.java +++ /dev/null @@ -1,26 +0,0 @@ -package cgeo.geocaching.apps.cache.navi; - -import cgeo.geocaching.cgWaypoint; -import cgeo.geocaching.apps.AbstractApp; -import cgeo.geocaching.geopoint.Geopoint; - -abstract class AbstractNavigationApp extends AbstractApp implements NavigationApp { - - protected AbstractNavigationApp(String name, String intent, String packageName) { - super(name, intent, packageName); - } - - protected AbstractNavigationApp(String name, String intent) { - super(name, intent); - } - - @Override - public boolean isEnabled(cgWaypoint waypoint) { - return waypoint != null; - } - - @Override - public boolean isEnabled(Geopoint geopoint) { - return geopoint != null; - } -} diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java index ca8c7db..67aa849 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java @@ -1,7 +1,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.apps.AbstractApp; import android.app.Activity; @@ -25,7 +25,7 @@ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNa } @Override - public void navigate(Activity activity, cgWaypoint waypoint) { + public void navigate(Activity activity, Waypoint waypoint) { navigate(activity, waypoint.getCoords()); } @@ -35,7 +35,7 @@ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNa } @Override - public boolean isEnabled(cgWaypoint waypoint) { + public boolean isEnabled(Waypoint waypoint) { return waypoint.getCoords() != null; } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java index f27b53c..e6bf9f4 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java @@ -4,9 +4,9 @@ import cgeo.geocaching.ILogable; import cgeo.geocaching.R; import cgeo.geocaching.StaticMapsActivity; import cgeo.geocaching.StaticMapsProvider; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractApp; @@ -15,7 +15,7 @@ import org.apache.commons.lang3.StringUtils; import android.app.Activity; abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp { - public AbstractStaticMapsApp(String name) { + protected AbstractStaticMapsApp(String name) { super(name, null); } @@ -29,18 +29,19 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat return false; } - protected static boolean hasStaticMap(cgWaypoint waypoint) { - if (waypoint==null) + protected static boolean hasStaticMap(Waypoint waypoint) { + if (waypoint==null) { return false; + } String geocode = waypoint.getGeocode(); int id = waypoint.getId(); - if (StringUtils.isNotEmpty(geocode) && cgeoapplication.getInstance().isOffline(geocode, null)) { + if (StringUtils.isNotEmpty(geocode) && cgData.isOffline(geocode, null)) { return StaticMapsProvider.hasStaticMapForWaypoint(geocode, id); } return false; } - protected static boolean invokeStaticMaps(final Activity activity, final cgCache cache, final cgWaypoint waypoint, final boolean download) { + protected static boolean invokeStaticMaps(final Activity activity, final cgCache cache, final Waypoint waypoint, final boolean download) { final ILogable logable = cache != null && cache.getListId() != 0 ? cache : waypoint; // If the cache is not stored for offline, cache seems to be null and waypoint may be null too if (logable==null || logable.getGeocode()==null ) { diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java index 5275d53..330c338 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java @@ -1,8 +1,8 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.cgeonavigate; import cgeo.geocaching.apps.AbstractApp; import cgeo.geocaching.geopoint.Geopoint; @@ -27,13 +27,13 @@ class CompassApp extends AbstractApp implements CacheNavigationApp, WaypointNavi } @Override - public void navigate(Activity activity, cgWaypoint waypoint) { + public void navigate(Activity activity, Waypoint waypoint) { cgeonavigate.startActivity(activity, waypoint.getPrefix() + "/" + waypoint.getLookup(), waypoint.getName(), waypoint.getCoords(), null, waypoint.getWaypointType().getL10n()); } @Override - public boolean isEnabled(cgWaypoint waypoint) { + public boolean isEnabled(Waypoint waypoint) { return waypoint.getCoords() != null; } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java index faf3c36..846b9bc 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java @@ -2,7 +2,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.Waypoint; import android.app.Activity; @@ -18,7 +18,7 @@ class DownloadStaticMapsApp extends AbstractStaticMapsApp { } @Override - public boolean isEnabled(cgWaypoint waypoint) { + public boolean isEnabled(Waypoint waypoint) { return !hasStaticMap(waypoint); } @@ -28,7 +28,7 @@ class DownloadStaticMapsApp extends AbstractStaticMapsApp { } @Override - public void navigate(Activity activity, cgWaypoint waypoint) { + public void navigate(Activity activity, Waypoint waypoint) { invokeStaticMaps(activity, null, waypoint, true); } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java new file mode 100644 index 0000000..db4fc1c --- /dev/null +++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java @@ -0,0 +1,48 @@ +package cgeo.geocaching.apps.cache.navi; + +import cgeo.geocaching.IGeoData; +import cgeo.geocaching.R; +import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.maps.MapProviderFactory; +import cgeo.geocaching.utils.Log; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; + +public class GoogleMapsDirectionApp extends AbstractPointNavigationApp { + + protected GoogleMapsDirectionApp() { + super(getString(R.string.cache_menu_maps_directions), null); + } + + @Override + public boolean isInstalled() { + return MapProviderFactory.isGoogleMapsInstalled(); + } + + @Override + public void navigate(Activity activity, Geopoint coords) { + try { + IGeoData geo = cgeoapplication.getInstance().currentGeo(); + final Geopoint coordsNow = geo == null ? null : geo.getCoords(); + + if (coordsNow != null) { + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri + .parse("http://maps.google.com/maps?f=d&saddr=" + + coordsNow.getLatitude() + "," + coordsNow.getLongitude() + "&daddr=" + + coords.getLatitude() + "," + coords.getLongitude()))); + } else { + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri + .parse("http://maps.google.com/maps?f=d&daddr=" + + coords.getLatitude() + "," + coords.getLongitude()))); + } + + } catch (Exception e) { + Log.i("GoogleMapsDirection: application not available."); + } + + } + +} diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java index 7258e11..f1616ad 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java @@ -1,10 +1,6 @@ package cgeo.geocaching.apps.cache.navi; -import cgeo.geocaching.IGeoData; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; -import cgeo.geocaching.cgeoapplication; -import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.Log; @@ -12,10 +8,13 @@ import android.app.Activity; import android.content.Intent; import android.net.Uri; -class GoogleNavigationApp extends AbstractPointNavigationApp { +abstract class GoogleNavigationApp extends AbstractPointNavigationApp { - GoogleNavigationApp() { - super(getString(R.string.cache_menu_tbt), null); + private final String mode; + + protected GoogleNavigationApp(final int nameResourceId, final String mode) { + super(getString(nameResourceId), null); + this.mode = mode; } @Override @@ -23,49 +22,27 @@ class GoogleNavigationApp extends AbstractPointNavigationApp { return true; } - private static boolean navigateToCoordinates(Activity activity, final Geopoint coords) { - IGeoData geo = cgeoapplication.getInstance().currentGeo(); - final Geopoint coordsNow = geo == null ? null : geo.getCoords(); - - // Google Navigation - if (Settings.isUseGoogleNavigation()) { - try { - activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri - .parse("google.navigation:ll=" + coords.getLatitude() + "," - + coords.getLongitude()))); - - return true; - } catch (Exception e) { - // nothing - } - } - - // Google Maps Directions + @Override + public void navigate(Activity activity, Geopoint coords) { try { - if (coordsNow != null) { - activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri - .parse("http://maps.google.com/maps?f=d&saddr=" - + coordsNow.getLatitude() + "," + coordsNow.getLongitude() + "&daddr=" - + coords.getLatitude() + "," + coords.getLongitude()))); - } else { - activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri - .parse("http://maps.google.com/maps?f=d&daddr=" - + coords.getLatitude() + "," + coords.getLongitude()))); - } + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri + .parse("google.navigation:ll=" + coords.getLatitude() + "," + + coords.getLongitude() + mode))); - return true; } catch (Exception e) { - // nothing + Log.i("cgBase.runNavigation: No navigation application available."); } + } - Log.i("cgBase.runNavigation: No navigation application available."); - return false; + static class GoogleNavigationWalkingApp extends GoogleNavigationApp { + GoogleNavigationWalkingApp() { + super(R.string.cache_menu_navigation_walk, "&mode=w"); + } } - @Override - public void navigate(Activity activity, Geopoint coords) { - if (!navigateToCoordinates(activity, coords)) { - ActivityMixin.showToast(activity, getString(R.string.err_navigation_no)); + static class GoogleNavigationDrivingApp extends GoogleNavigationApp { + GoogleNavigationDrivingApp() { + super(R.string.cache_menu_navigation_drive, "&mode=d"); } } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java index 8185f40..db842ad 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java @@ -1,8 +1,8 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.apps.AbstractApp; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.Geopoint; @@ -27,12 +27,12 @@ class InternalMap extends AbstractApp implements CacheNavigationApp, WaypointNav } @Override - public void navigate(Activity activity, cgWaypoint waypoint) { + public void navigate(Activity activity, Waypoint waypoint) { CGeoMap.startActivityCoords(activity, waypoint.getCoords(), waypoint.getWaypointType(), waypoint.getName()); } @Override - public boolean isEnabled(cgWaypoint waypoint) { + public boolean isEnabled(Waypoint waypoint) { return waypoint.getCoords() != null; } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java index a20f2ce..b326105 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java @@ -1,7 +1,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.apps.AbstractLocusApp; import android.app.Activity; @@ -11,7 +11,7 @@ import java.util.Collections; class LocusApp extends AbstractLocusApp implements CacheNavigationApp, WaypointNavigationApp { @Override - public boolean isEnabled(cgWaypoint waypoint) { + public boolean isEnabled(Waypoint waypoint) { return waypoint.getCoords() != null; } @@ -21,7 +21,7 @@ class LocusApp extends AbstractLocusApp implements CacheNavigationApp, WaypointN * */ @Override - public void navigate(Activity activity, cgWaypoint waypoint) { + public void navigate(Activity activity, Waypoint waypoint) { showInLocus(Collections.singletonList(waypoint), true, false, activity); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationApp.java deleted file mode 100644 index 52d16cf..0000000 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationApp.java +++ /dev/null @@ -1,18 +0,0 @@ -package cgeo.geocaching.apps.cache.navi; - -import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; -import cgeo.geocaching.apps.App; -import cgeo.geocaching.geopoint.Geopoint; - -import android.app.Activity; - -public interface NavigationApp extends App { - public boolean invoke(final Activity activity, - final cgCache cache, final cgWaypoint waypoint, - final Geopoint coords); - - boolean isEnabled(final cgWaypoint waypoint); - - boolean isEnabled(final Geopoint geopoint); -} diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java index 57a71bb..8effc05 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java @@ -2,12 +2,17 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; import cgeo.geocaching.Settings; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractAppFactory; import cgeo.geocaching.apps.App; +import cgeo.geocaching.apps.cache.CacheBeaconApp; +import cgeo.geocaching.apps.cache.GccApp; +import cgeo.geocaching.apps.cache.WhereYouGoApp; +import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationDrivingApp; +import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationWalkingApp; import cgeo.geocaching.geopoint.Geopoint; import android.app.Activity; @@ -40,7 +45,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** Google Maps */ GOOGLE_MAPS(new GoogleMapsApp(), 6), /** Google Navigation */ - GOOGLE_NAVIGATION(new GoogleNavigationApp(), 7), + GOOGLE_NAVIGATION(new GoogleNavigationDrivingApp(), 7), /** Google Streetview */ GOOGLE_STREETVIEW(new StreetviewApp(), 8), /** The external OruxMaps app */ @@ -48,7 +53,19 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** The external navigon app */ NAVIGON(new NavigonApp(), 10), /** The external Sygic app */ - SYGIC(new SygicNavigationApp(), 11); + SYGIC(new SygicNavigationApp(), 11), + /** + * Google Navigation in walking mode + */ + GOOGLE_NAVIGATION_WALK(new GoogleNavigationWalkingApp(), 12), + /** + * Google Maps Directions + */ + GOOGLE_MAPS_DIRECTIONS(new GoogleMapsDirectionApp(), 13), + + CACHE_BEACON(new CacheBeaconApp(), 14), + GCC(new GccApp(), 15), + WHERE_YOU_GO(new WhereYouGoApp(), 16); NavigationAppsEnum(App app, int id) { this.app = app; @@ -79,7 +96,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { * Default way to handle selection of navigation tool.<br /> * A dialog is created for tool selection and the selected tool is started afterwards. * <p /> - * Delegates to {@link #showNavigationMenu(Activity, cgCache, cgWaypoint, Geopoint, boolean, boolean)} with + * Delegates to {@link #showNavigationMenu(Activity, cgCache, cgeo.geocaching.Waypoint, Geopoint, boolean, boolean)} with * <code>showInternalMap = true</code> and <code>showDefaultNavigation = false</code> * * @param activity @@ -88,7 +105,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { * @param destination */ public static void showNavigationMenu(final Activity activity, - final cgCache cache, final cgWaypoint waypoint, final Geopoint destination) { + final cgCache cache, final Waypoint waypoint, final Geopoint destination) { showNavigationMenu(activity, cache, waypoint, destination, true, false); } @@ -108,14 +125,13 @@ public final class NavigationAppFactory extends AbstractAppFactory { * @param showDefaultNavigation * should be <code>false</code> by default * - * @see #showNavigationMenu(Activity, cgCache, cgWaypoint, Geopoint) + * @see #showNavigationMenu(Activity, cgCache, cgeo.geocaching.Waypoint, Geopoint) */ public static void showNavigationMenu(final Activity activity, - final cgCache cache, final cgWaypoint waypoint, final Geopoint destination, + final cgCache cache, final Waypoint waypoint, final Geopoint destination, final boolean showInternalMap, final boolean showDefaultNavigation) { final AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(R.string.cache_menu_navigate); - builder.setIcon(R.drawable.ic_menu_mapmode); final List<NavigationAppsEnum> items = new ArrayList<NavigationAppFactory.NavigationAppsEnum>(); final int defaultNavigationTool = Settings.getDefaultNavigationTool(); for (NavigationAppsEnum navApp : getInstalledNavigationApps()) { @@ -146,17 +162,15 @@ public final class NavigationAppFactory extends AbstractAppFactory { @Override public void onClick(DialogInterface dialog, int item) { NavigationAppsEnum selectedItem = adapter.getItem(item); + App app = selectedItem.app; if (cache != null) { - CacheNavigationApp cacheApp = (CacheNavigationApp) selectedItem.app; - cacheApp.navigate(activity, cache); + navigateCache(activity, cache, app); } else if (waypoint != null) { - WaypointNavigationApp waypointApp = (WaypointNavigationApp) selectedItem.app; - waypointApp.navigate(activity, waypoint); + navigateWaypoint(activity, waypoint, app); } else { - GeopointNavigationApp geopointApp = (GeopointNavigationApp) selectedItem.app; - geopointApp.navigate(activity, destination); + navigateGeopoint(activity, destination, app); } } }); @@ -205,7 +219,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { * Use {@link #onMenuItemSelected(MenuItem, Activity, cgCache)} on * selection event to start the selected navigation tool. * - * <b>Only use this way if {@link #showNavigationMenu(Activity, cgCache, cgWaypoint, Geopoint, boolean, boolean)} is + * <b>Only use this way if {@link #showNavigationMenu(Activity, cgCache, cgeo.geocaching.Waypoint, Geopoint, boolean, boolean)} is * not suitable for the given usecase.</b> * * @param menu @@ -221,7 +235,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { } } - public static void addMenuItems(final Menu menu, final cgWaypoint waypoint) { + public static void addMenuItems(final Menu menu, final Waypoint waypoint) { for (NavigationAppsEnum navApp : getInstalledNavigationApps()) { if (navApp.app instanceof WaypointNavigationApp) { WaypointNavigationApp waypointApp = (WaypointNavigationApp) navApp.app; @@ -253,13 +267,13 @@ public final class NavigationAppFactory extends AbstractAppFactory { } } - public static boolean onMenuItemSelected(final MenuItem item, Activity activity, cgWaypoint waypoint) { + public static boolean onMenuItemSelected(final MenuItem item, Activity activity, Waypoint waypoint) { final App menuItem = getAppFromMenuItem(item); navigateWaypoint(activity, waypoint, menuItem); return menuItem != null; } - private static void navigateWaypoint(Activity activity, cgWaypoint waypoint, App app) { + private static void navigateWaypoint(Activity activity, Waypoint waypoint, App app) { if (app instanceof WaypointNavigationApp) { WaypointNavigationApp waypointApp = (WaypointNavigationApp) app; waypointApp.navigate(activity, waypoint); @@ -313,7 +327,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { * @param activity * @param waypoint */ - public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, cgWaypoint waypoint) { + public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, Waypoint waypoint) { if (waypoint == null || waypoint.getCoords() == null) { ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_location_unknown)); return; diff --git a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java index a481813..c94c4f4 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java @@ -1,8 +1,8 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.apps.AbstractApp; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter.Format; @@ -21,7 +21,7 @@ class RMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNaviga } @Override - public void navigate(Activity activity, cgWaypoint waypoint) { + public void navigate(Activity activity, Waypoint waypoint) { navigate(activity, waypoint.getCoords(), waypoint.getLookup(), waypoint.getName()); } @@ -34,7 +34,7 @@ class RMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNaviga } @Override - public boolean isEnabled(cgWaypoint waypoint) { + public boolean isEnabled(Waypoint waypoint) { return waypoint.getCoords() != null; } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java index eb01f23..4c3b87e 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java @@ -1,8 +1,8 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; import android.app.Activity; @@ -18,7 +18,7 @@ class StaticMapApp extends AbstractStaticMapsApp { } @Override - public boolean isEnabled(cgWaypoint waypoint) { + public boolean isEnabled(Waypoint waypoint) { return hasStaticMap(waypoint); } @@ -28,7 +28,7 @@ class StaticMapApp extends AbstractStaticMapsApp { } @Override - public void navigate(Activity activity, cgWaypoint waypoint) { + public void navigate(Activity activity, Waypoint waypoint) { invokeStaticMaps(activity, null, waypoint, false); } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java index 7d3a706..c26ec3e 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java @@ -1,6 +1,6 @@ package cgeo.geocaching.apps.cache.navi; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.Waypoint; import android.app.Activity; @@ -9,7 +9,7 @@ import android.app.Activity; * */ public interface WaypointNavigationApp { - void navigate(final Activity activity, final cgWaypoint waypoint); + void navigate(final Activity activity, final Waypoint waypoint); - boolean isEnabled(final cgWaypoint waypoint); + boolean isEnabled(final Waypoint waypoint); } diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java index fbfb9fc..b01c0ac 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java +++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java @@ -64,7 +64,7 @@ public final class CacheListAppFactory extends AbstractAppFactory { activity.invalidateOptionsMenuCompatible(); return result; } catch (Exception e) { - Log.e("CacheListAppFactory.onMenuItemSelected: " + e.toString()); + Log.e("CacheListAppFactory.onMenuItemSelected", e); } } return false; diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/cgCache.java index 7035d65..24bd66b 100644 --- a/main/src/cgeo/geocaching/cgCache.java +++ b/main/src/cgeo/geocaching/cgCache.java @@ -11,6 +11,7 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheAttribute; +import cgeo.geocaching.enumerations.CacheRealm; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; @@ -27,6 +28,7 @@ import cgeo.geocaching.utils.LazyInitializedList; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -38,7 +40,6 @@ import android.net.Uri; import android.os.Handler; import android.os.Message; import android.text.Html; -import android.text.Spannable; import java.util.ArrayList; import java.util.Calendar; @@ -48,7 +49,6 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -66,7 +66,6 @@ public class cgCache implements ICache, IWaypoint { private String guid = ""; private CacheType cacheType = CacheType.UNKNOWN; private String name = ""; - private Spannable nameSp = null; private String ownerDisplayName = ""; private String ownerUserId = ""; private Date hidden = null; @@ -99,23 +98,23 @@ public class cgCache implements ICache, IWaypoint { private LazyInitializedList<String> attributes = new LazyInitializedList<String>() { @Override protected List<String> loadFromDatabase() { - return cgeoapplication.getInstance().loadAttributes(geocode); + return cgData.loadAttributes(geocode); } }; - private LazyInitializedList<cgWaypoint> waypoints = new LazyInitializedList<cgWaypoint>() { + private LazyInitializedList<Waypoint> waypoints = new LazyInitializedList<Waypoint>() { @Override - protected List<cgWaypoint> loadFromDatabase() { - return cgeoapplication.getInstance().loadWaypoints(geocode); + protected List<Waypoint> loadFromDatabase() { + return cgData.loadWaypoints(geocode); } }; - private List<cgImage> spoilers = null; + private List<Image> spoilers = null; private LazyInitializedList<LogEntry> logs = new LazyInitializedList<LogEntry>() { @Override protected List<LogEntry> loadFromDatabase() { - return cgeoapplication.getInstance().loadLogs(geocode); + return cgData.loadLogs(geocode); } }; - private List<cgTrackable> inventory = null; + private List<Trackable> inventory = null; private Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>(); private boolean logOffline = false; private boolean userModifiedCoords = false; @@ -147,7 +146,7 @@ public class cgCache implements ICache, IWaypoint { public cgCache(GPXParser gpxParser) { setReliableLatLon(true); setAttributes(Collections.<String> emptyList()); - setWaypoints(Collections.<cgWaypoint> emptyList(), false); + setWaypoints(Collections.<Waypoint> emptyList(), false); setLogs(Collections.<LogEntry> emptyList()); } @@ -227,9 +226,6 @@ public class cgCache implements ICache, IWaypoint { if (StringUtils.isBlank(name)) { name = other.name; } - if (StringUtils.isBlank(nameSp)) { - nameSp = other.nameSp; - } if (StringUtils.isBlank(ownerDisplayName)) { ownerDisplayName = other.ownerDisplayName; } @@ -278,6 +274,8 @@ public class cgCache implements ICache, IWaypoint { if (StringUtils.isBlank(description)) { description = other.description; } + // FIXME: this makes no sense to favor this over the other. 0 should not be a special case here as it is + // in the range of acceptable values. This is probably the case at other places (rating, votes, etc.) too. if (favoritePoints == 0) { favoritePoints = other.favoritePoints; } @@ -294,12 +292,12 @@ public class cgCache implements ICache, IWaypoint { attributes.set(other.attributes); } if (waypoints.isEmpty()) { - waypoints.set(other.waypoints); + this.setWaypoints(other.waypoints.asList(), false); } else { - ArrayList<cgWaypoint> newPoints = new ArrayList<cgWaypoint>(waypoints.asList()); - cgWaypoint.mergeWayPoints(newPoints, other.getWaypoints(), false); - waypoints.set(newPoints); + ArrayList<Waypoint> newPoints = new ArrayList<Waypoint>(waypoints.asList()); + Waypoint.mergeWayPoints(newPoints, other.waypoints.asList(), false); + this.setWaypoints(newPoints, false); } if (spoilers == null) { spoilers = other.spoilers; @@ -315,12 +313,21 @@ public class cgCache implements ICache, IWaypoint { if (logs.isEmpty()) { // keep last known logs if none logs.set(other.logs); } - if (logCounts.size() == 0) { + if (logCounts.isEmpty()) { logCounts = other.logCounts; } - if (!userModifiedCoords) { - userModifiedCoords = other.userModifiedCoords; + + // if cache has ORIGINAL type waypoint ... it is considered that it has modified coordinates, otherwise not + userModifiedCoords = false; + if (waypoints != null) { + for (Waypoint wpt : waypoints) { + if (wpt.getWaypointType() == WaypointType.ORIGINAL) { + userModifiedCoords = true; + break; + } + } } + if (!reliableLatLon) { reliableLatLon = other.reliableLatLon; } @@ -328,19 +335,14 @@ public class cgCache implements ICache, IWaypoint { zoomlevel = other.zoomlevel; } - boolean isEqual = isEqualTo(other); - - if (!isEqual) { - notifyChange(); - } - - return isEqual; + return isEqualTo(other); } /** * Compare two caches quickly. For map and list fields only the references are compared ! * - * @param other the other cache to compare this one to + * @param other + * the other cache to compare this one to * @return true if both caches have the same content */ private boolean isEqualTo(final cgCache other) { @@ -376,7 +378,6 @@ public class cgCache implements ICache, IWaypoint { (direction != null ? direction.equals(other.direction) : null == other.direction) && (distance != null ? distance.equals(other.distance) : null == other.distance) && (elevation != null ? elevation.equals(other.elevation) : null == other.elevation) && - nameSp == other.nameSp && rating == other.rating && votes == other.votes && myVote == other.myVote && @@ -441,8 +442,7 @@ public class cgCache implements ICache, IWaypoint { } Intent logVisitIntent = new Intent((Activity) fromActivity, VisitCacheActivity.class); logVisitIntent.putExtra(VisitCacheActivity.EXTRAS_ID, cacheId); - logVisitIntent.putExtra(VisitCacheActivity.EXTRAS_GEOCODE, geocode.toUpperCase()); - logVisitIntent.putExtra(VisitCacheActivity.EXTRAS_FOUND, found); + logVisitIntent.putExtra(VisitCacheActivity.EXTRAS_GEOCODE, geocode); ((Activity) fromActivity).startActivity(logVisitIntent); } @@ -457,13 +457,12 @@ public class cgCache implements ICache, IWaypoint { if (logType == LogType.UNKNOWN) { return; } - cgeoapplication app = (cgeoapplication) fromActivity.getApplication(); - final boolean status = app.saveLogOffline(geocode, date.getTime(), logType, log); + final boolean status = cgData.saveLogOffline(geocode, date.getTime(), logType, log); Resources res = fromActivity.getResources(); if (status) { ActivityMixin.showToast(fromActivity, res.getString(R.string.info_log_saved)); - app.saveVisitDate(geocode); + cgData.saveVisitDate(geocode); logOffline = true; notifyChange(); @@ -538,6 +537,14 @@ public class cgCache implements ICache, IWaypoint { return getConnector().supportsLogging(); } + public boolean supportsOwnCoordinates() { + return getConnector().supportsOwnCoordinates(); + } + + public CacheRealm getCacheRealm() { + return getConnector().getCacheRealm(); + } + @Override public float getDifficulty() { return difficulty; @@ -603,7 +610,7 @@ public class cgCache implements ICache, IWaypoint { @Override public String getDescription() { if (description == null) { - description = StringUtils.defaultString(cgeoapplication.getInstance().getCacheDescription(geocode)); + description = StringUtils.defaultString(cgData.getCacheDescription(geocode)); } return description; } @@ -661,7 +668,7 @@ public class cgCache implements ICache, IWaypoint { } StringBuilder subject = new StringBuilder("Geocache "); - subject.append(geocode.toUpperCase()); + subject.append(geocode); if (StringUtils.isNotBlank(name)) { subject.append(" - ").append(name); } @@ -700,7 +707,6 @@ public class cgCache implements ICache, IWaypoint { this.favorite = favourite; } - @Override public boolean isWatchlist() { return onWatchlist; @@ -717,19 +723,19 @@ public class cgCache implements ICache, IWaypoint { } @Override - public List<cgTrackable> getInventory() { + public List<Trackable> getInventory() { return inventory; } - public void addSpoiler(final cgImage spoiler) { + public void addSpoiler(final Image spoiler) { if (spoilers == null) { - spoilers = new ArrayList<cgImage>(); + spoilers = new ArrayList<Image>(); } spoilers.add(spoiler); } @Override - public List<cgImage> getSpoilers() { + public List<Image> getSpoilers() { if (spoilers == null) { return Collections.emptyList(); } @@ -749,7 +755,7 @@ public class cgCache implements ICache, IWaypoint { @Override public String getNameForSorting() { if (null == nameForSorting) { - final Matcher matcher = NUMBER_PATTERN.matcher(name); + final MatcherWrapper matcher = new MatcherWrapper(NUMBER_PATTERN, name); if (matcher.find()) { nameForSorting = name.replace(matcher.group(), StringUtils.leftPad(matcher.group(), 6, '0')); } @@ -809,14 +815,6 @@ public class cgCache implements ICache, IWaypoint { this.detailed = detailed; } - public Spannable getNameSp() { - return nameSp; - } - - public void setNameSp(Spannable nameSp) { - this.nameSp = nameSp; - } - public void setHidden(final Date hidden) { if (hidden == null) { this.hidden = null; @@ -935,7 +933,7 @@ public class cgCache implements ICache, IWaypoint { * * @return always non <code>null</code> */ - public List<cgWaypoint> getWaypoints() { + public List<Waypoint> getWaypoints() { return waypoints.asList(); } @@ -947,19 +945,18 @@ public class cgCache implements ICache, IWaypoint { * called while loading or building a cache * @return <code>true</code> if waypoints successfully added to waypoint database */ - public boolean setWaypoints(List<cgWaypoint> waypoints, boolean saveToDatabase) { + public boolean setWaypoints(List<Waypoint> waypoints, boolean saveToDatabase) { this.waypoints.set(waypoints); finalDefined = false; if (waypoints != null) { - for (cgWaypoint waypoint : waypoints) { + for (Waypoint waypoint : waypoints) { waypoint.setGeocode(geocode); if (waypoint.isFinalWithCoords()) { finalDefined = true; } } } - - return saveToDatabase && cgeoapplication.getInstance().saveWaypoints(this); + return saveToDatabase && cgData.saveWaypoints(this); } /** @@ -1015,7 +1012,7 @@ public class cgCache implements ICache, IWaypoint { } public void setGeocode(String geocode) { - this.geocode = geocode; + this.geocode = StringUtils.upperCase(geocode); } public void setCacheId(String cacheId) { @@ -1087,11 +1084,11 @@ public class cgCache implements ICache, IWaypoint { this.attributes.set(attributes); } - public void setSpoilers(List<cgImage> spoilers) { + public void setSpoilers(List<Image> spoilers) { this.spoilers = spoilers; } - public void setInventory(List<cgTrackable> inventory) { + public void setInventory(List<Trackable> inventory) { this.inventory = inventory; } @@ -1149,7 +1146,7 @@ public class cgCache implements ICache, IWaypoint { * called while loading or building a cache * @return <code>true</code> if waypoint successfully added to waypoint database */ - public boolean addOrChangeWaypoint(final cgWaypoint waypoint, boolean saveToDatabase) { + public boolean addOrChangeWaypoint(final Waypoint waypoint, boolean saveToDatabase) { waypoint.setGeocode(geocode); if (waypoint.getId() <= 0) { // this is a new waypoint @@ -1166,8 +1163,7 @@ public class cgCache implements ICache, IWaypoint { // when waypoint was edited, finalDefined may have changed resetFinalDefined(); } - - return saveToDatabase && cgeoapplication.getInstance().saveWaypoint(waypoint.getId(), geocode, waypoint); + return saveToDatabase && cgData.saveWaypoint(waypoint.getId(), geocode, waypoint); } public boolean hasWaypoints() { @@ -1188,7 +1184,7 @@ public class cgCache implements ICache, IWaypoint { */ private void resetFinalDefined() { finalDefined = false; - for (cgWaypoint wp : waypoints) { + for (Waypoint wp : waypoints) { if (wp.isFinalWithCoords()) { finalDefined = true; break; @@ -1201,43 +1197,47 @@ public class cgCache implements ICache, IWaypoint { } public void setUserModifiedCoords(boolean coordsChanged) { - this.userModifiedCoords = coordsChanged; + userModifiedCoords = coordsChanged; } /** * Duplicate a waypoint. * - * @param index the waypoint to duplicate + * @param original + * the waypoint to duplicate * @return <code>true</code> if the waypoint was duplicated, <code>false</code> otherwise (invalid index) */ - public boolean duplicateWaypoint(final int index) { - final cgWaypoint original = getWaypoint(index); + public boolean duplicateWaypoint(final Waypoint original) { if (original == null) { return false; } - final cgWaypoint copy = new cgWaypoint(original); + final int index = getWaypointIndex(original); + final Waypoint copy = new Waypoint(original); copy.setUserDefined(); copy.setName(cgeoapplication.getInstance().getString(R.string.waypoint_copy_of) + " " + copy.getName()); waypoints.add(index + 1, copy); - return cgeoapplication.getInstance().saveWaypoint(-1, geocode, copy); + return cgData.saveWaypoint(-1, geocode, copy); } /** * delete a user defined waypoint * - * @param index - * of the waypoint in cache's waypoint list + * @param waypoint + * to be removed from cache * @return <code>true</code>, if the waypoint was deleted */ - public boolean deleteWaypoint(final int index) { - final cgWaypoint waypoint = getWaypoint(index); + public boolean deleteWaypoint(final Waypoint waypoint) { if (waypoint == null) { return false; } + if (waypoint.getId() <= 0) { + return false; + } if (waypoint.isUserDefined()) { + final int index = getWaypointIndex(waypoint); waypoints.remove(index); - cgeoapplication.getInstance().deleteWaypoint(waypoint.getId()); - cgeoapplication.getInstance().removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); + cgData.deleteWaypoint(waypoint.getId()); + cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); // Check status if Final is defined if (waypoint.isFinalWithCoords()) { resetFinalDefined(); @@ -1248,19 +1248,17 @@ public class cgCache implements ICache, IWaypoint { } /** - * delete a user defined waypoint + * deletes any waypoint * * @param waypoint - * to be removed from cache - * @return <code>true</code>, if the waypoint was deleted */ - public boolean deleteWaypoint(final cgWaypoint waypoint) { - if (waypoint.getId() <= 0) { - return false; - } + public void deleteWaypointForce(Waypoint waypoint) { final int index = getWaypointIndex(waypoint); - return index >= 0 && deleteWaypoint(index); + waypoints.remove(index); + cgData.deleteWaypoint(waypoint.getId()); + cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); + resetFinalDefined(); } /** @@ -1270,7 +1268,7 @@ public class cgCache implements ICache, IWaypoint { * to find index for * @return index in <code>waypoints</code> if found, -1 otherwise */ - private int getWaypointIndex(final cgWaypoint waypoint) { + private int getWaypointIndex(final Waypoint waypoint) { final int id = waypoint.getId(); for (int index = 0; index < waypoints.size(); index++) { if (waypoints.get(index).getId() == id) { @@ -1283,21 +1281,23 @@ public class cgCache implements ICache, IWaypoint { /** * Retrieve a given waypoint. * - * @param index the index of the waypoint + * @param index + * the index of the waypoint * @return waypoint or <code>null</code> if index is out of range */ - public cgWaypoint getWaypoint(final int index) { + public Waypoint getWaypoint(final int index) { return index >= 0 && index < waypoints.size() ? waypoints.get(index) : null; } /** * Lookup a waypoint by its id. * - * @param id the id of the waypoint to look for + * @param id + * the id of the waypoint to look for * @return waypoint or <code>null</code> */ - public cgWaypoint getWaypointById(final int id) { - for (final cgWaypoint waypoint : waypoints) { + public Waypoint getWaypointById(final int id) { + for (final Waypoint waypoint : waypoints) { if (waypoint.getId() == id) { return waypoint; } @@ -1313,14 +1313,14 @@ public class cgCache implements ICache, IWaypoint { final Pattern coordPattern = Pattern.compile("\\b[nNsS]{1}\\s*\\d"); // begin of coordinates int count = 1; String note = getPersonalNote(); - Matcher matcher = coordPattern.matcher(note); + MatcherWrapper matcher = new MatcherWrapper(coordPattern, note); while (matcher.find()) { try { final Geopoint point = new Geopoint(note.substring(matcher.start())); // coords must have non zero latitude and longitude and at least one part shall have fractional degrees if (point.getLatitudeE6() != 0 && point.getLongitudeE6() != 0 && ((point.getLatitudeE6() % 1000) != 0 || (point.getLongitudeE6() % 1000) != 0)) { final String name = cgeoapplication.getInstance().getString(R.string.cache_personal_note) + " " + count; - final cgWaypoint waypoint = new cgWaypoint(name, WaypointType.WAYPOINT, false); + final Waypoint waypoint = new Waypoint(name, WaypointType.WAYPOINT, false); waypoint.setCoords(point); addOrChangeWaypoint(waypoint, false); count++; @@ -1330,10 +1330,10 @@ public class cgCache implements ICache, IWaypoint { } note = note.substring(matcher.start() + 1); - matcher = coordPattern.matcher(note); + matcher = new MatcherWrapper(coordPattern, note); } } catch (Exception e) { - Log.e("cgCache.parseWaypointsFromNote: " + e.toString()); + Log.e("cgCache.parseWaypointsFromNote", e); } } @@ -1391,8 +1391,8 @@ public class cgCache implements ICache, IWaypoint { public void drop(Handler handler) { try { - cgeoapplication.getInstance().markDropped(Collections.singletonList(this)); - cgeoapplication.getInstance().removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE)); + cgData.markDropped(Collections.singletonList(this)); + cgData.removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE)); handler.sendMessage(Message.obtain()); } catch (Exception e) { @@ -1402,48 +1402,48 @@ public class cgCache implements ICache, IWaypoint { public void checkFields() { if (StringUtils.isBlank(getGeocode())) { - Log.e("geo code not parsed correctly"); + Log.w("geo code not parsed correctly for " + geocode); } if (StringUtils.isBlank(getName())) { - Log.e("name not parsed correctly"); + Log.w("name not parsed correctly for " + geocode); } if (StringUtils.isBlank(getGuid())) { - Log.e("guid not parsed correctly"); + Log.w("guid not parsed correctly for " + geocode); } if (getTerrain() == 0.0) { - Log.e("terrain not parsed correctly"); + Log.w("terrain not parsed correctly for " + geocode); } if (getDifficulty() == 0.0) { - Log.e("difficulty not parsed correctly"); + Log.w("difficulty not parsed correctly for " + geocode); } if (StringUtils.isBlank(getOwnerDisplayName())) { - Log.e("owner display name not parsed correctly"); + Log.w("owner display name not parsed correctly for " + geocode); } if (StringUtils.isBlank(getOwnerUserId())) { - Log.e("owner user id real not parsed correctly"); + Log.w("owner user id real not parsed correctly for " + geocode); } if (getHiddenDate() == null) { - Log.e("hidden not parsed correctly"); + Log.w("hidden not parsed correctly for " + geocode); } if (getFavoritePoints() < 0) { - Log.e("favoriteCount not parsed correctly"); + Log.w("favoriteCount not parsed correctly for " + geocode); } if (getSize() == null) { - Log.e("size not parsed correctly"); + Log.w("size not parsed correctly for " + geocode); } if (getType() == null || getType() == CacheType.UNKNOWN) { - Log.e("type not parsed correctly"); + Log.w("type not parsed correctly for " + geocode); } if (getCoords() == null) { - Log.e("coordinates not parsed correctly"); + Log.w("coordinates not parsed correctly for " + geocode); } if (StringUtils.isBlank(getLocation())) { - Log.e("location not parsed correctly"); + Log.w("location not parsed correctly for " + geocode); } } public void refresh(int newListId, CancellableHandler handler) { - cgeoapplication.getInstance().removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); + cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); storeCache(null, geocode, newListId, true, handler); } @@ -1491,7 +1491,7 @@ public class cgCache implements ICache, IWaypoint { // store spoilers if (CollectionUtils.isNotEmpty(cache.getSpoilers())) { - for (cgImage oneSpoiler : cache.getSpoilers()) { + for (Image oneSpoiler : cache.getSpoilers()) { imgGetter.getDrawable(oneSpoiler.getUrl()); } } @@ -1504,7 +1504,7 @@ public class cgCache implements ICache, IWaypoint { if (Settings.isStoreLogImages()) { for (LogEntry log : cache.getLogs()) { if (log.hasLogImages()) { - for (cgImage oneLogImg : log.getLogImages()) { + for (Image oneLogImg : log.getLogImages()) { imgGetter.getDrawable(oneLogImg.getUrl()); } } @@ -1516,7 +1516,7 @@ public class cgCache implements ICache, IWaypoint { } cache.setListId(listId); - cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); if (CancellableHandler.isCancelled(handler)) { return; @@ -1538,10 +1538,9 @@ public class cgCache implements ICache, IWaypoint { return null; } - final cgeoapplication app = cgeoapplication.getInstance(); - if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (app.isOffline(geocode, guid) || app.isThere(geocode, guid, true, true))) { + if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (cgData.isOffline(geocode, guid) || cgData.isThere(geocode, guid, true, true))) { final SearchResult search = new SearchResult(); - final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : app.getGeocode(guid); + final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : cgData.getGeocodeForGuid(guid); search.addGeocode(realGeocode); return search; } @@ -1573,7 +1572,7 @@ public class cgCache implements ICache, IWaypoint { } // 12:34 final Pattern time = Pattern.compile("\\b(\\d{1,2})\\:(\\d\\d)\\b"); - final Matcher matcher = time.matcher(getDescription()); + final MatcherWrapper matcher = new MatcherWrapper(time, getDescription()); while (matcher.find()) { try { final int hours = Integer.valueOf(matcher.group(1)); @@ -1589,7 +1588,7 @@ public class cgCache implements ICache, IWaypoint { final String hourLocalized = cgeoapplication.getInstance().getString(R.string.cache_time_full_hours); if (StringUtils.isNotBlank(hourLocalized)) { final Pattern fullHours = Pattern.compile("\\b(\\d{1,2})\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE); - final Matcher matcherHours = fullHours.matcher(getDescription()); + final MatcherWrapper matcherHours = new MatcherWrapper(fullHours, getDescription()); if (matcherHours.find()) { try { final int hours = Integer.valueOf(matcherHours.group(1)); @@ -1613,8 +1612,7 @@ public class cgCache implements ICache, IWaypoint { * @return */ public boolean hasAttribute(CacheAttribute attribute, boolean yes) { - // lazy loading of attributes - cgCache fullCache = cgeoapplication.getInstance().loadCache(getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES)); + cgCache fullCache = cgData.loadCache(getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES)); if (fullCache == null) { fullCache = this; } @@ -1625,12 +1623,32 @@ public class cgCache implements ICache, IWaypoint { return StaticMapsProvider.hasStaticMap(this); } - public List<cgImage> getImages() { - List<cgImage> result = new ArrayList<cgImage>(); + public List<Image> getImages() { + List<Image> result = new ArrayList<Image>(); result.addAll(getSpoilers()); for (LogEntry log : getLogs()) { result.addAll(log.getLogImages()); } return result; } + + public void setDetailedUpdatedNow() { + final long now = System.currentTimeMillis(); + setUpdated(now); + setDetailedUpdate(now); + setDetailed(true); + } + + /** + * Gets whether the user has logged the specific log type for this cache. Only checks the currently stored logs of + * the cache, so the result might be wrong. + */ + public boolean hasOwnLog(LogType logType) { + for (LogEntry logEntry : getLogs()) { + if (logEntry.type == logType && logEntry.isOwn()) { + return true; + } + } + return false; + } } diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java index 94eb3fd..3ec1d14 100644 --- a/main/src/cgeo/geocaching/cgData.java +++ b/main/src/cgeo/geocaching/cgData.java @@ -23,7 +23,6 @@ import android.content.ContextWrapper; import android.content.res.Resources; import android.database.Cursor; import android.database.DatabaseUtils; -import android.database.DatabaseUtils.InsertHelper; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteDoneException; @@ -48,6 +47,10 @@ import java.util.regex.Pattern; public class cgData { + private cgData() { + // utility class + } + public enum StorageLocation { HEAP, CACHE, @@ -72,9 +75,9 @@ public class cgData { * holds the column indexes of the cache table to avoid lookups */ private static int[] cacheColumnIndex; - private CacheCache cacheCache = new CacheCache(); - private SQLiteDatabase database = null; - private static final int dbVersion = 64; + private static CacheCache cacheCache = new CacheCache(); + private static SQLiteDatabase database = null; + private static final int dbVersion = 65; public static final int customListIdOffset = 10; private static final String dbName = "data"; private static final String dbTableCaches = "cg_caches"; @@ -151,9 +154,6 @@ public class cgData { + "updated long not null, " // date of save + "attribute text " + "); "; - private final static int ATTRIBUTES_GEOCODE = 2; - private final static int ATTRIBUTES_UPDATED = 3; - private final static int ATTRIBUTES_ATTRIBUTE = 4; private static final String dbCreateWaypoints = "" + "create table " + dbTableWaypoints + " (" @@ -191,14 +191,6 @@ public class cgData { + "found integer not null default 0, " + "friend integer " + "); "; - private final static int LOGS_GEOCODE = 2; - private final static int LOGS_UPDATED = 3; - private final static int LOGS_TYPE = 4; - private final static int LOGS_AUTHOR = 5; - private final static int LOGS_LOG = 6; - private final static int LOGS_DATE = 7; - private final static int LOGS_FOUND = 8; - private final static int LOGS_FRIEND = 9; private static final String dbCreateLogCount = "" + "create table " + dbTableLogCount + " (" @@ -246,10 +238,10 @@ public class cgData { + "longitude double " + "); "; - private HashMap<String, SQLiteStatement> statements = new HashMap<String, SQLiteStatement>(); private static boolean newlyCreatedDatabase = false; + private static boolean databaseCleaned = false; - public synchronized void init() { + public synchronized static void init() { if (database != null) { return; } @@ -262,35 +254,28 @@ public class cgData { } } - public void closeDb() { + public static void closeDb() { if (database == null) { return; } cacheCache.removeAllFromCache(); - clearPreparedStatements(); + PreparedStatements.clearPreparedStatements(); database.close(); database = null; } - private void clearPreparedStatements() { - for (SQLiteStatement statement : statements.values()) { - statement.close(); - } - statements.clear(); - } - - private static File backupFile() { + private static File getBackupFile() { return new File(LocalStorage.getStorage(), "cgeo.sqlite"); } - public String backupDatabase() { + public static String backupDatabase() { if (!LocalStorage.isExternalStorageAvailable()) { Log.w("Database wasn't backed up: no external memory"); return null; } - final File target = backupFile(); + final File target = getBackupFile(); closeDb(); final boolean backupDone = LocalStorage.copy(databasePath(), target); init(); @@ -304,7 +289,7 @@ public class cgData { return target.getPath(); } - public boolean moveDatabase() { + public static boolean moveDatabase() { if (!LocalStorage.isExternalStorageAvailable()) { Log.w("Database was not moved: external memory not available"); return false; @@ -340,18 +325,18 @@ public class cgData { return databasePath(Settings.isDbOnSDCard()); } - public static File isRestoreFile() { - final File fileSourceFile = backupFile(); + public static File getRestoreFile() { + final File fileSourceFile = getBackupFile(); return fileSourceFile.exists() ? fileSourceFile : null; } - public boolean restoreDatabase() { + public static boolean restoreDatabase() { if (!LocalStorage.isExternalStorageAvailable()) { Log.w("Database wasn't restored: no external memory"); return false; } - final File sourceFile = backupFile(); + final File sourceFile = getBackupFile(); closeDb(); final boolean restoreDone = LocalStorage.copy(sourceFile, databasePath()); init(); @@ -475,7 +460,7 @@ public class cgData { try { db.execSQL(dbCreateLogImages); } catch (Exception e) { - Log.e("Failed to upgrade to ver. 54: " + e.toString()); + Log.e("Failed to upgrade to ver. 54", e); } } @@ -484,7 +469,7 @@ public class cgData { try { db.execSQL("alter table " + dbTableCaches + " add column personal_note text"); } catch (Exception e) { - Log.e("Failed to upgrade to ver. 55: " + e.toString()); + Log.e("Failed to upgrade to ver. 55", e); } } @@ -496,7 +481,7 @@ public class cgData { "lower(attribute) where attribute like \"%_yes\" " + "or attribute like \"%_no\""); } catch (Exception e) { - Log.e("Failed to upgrade to ver. 56: " + e.toString()); + Log.e("Failed to upgrade to ver. 56", e); } } @@ -511,7 +496,7 @@ public class cgData { db.execSQL("drop index in_f"); createIndices(db); } catch (Exception e) { - Log.e("Failed to upgrade to ver. 57: " + e.toString()); + Log.e("Failed to upgrade to ver. 57", e); } } @@ -629,7 +614,7 @@ public class cgData { db.execSQL("alter table " + dbTableLogs + " add column friend integer"); db.execSQL("alter table " + dbTableCaches + " add column coordsChanged integer default 0"); } catch (Exception e) { - Log.e("Failed to upgrade to ver. 61: " + e.toString()); + Log.e("Failed to upgrade to ver. 61", e); } } @@ -640,7 +625,7 @@ public class cgData { db.execSQL("alter table " + dbTableWaypoints + " add column own integer default 0"); db.execSQL("update " + dbTableWaypoints + " set own = 1 where type = 'own'"); } catch (Exception e) { - Log.e("Failed to upgrade to ver. 62: " + e.toString()); + Log.e("Failed to upgrade to ver. 62", e); } } @@ -648,7 +633,7 @@ public class cgData { try { removeDoubleUnderscoreMapFiles(); } catch (Exception e) { - Log.e("Failed to upgrade to ver. 63: " + e.toString()); + Log.e("Failed to upgrade to ver. 63", e); } } @@ -663,6 +648,15 @@ public class cgData { Log.e("Failed to upgrade to ver. 64", e); } } + + if (oldVersion < 65) { + try { + // Set all waypoints where name is Original coordinates to type ORIGINAL + db.execSQL("update " + dbTableWaypoints + " set type='original', own=0 where name='Original Coordinates'"); + } catch (Exception e) { + Log.e("Failed to upgrade to ver. 65:", e); + } + } } db.setTransactionSuccessful(); @@ -705,13 +699,15 @@ public class cgData { final FilenameFilter filter = new FilenameFilter() { @Override public boolean accept(File dir, String filename) { - return (filename.startsWith("map_") && filename.contains("__")); + return filename.startsWith("map_") && filename.contains("__"); } }; - for (File dir : geocodeDirs) { - File[] wrongFiles = dir.listFiles(filter); - for (File wrongFile : wrongFiles) { - wrongFile.delete(); + for (final File dir : geocodeDirs) { + final File[] wrongFiles = dir.listFiles(filter); + if (wrongFiles != null) { + for (final File wrongFile : wrongFiles) { + wrongFile.delete(); + } } } } @@ -776,15 +772,12 @@ public class cgData { db.execSQL("drop table if exists " + dbTableTrackables); } - public String[] allDetailedThere() { + public static String[] getRecentGeocodesForSearch() { init(); - Cursor cursor = null; - List<String> list = new ArrayList<String>(); - try { long timestamp = System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED; - cursor = database.query( + final Cursor cursor = database.query( dbTableCaches, new String[]{"geocode"}, "(detailed = 1 and detailedupdate > ?) or reason > 0", @@ -794,43 +787,23 @@ public class cgData { "detailedupdate desc", "100"); - if (cursor != null) { - int index; - - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - index = cursor.getColumnIndex("geocode"); - - do { - list.add(cursor.getString(index)); - } while (cursor.moveToNext()); - } else { - cursor.close(); - return null; - } - } - } catch (Exception e) { - Log.e("cgData.allDetailedThere: " + e.toString()); - } - - if (cursor != null) { - cursor.close(); + return getFirstColumn(cursor); + } catch (final Exception e) { + Log.e("cgData.allDetailedThere", e); + return new String[0]; } - - return list.toArray(new String[list.size()]); } - public boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) { + public static boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) { init(); - Cursor cursor = null; - - int cnt = 0; long dataUpdated = 0; long dataDetailedUpdate = 0; int dataDetailed = 0; try { + Cursor cursor; + if (StringUtils.isNotBlank(geocode)) { cursor = database.query( dbTableCaches, @@ -855,55 +828,38 @@ public class cgData { return false; } - if (cursor != null) { - int index; - cnt = cursor.getCount(); - - if (cnt > 0) { - cursor.moveToFirst(); - - index = cursor.getColumnIndex("updated"); - dataUpdated = cursor.getLong(index); - index = cursor.getColumnIndex("detailedupdate"); - dataDetailedUpdate = cursor.getLong(index); - index = cursor.getColumnIndex("detailed"); - dataDetailed = cursor.getInt(index); - } + if (cursor.moveToFirst()) { + dataDetailed = cursor.getInt(0); + dataDetailedUpdate = cursor.getLong(1); + dataUpdated = cursor.getLong(2); } - } catch (Exception e) { - Log.e("cgData.isThere: " + e.toString()); - } - if (cursor != null) { cursor.close(); + } catch (final Exception e) { + Log.e("cgData.isThere", e); } - if (cnt > 0) { - if (detailed && dataDetailed == 0) { - // we want details, but these are not stored - return false; - } - - if (checkTime && detailed && dataDetailedUpdate < (System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED)) { - // we want to check time for detailed cache, but data are older than 3 hours - return false; - } + if (detailed && dataDetailed == 0) { + // we want details, but these are not stored + return false; + } - if (checkTime && !detailed && dataUpdated < (System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED)) { - // we want to check time for short cache, but data are older than 3 hours - return false; - } + if (checkTime && detailed && dataDetailedUpdate < (System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED)) { + // we want to check time for detailed cache, but data are older than 3 hours + return false; + } - // we have some cache - return true; + if (checkTime && !detailed && dataUpdated < (System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED)) { + // we want to check time for short cache, but data are older than 3 hours + return false; } - // we have no such cache stored in cache - return false; + // we have some cache + return true; } /** is cache stored in one of the lists (not only temporary) */ - public boolean isOffline(String geocode, String guid) { + public static boolean isOffline(String geocode, String guid) { if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) { return false; } @@ -913,11 +869,11 @@ public class cgData { final SQLiteStatement listId; final String value; if (StringUtils.isNotBlank(geocode)) { - listId = getStatementListIdFromGeocode(); + listId = PreparedStatements.getListIdOfGeocode(); value = geocode; } else { - listId = getStatementListIdFromGuid(); + listId = PreparedStatements.getListIdOfGuid(); value = guid; } synchronized (listId) { @@ -933,14 +889,14 @@ public class cgData { return false; } - public String getGeocodeForGuid(String guid) { + public static String getGeocodeForGuid(String guid) { if (StringUtils.isBlank(guid)) { return null; } init(); try { - final SQLiteStatement description = getStatementGeocode(); + final SQLiteStatement description = PreparedStatements.getGeocodeOfGuid(); synchronized (description) { description.bindString(1, guid); return description.simpleQueryForString(); @@ -954,14 +910,14 @@ public class cgData { return null; } - public String getCacheidForGeocode(String geocode) { + public static String getCacheidForGeocode(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); try { - final SQLiteStatement description = getStatementCacheId(); + final SQLiteStatement description = PreparedStatements.getCacheIdOfGeocode(); synchronized (description) { description.bindString(1, geocode); return description.simpleQueryForString(); @@ -984,7 +940,7 @@ public class cgData { * * @return true = cache saved successfully to the CacheCache/DB */ - public boolean saveCache(cgCache cache, EnumSet<LoadFlags.SaveFlag> saveFlags) { + public static boolean saveCache(cgCache cache, EnumSet<LoadFlags.SaveFlag> saveFlags) { if (cache == null) { throw new IllegalArgumentException("cache must not be null"); } @@ -1064,12 +1020,12 @@ public class cgData { values.put("coordsChanged", cache.hasUserModifiedCoords() ? 1 : 0); values.put("finalDefined", cache.hasFinalDefined() ? 1 : 0); - boolean result = false; init(); //try to update record else insert fresh.. database.beginTransaction(); + boolean result = false; try { saveAttributesWithoutTransaction(cache); saveOriginalWaypointsWithoutTransaction(cache); @@ -1087,7 +1043,7 @@ public class cgData { database.setTransactionSuccessful(); result = true; } catch (Exception e) { - // nothing + Log.e("SaveCache", e); } finally { database.endTransaction(); } @@ -1095,25 +1051,21 @@ public class cgData { return result; } - private void saveAttributesWithoutTransaction(final cgCache cache) { + private static void saveAttributesWithoutTransaction(final cgCache cache) { String geocode = cache.getGeocode(); database.delete(dbTableAttributes, "geocode = ?", new String[]{geocode}); - if (cache.getAttributes().isNotEmpty()) { - - InsertHelper helper = new InsertHelper(database, dbTableAttributes); - long timeStamp = System.currentTimeMillis(); - - for (String attribute : cache.getAttributes()) { - helper.prepareForInsert(); - - helper.bind(ATTRIBUTES_GEOCODE, geocode); - helper.bind(ATTRIBUTES_UPDATED, timeStamp); - helper.bind(ATTRIBUTES_ATTRIBUTE, attribute); + if (cache.getAttributes().isEmpty()) { + return; + } + SQLiteStatement statement = PreparedStatements.getInsertAttribute(); + final long timestamp = System.currentTimeMillis(); + for (String attribute : cache.getAttributes()) { + statement.bindString(1, geocode); + statement.bindLong(2, timestamp); + statement.bindString(3, attribute); - helper.execute(); - } - helper.close(); + statement.executeInsert(); } } @@ -1123,16 +1075,14 @@ public class cgData { * @param destination * a destination to save */ - public void saveSearchedDestination(final Destination destination) { + public static void saveSearchedDestination(final Destination destination) { init(); database.beginTransaction(); try { - ContentValues values = new ContentValues(); - values.put("date", destination.getDate()); - putCoords(values, destination.getCoords()); - database.insert(dbTableSearchDestionationHistory, null, values); + SQLiteStatement insertDestination = PreparedStatements.getInsertSearchDestination(destination); + insertDestination.executeInsert(); database.setTransactionSuccessful(); } catch (Exception e) { Log.e("Updating searchedDestinations db failed", e); @@ -1141,11 +1091,11 @@ public class cgData { } } - public boolean saveWaypoints(final cgCache cache) { - boolean result = false; + public static boolean saveWaypoints(final cgCache cache) { init(); database.beginTransaction(); + boolean result = false; try { saveOriginalWaypointsWithoutTransaction(cache); database.setTransactionSuccessful(); @@ -1158,15 +1108,15 @@ public class cgData { return result; } - private void saveOriginalWaypointsWithoutTransaction(final cgCache cache) { + private static void saveOriginalWaypointsWithoutTransaction(final cgCache cache) { String geocode = cache.getGeocode(); database.delete(dbTableWaypoints, "geocode = ? and type <> ? and own = 0", new String[]{geocode, "own"}); - List<cgWaypoint> waypoints = cache.getWaypoints(); + List<Waypoint> waypoints = cache.getWaypoints(); if (CollectionUtils.isNotEmpty(waypoints)) { ContentValues values = new ContentValues(); long timeStamp = System.currentTimeMillis(); - for (cgWaypoint oneWaypoint : waypoints) { + for (Waypoint oneWaypoint : waypoints) { if (oneWaypoint.isUserDefined()) { continue; } @@ -1221,15 +1171,15 @@ public class cgData { return new Geopoint(cursor.getDouble(indexLat), cursor.getDouble(indexLon)); } - public boolean saveWaypoint(int id, String geocode, cgWaypoint waypoint) { + private static boolean saveWaypointInternal(int id, String geocode, Waypoint waypoint) { if ((StringUtils.isBlank(geocode) && id <= 0) || waypoint == null) { return false; } init(); - boolean ok = false; database.beginTransaction(); + boolean ok = false; try { ContentValues values = new ContentValues(); values.put("geocode", geocode); @@ -1259,7 +1209,7 @@ public class cgData { return ok; } - public boolean deleteWaypoint(int id) { + public static boolean deleteWaypoint(int id) { if (id == 0) { return false; } @@ -1269,28 +1219,32 @@ public class cgData { return database.delete(dbTableWaypoints, "_id = " + id, null) > 0; } - private void saveSpoilersWithoutTransaction(final cgCache cache) { + private static void saveSpoilersWithoutTransaction(final cgCache cache) { String geocode = cache.getGeocode(); database.delete(dbTableSpoilers, "geocode = ?", new String[]{geocode}); - List<cgImage> spoilers = cache.getSpoilers(); + List<Image> spoilers = cache.getSpoilers(); if (CollectionUtils.isNotEmpty(spoilers)) { - ContentValues values = new ContentValues(); - long timeStamp = System.currentTimeMillis(); - for (cgImage spoiler : spoilers) { - values.clear(); - values.put("geocode", geocode); - values.put("updated", timeStamp); - values.put("url", spoiler.getUrl()); - values.put("title", spoiler.getTitle()); - values.put("description", spoiler.getDescription()); - - database.insert(dbTableSpoilers, null, values); + SQLiteStatement insertSpoiler = PreparedStatements.getInsertSpoiler(); + final long timestamp = System.currentTimeMillis(); + for (Image spoiler : spoilers) { + insertSpoiler.bindString(1, geocode); + insertSpoiler.bindLong(2, timestamp); + insertSpoiler.bindString(3, spoiler.getUrl()); + insertSpoiler.bindString(4, spoiler.getTitle()); + final String description = spoiler.getDescription(); + if (description != null) { + insertSpoiler.bindString(5, description); + } + else { + insertSpoiler.bindNull(5); + } + insertSpoiler.executeInsert(); } } } - private void saveLogsWithoutTransaction(final String geocode, final Iterable<LogEntry> logs) { + private static void saveLogsWithoutTransaction(final String geocode, final Iterable<LogEntry> logs) { // TODO delete logimages referring these logs database.delete(dbTableLogs, "geocode = ?", new String[]{geocode}); @@ -1298,59 +1252,51 @@ public class cgData { return; } - InsertHelper helper = new InsertHelper(database, dbTableLogs); - long timeStamp = System.currentTimeMillis(); + SQLiteStatement insertLog = PreparedStatements.getInsertLog(); + final long timestamp = System.currentTimeMillis(); for (LogEntry log : logs) { - helper.prepareForInsert(); - - helper.bind(LOGS_GEOCODE, geocode); - helper.bind(LOGS_UPDATED, timeStamp); - helper.bind(LOGS_TYPE, log.type.id); - helper.bind(LOGS_AUTHOR, log.author); - helper.bind(LOGS_LOG, log.log); - helper.bind(LOGS_DATE, log.date); - helper.bind(LOGS_FOUND, log.found); - helper.bind(LOGS_FRIEND, log.friend); - - long log_id = helper.execute(); - + insertLog.bindString(1, geocode); + insertLog.bindLong(2, timestamp); + insertLog.bindLong(3, log.type.id); + insertLog.bindString(4, log.author); + insertLog.bindString(5, log.log); + insertLog.bindLong(6, log.date); + insertLog.bindLong(7, log.found); + insertLog.bindLong(8, log.friend ? 1 : 0); + long logId = insertLog.executeInsert(); if (log.hasLogImages()) { - ContentValues values = new ContentValues(); - for (cgImage img : log.getLogImages()) { - values.clear(); - values.put("log_id", log_id); - values.put("title", img.getTitle()); - values.put("url", img.getUrl()); - database.insert(dbTableLogImages, null, values); + SQLiteStatement insertImage = PreparedStatements.getInsertLogImage(); + for (Image img : log.getLogImages()) { + insertImage.bindLong(1, logId); + insertImage.bindString(2, img.getTitle()); + insertImage.bindString(3, img.getUrl()); + insertImage.executeInsert(); } } } - helper.close(); } - private void saveLogCountsWithoutTransaction(final cgCache cache) { + private static void saveLogCountsWithoutTransaction(final cgCache cache) { String geocode = cache.getGeocode(); database.delete(dbTableLogCount, "geocode = ?", new String[]{geocode}); Map<LogType, Integer> logCounts = cache.getLogCounts(); if (MapUtils.isNotEmpty(logCounts)) { - ContentValues values = new ContentValues(); - Set<Entry<LogType, Integer>> logCountsItems = logCounts.entrySet(); - long timeStamp = System.currentTimeMillis(); + SQLiteStatement insertLogCounts = PreparedStatements.getInsertLogCounts(); + final long timestamp = System.currentTimeMillis(); for (Entry<LogType, Integer> pair : logCountsItems) { - values.clear(); - values.put("geocode", geocode); - values.put("updated", timeStamp); - values.put("type", pair.getKey().id); - values.put("count", pair.getValue()); + insertLogCounts.bindString(1, geocode); + insertLogCounts.bindLong(2, timestamp); + insertLogCounts.bindLong(3, pair.getKey().id); + insertLogCounts.bindLong(4, pair.getValue()); - database.insert(dbTableLogCount, null, values); + insertLogCounts.executeInsert(); } } } - public boolean saveTrackable(final cgTrackable trackable) { + public static boolean saveTrackable(final Trackable trackable) { init(); database.beginTransaction(); @@ -1364,7 +1310,7 @@ public class cgData { return true; } - private void saveInventoryWithoutTransaction(final String geocode, final List<cgTrackable> trackables) { + private static void saveInventoryWithoutTransaction(final String geocode, final List<Trackable> trackables) { if (geocode != null) { database.delete(dbTableTrackables, "geocode = ?", new String[]{geocode}); } @@ -1372,7 +1318,7 @@ public class cgData { if (CollectionUtils.isNotEmpty(trackables)) { ContentValues values = new ContentValues(); long timeStamp = System.currentTimeMillis(); - for (cgTrackable trackable : trackables) { + for (Trackable trackable : trackables) { final String tbCode = trackable.getGeocode(); if (StringUtils.isNotBlank(tbCode)) { database.delete(dbTableTrackables, "tbcode = ?", new String[] { tbCode }); @@ -1401,7 +1347,7 @@ public class cgData { } } - public Viewport getBounds(final Set<String> geocodes) { + public static Viewport getBounds(final Set<String> geocodes) { if (CollectionUtils.isEmpty(geocodes)) { return null; } @@ -1417,7 +1363,7 @@ public class cgData { * The Geocode GCXXXX * @return the loaded cache (if found). Can be null */ - public cgCache loadCache(final String geocode, final EnumSet<LoadFlag> loadFlags) { + public static cgCache loadCache(final String geocode, final EnumSet<LoadFlag> loadFlags) { if (StringUtils.isBlank(geocode)) { throw new IllegalArgumentException("geocode must not be empty"); } @@ -1432,7 +1378,7 @@ public class cgData { * @param geocodes * @return Set of loaded caches. Never null. */ - public Set<cgCache> loadCaches(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) { + public static Set<cgCache> loadCaches(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) { if (CollectionUtils.isEmpty(geocodes)) { return new HashSet<cgCache>(); } @@ -1476,7 +1422,7 @@ public class cgData { } if (remaining.size() >= 1) { - Log.e("cgData.loadCaches(" + remaining.toString() + ") failed"); + Log.i("cgData.loadCaches(" + remaining.toString() + ") failed"); } return result; } @@ -1488,7 +1434,7 @@ public class cgData { * @param loadFlags * @return Set of loaded caches. Never null. */ - private Set<cgCache> loadCachesFromGeocodes(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) { + private static Set<cgCache> loadCachesFromGeocodes(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) { if (CollectionUtils.isEmpty(geocodes)) { return Collections.emptySet(); } @@ -1516,14 +1462,10 @@ public class cgData { Cursor cursor = database.rawQuery(query.toString(), null); try { - if (!cursor.moveToFirst()) { - return Collections.emptySet(); - } - final Set<cgCache> caches = new HashSet<cgCache>(); int logIndex = -1; - do { - //Extracted Method = LOADDBMINIMAL + + while (cursor.moveToNext()) { cgCache cache = cgData.createCacheFromDatabaseContent(cursor); if (loadFlags.contains(LoadFlag.LOAD_ATTRIBUTES)) { @@ -1531,14 +1473,14 @@ public class cgData { } if (loadFlags.contains(LoadFlag.LOAD_WAYPOINTS)) { - final List<cgWaypoint> waypoints = loadWaypoints(cache.getGeocode()); + final List<Waypoint> waypoints = loadWaypoints(cache.getGeocode()); if (CollectionUtils.isNotEmpty(waypoints)) { cache.setWaypoints(waypoints, false); } } if (loadFlags.contains(LoadFlag.LOAD_SPOILERS)) { - final List<cgImage> spoilers = loadSpoilers(cache.getGeocode()); + final List<Image> spoilers = loadSpoilers(cache.getGeocode()); cache.setSpoilers(spoilers); } @@ -1552,10 +1494,10 @@ public class cgData { } if (loadFlags.contains(LoadFlag.LOAD_INVENTORY)) { - final List<cgTrackable> inventory = loadInventory(cache.getGeocode()); + final List<Trackable> inventory = loadInventory(cache.getGeocode()); if (CollectionUtils.isNotEmpty(inventory)) { if (cache.getInventory() == null) { - cache.setInventory(new ArrayList<cgTrackable>()); + cache.setInventory(new ArrayList<Trackable>()); } else { cache.getInventory().clear(); } @@ -1573,7 +1515,7 @@ public class cgData { cacheCache.putCacheInCache(cache); caches.add(cache); - } while (cursor.moveToNext()); + } return caches; } finally { cursor.close(); @@ -1600,7 +1542,6 @@ public class cgData { * @return Cache from DB */ private static cgCache createCacheFromDatabaseContent(Cursor cursor) { - int index; cgCache cache = new cgCache(); if (cacheColumnIndex == null) { @@ -1669,7 +1610,7 @@ public class cgData { cache.setHint(cursor.getString(cacheColumnIndex[14])); cache.setSize(CacheSize.getById(cursor.getString(cacheColumnIndex[15]))); cache.setDifficulty(cursor.getFloat(cacheColumnIndex[16])); - index = cacheColumnIndex[17]; + int index = cacheColumnIndex[17]; if (cursor.isNull(index)) { cache.setDirection(null); } else { @@ -1714,16 +1655,16 @@ public class cgData { return cache; } - public List<String> loadAttributes(String geocode) { + public static List<String> loadAttributes(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - ArrayList<String> attributes = new ArrayList<String>(); + final ArrayList<String> attributes = new ArrayList<String>(); - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableAttributes, new String[]{"attribute"}, "geocode = ?", @@ -1733,32 +1674,23 @@ public class cgData { null, "100"); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); - int index = cursor.getColumnIndex("attribute"); - - do { - attributes.add(cursor.getString(index)); - } while (cursor.moveToNext()); + while (cursor.moveToNext()) { + attributes.add(cursor.getString(0)); } - if (cursor != null) { - cursor.close(); - } + cursor.close(); return attributes; } - public cgWaypoint loadWaypoint(int id) { + public static Waypoint loadWaypoint(int id) { if (id == 0) { return null; } init(); - cgWaypoint waypoint = null; - - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableWaypoints, WAYPOINT_COLUMNS, "_id = ?", @@ -1770,29 +1702,23 @@ public class cgData { Log.d("cgData.loadWaypoint(" + id + ")"); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); + final Waypoint waypoint = cursor.moveToFirst() ? createWaypointFromDatabaseContent(cursor) : null; - waypoint = createWaypointFromDatabaseContent(cursor); - } - - if (cursor != null) { - cursor.close(); - } + cursor.close(); return waypoint; } - public List<cgWaypoint> loadWaypoints(final String geocode) { + public static List<Waypoint> loadWaypoints(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - List<cgWaypoint> waypoints = new ArrayList<cgWaypoint>(); + final List<Waypoint> waypoints = new ArrayList<Waypoint>(); - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableWaypoints, WAYPOINT_COLUMNS, "geocode = ?", @@ -1802,29 +1728,20 @@ public class cgData { "_id", "100"); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); - - do { - - cgWaypoint waypoint = createWaypointFromDatabaseContent(cursor); - - waypoints.add(waypoint); - } while (cursor.moveToNext()); + while (cursor.moveToNext()) { + waypoints.add(createWaypointFromDatabaseContent(cursor)); } - if (cursor != null) { - cursor.close(); - } + cursor.close(); return waypoints; } - private static cgWaypoint createWaypointFromDatabaseContent(Cursor cursor) { - String name = cursor.getString(cursor.getColumnIndex("name")); - WaypointType type = WaypointType.findById(cursor.getString(cursor.getColumnIndex("type"))); - boolean own = cursor.getInt(cursor.getColumnIndex("own")) != 0; - cgWaypoint waypoint = new cgWaypoint(name, type, own); + private static Waypoint createWaypointFromDatabaseContent(final Cursor cursor) { + final String name = cursor.getString(cursor.getColumnIndex("name")); + final WaypointType type = WaypointType.findById(cursor.getString(cursor.getColumnIndex("type"))); + final boolean own = cursor.getInt(cursor.getColumnIndex("own")) != 0; + final Waypoint waypoint = new Waypoint(name, type, own); waypoint.setId(cursor.getInt(cursor.getColumnIndex("_id"))); waypoint.setGeocode(cursor.getString(cursor.getColumnIndex("geocode"))); @@ -1837,16 +1754,16 @@ public class cgData { return waypoint; } - private List<cgImage> loadSpoilers(String geocode) { + private static List<Image> loadSpoilers(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - List<cgImage> spoilers = new ArrayList<cgImage>(); + final List<Image> spoilers = new ArrayList<Image>(); - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableSpoilers, new String[]{"url", "title", "description"}, "geocode = ?", @@ -1856,22 +1773,11 @@ public class cgData { null, "100"); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); - int indexUrl = cursor.getColumnIndex("url"); - int indexTitle = cursor.getColumnIndex("title"); - int indexDescription = cursor.getColumnIndex("description"); - - do { - cgImage spoiler = new cgImage(cursor.getString(indexUrl), cursor.getString(indexTitle), cursor.getString(indexDescription)); - - spoilers.add(spoiler); - } while (cursor.moveToNext()); + while (cursor.moveToNext()) { + spoilers.add(new Image(cursor.getString(0), cursor.getString(1), cursor.getString(2))); } - if (cursor != null) { - cursor.close(); - } + cursor.close(); return spoilers; } @@ -1882,10 +1788,10 @@ public class cgData { * * @return A list of previously entered destinations or an empty list. */ - public List<Destination> loadHistoryOfSearchedLocations() { + public static List<Destination> loadHistoryOfSearchedLocations() { init(); - Cursor cursor = database.query(dbTableSearchDestionationHistory, + final Cursor cursor = database.query(dbTableSearchDestionationHistory, new String[]{"_id", "date", "latitude", "longitude"}, null, null, @@ -1896,36 +1802,25 @@ public class cgData { final List<Destination> destinations = new LinkedList<Destination>(); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); - int indexId = cursor.getColumnIndex("_id"); - int indexDate = cursor.getColumnIndex("date"); - int indexLatitude = cursor.getColumnIndex("latitude"); - int indexLongitude = cursor.getColumnIndex("longitude"); + while (cursor.moveToNext()) { + final Destination dest = new Destination(cursor.getLong(0), cursor.getLong(1), getCoords(cursor, 2, 3)); - do { - final Destination dest = new Destination(cursor.getLong(indexId), cursor.getLong(indexDate), getCoords(cursor, indexLatitude, indexLongitude)); - - // If coordinates are non-existent or invalid, do not consider - // this point. - if (dest.getCoords() != null) { - destinations.add(dest); - } - } while (cursor.moveToNext()); + // If coordinates are non-existent or invalid, do not consider this point. + if (dest.getCoords() != null) { + destinations.add(dest); + } } - if (cursor != null) { - cursor.close(); - } + cursor.close(); return destinations; } - public boolean clearSearchedDestinations() { - boolean success = true; + public static boolean clearSearchedDestinations() { init(); database.beginTransaction(); + boolean success = true; try { database.delete(dbTableSearchDestionationHistory, null, null); database.setTransactionSuccessful(); @@ -1939,7 +1834,7 @@ public class cgData { return success; } - public List<LogEntry> loadLogs(String geocode) { + public static List<LogEntry> loadLogs(String geocode) { List<LogEntry> logs = new ArrayList<LogEntry>(); if (StringUtils.isBlank(geocode)) { @@ -1948,60 +1843,45 @@ public class cgData { init(); - Cursor cursor = database.rawQuery( - "SELECT cg_logs._id as cg_logs_id, type, author, log, date, found, friend, " + dbTableLogImages + "._id as cg_logImages_id, log_id, title, url FROM " - + dbTableLogs + " LEFT OUTER JOIN " + dbTableLogImages + final Cursor cursor = database.rawQuery( + /* 0 1 2 3 4 5 6 7 8 9 10 */ + "SELECT cg_logs._id as cg_logs_id, type, author, log, date, found, friend, " + dbTableLogImages + "._id as cg_logImages_id, log_id, title, url" + + " FROM " + dbTableLogs + " LEFT OUTER JOIN " + dbTableLogImages + " ON ( cg_logs._id = log_id ) WHERE geocode = ? ORDER BY date desc, cg_logs._id asc", new String[]{geocode}); - if (cursor != null && cursor.getCount() > 0) { - LogEntry log = null; - int indexLogsId = cursor.getColumnIndex("cg_logs_id"); - int indexType = cursor.getColumnIndex("type"); - int indexAuthor = cursor.getColumnIndex("author"); - int indexLog = cursor.getColumnIndex("log"); - int indexDate = cursor.getColumnIndex("date"); - int indexFound = cursor.getColumnIndex("found"); - int indexFriend = cursor.getColumnIndex("friend"); - int indexLogImagesId = cursor.getColumnIndex("cg_logImages_id"); - int indexTitle = cursor.getColumnIndex("title"); - int indexUrl = cursor.getColumnIndex("url"); - while (cursor.moveToNext() && logs.size() < 100) { - if (log == null || log.id != cursor.getInt(indexLogsId)) { - log = new LogEntry( - cursor.getString(indexAuthor), - cursor.getLong(indexDate), - LogType.getById(cursor.getInt(indexType)), - cursor.getString(indexLog)); - log.id = cursor.getInt(indexLogsId); - log.found = cursor.getInt(indexFound); - log.friend = cursor.getInt(indexFriend) == 1; - logs.add(log); - } - if (!cursor.isNull(indexLogImagesId)) { - String title = cursor.getString(indexTitle); - String url = cursor.getString(indexUrl); - log.addLogImage(new cgImage(url, title)); - } + LogEntry log = null; + while (cursor.moveToNext() && logs.size() < 100) { + if (log == null || log.id != cursor.getInt(0)) { + log = new LogEntry( + cursor.getString(2), + cursor.getLong(4), + LogType.getById(cursor.getInt(1)), + cursor.getString(3)); + log.id = cursor.getInt(0); + log.found = cursor.getInt(5); + log.friend = cursor.getInt(6) == 1; + logs.add(log); + } + if (!cursor.isNull(7)) { + log.addLogImage(new Image(cursor.getString(10), cursor.getString(9))); } } - if (cursor != null) { - cursor.close(); - } + cursor.close(); return logs; } - public Map<LogType, Integer> loadLogCounts(String geocode) { + public static Map<LogType, Integer> loadLogCounts(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>(); + final Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>(); - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableLogCount, new String[]{"type", "count"}, "geocode = ?", @@ -2011,36 +1891,25 @@ public class cgData { null, "100"); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); - int indexType = cursor.getColumnIndex("type"); - int indexCount = cursor.getColumnIndex("count"); - - do { - LogType type = LogType.getById(cursor.getInt(indexType)); - Integer count = cursor.getInt(indexCount); - - logCounts.put(type, count); - } while (cursor.moveToNext()); + while (cursor.moveToNext()) { + logCounts.put(LogType.getById(cursor.getInt(0)), cursor.getInt(1)); } - if (cursor != null) { - cursor.close(); - } + cursor.close(); return logCounts; } - private List<cgTrackable> loadInventory(String geocode) { + private static List<Trackable> loadInventory(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - List<cgTrackable> trackables = new ArrayList<cgTrackable>(); + final List<Trackable> trackables = new ArrayList<Trackable>(); - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableTrackables, new String[]{"_id", "updated", "tbcode", "guid", "title", "owner", "released", "goal", "description"}, "geocode = ?", @@ -2050,33 +1919,23 @@ public class cgData { "title COLLATE NOCASE ASC", "100"); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); - - do { - cgTrackable trackable = createTrackableFromDatabaseContent(cursor); - - trackables.add(trackable); - } while (cursor.moveToNext()); + while (cursor.moveToNext()) { + trackables.add(createTrackableFromDatabaseContent(cursor)); } - if (cursor != null) { - cursor.close(); - } + cursor.close(); return trackables; } - public cgTrackable loadTrackable(String geocode) { + public static Trackable loadTrackable(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - cgTrackable trackable = new cgTrackable(); - - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableTrackables, new String[]{"updated", "tbcode", "guid", "title", "owner", "released", "goal", "description"}, "tbcode = ?", @@ -2086,30 +1945,25 @@ public class cgData { null, "1"); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); - trackable = createTrackableFromDatabaseContent(cursor); - } + final Trackable trackable = cursor.moveToFirst() ? createTrackableFromDatabaseContent(cursor) : null; - if (cursor != null) { - cursor.close(); - } + cursor.close(); return trackable; } - private cgTrackable createTrackableFromDatabaseContent(Cursor cursor) { - cgTrackable trackable = new cgTrackable(); + private static Trackable createTrackableFromDatabaseContent(final Cursor cursor) { + final Trackable trackable = new Trackable(); trackable.setGeocode(cursor.getString(cursor.getColumnIndex("tbcode"))); trackable.setGuid(cursor.getString(cursor.getColumnIndex("guid"))); trackable.setName(cursor.getString(cursor.getColumnIndex("title"))); trackable.setOwner(cursor.getString(cursor.getColumnIndex("owner"))); - String released = cursor.getString(cursor.getColumnIndex("released")); + final String released = cursor.getString(cursor.getColumnIndex("released")); if (released != null) { try { long releaseMilliSeconds = Long.parseLong(released); trackable.setReleased(new Date(releaseMilliSeconds)); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { Log.e("createTrackableFromDatabaseContent", e); } } @@ -2120,103 +1974,99 @@ public class cgData { } /** - * Number of caches stored. The number is shown on the starting activity of c:geo + * Number of caches stored for a given type and/or list * - * @param detailedOnly * @param cacheType * @param list * @return */ - public int getAllStoredCachesCount(final boolean detailedOnly, final CacheType cacheType, final int list) { + public static int getAllStoredCachesCount(final CacheType cacheType, final int list) { if (cacheType == null) { throw new IllegalArgumentException("cacheType must not be null"); } - init(); - - String listSql; - String listSqlW; - if (list == 0) { - listSql = " where reason >= 1"; - listSqlW = " and reason >= 1"; - } else if (list >= 1) { - listSql = " where reason = " + list; - listSqlW = " and reason = " + list; - } else { - return 0; + if (list <= 0) { + throw new IllegalArgumentException("list must be > 0"); } + init(); - int count = 0; try { - String sql; - if (!detailedOnly) { - if (cacheType == CacheType.ALL) { - sql = "select count(_id) from " + dbTableCaches + listSql; - } else { - sql = "select count(_id) from " + dbTableCaches + " where type = " + DatabaseUtils.sqlEscapeString(cacheType.id) + listSqlW; - } + StringBuilder sql = new StringBuilder("select count(_id) from " + dbTableCaches + " where detailed = 1"); + String typeKey; + int reasonIndex; + if (cacheType != CacheType.ALL) { + sql.append(" and type = ?"); + typeKey = cacheType.id; + reasonIndex = 2; + } + else { + typeKey = "all_types"; + reasonIndex = 1; + } + String listKey; + if (list == StoredList.ALL_LIST_ID) { + sql.append(" and reason > 0"); + listKey = "all_list"; } else { - if (cacheType == CacheType.ALL) { - sql = "select count(_id) from " + dbTableCaches + " where detailed = 1" + listSqlW; - } else { - sql = "select count(_id) from " + dbTableCaches + " where detailed = 1 and type = " + DatabaseUtils.sqlEscapeString(cacheType.id) + listSqlW; - } + sql.append(" and reason = ?"); + listKey = "list"; + } + + String key = "CountCaches_" + typeKey + "_" + listKey; + + SQLiteStatement compiledStmnt = PreparedStatements.getStatement(key, sql.toString()); + if (cacheType != CacheType.ALL) { + compiledStmnt.bindString(1, cacheType.id); } - SQLiteStatement compiledStmnt = database.compileStatement(sql); - count = (int) compiledStmnt.simpleQueryForLong(); - compiledStmnt.close(); + if (list != StoredList.ALL_LIST_ID) { + compiledStmnt.bindLong(reasonIndex, list); + } + return (int) compiledStmnt.simpleQueryForLong(); } catch (Exception e) { - Log.e("cgData.loadAllStoredCachesCount: " + e.toString()); + Log.e("cgData.loadAllStoredCachesCount", e); } - return count; + return 0; } - public int getAllHistoricCachesCount() { + public static int getAllHistoryCachesCount() { init(); - int count = 0; - try { - SQLiteStatement sqlCount = database.compileStatement("select count(_id) from " + dbTableCaches + " where visiteddate > 0"); - count = (int) sqlCount.simpleQueryForLong(); - sqlCount.close(); + return (int) PreparedStatements.getCountHistoryCaches().simpleQueryForLong(); } catch (Exception e) { - Log.e("cgData.getAllHistoricCachesCount: " + e.toString()); + Log.e("cgData.getAllHistoricCachesCount", e); } - return count; + return 0; } /** * Return a batch of stored geocodes. * - * @param detailedOnly * @param coords * the current coordinates to sort by distance, or null to sort by geocode * @param cacheType * @param listId - * @return + * @return a non-null set of geocodes */ - public Set<String> loadBatchOfStoredGeocodes(final boolean detailedOnly, final Geopoint coords, final CacheType cacheType, final int listId) { + private static Set<String> loadBatchOfStoredGeocodes(final Geopoint coords, final CacheType cacheType, final int listId) { if (cacheType == null) { throw new IllegalArgumentException("cacheType must not be null"); } init(); - Set<String> geocodes = new HashSet<String>(); + final Set<String> geocodes = new HashSet<String>(); - StringBuilder specifySql = new StringBuilder(); + final StringBuilder selection = new StringBuilder(); - specifySql.append("reason "); - specifySql.append(listId != StoredList.ALL_LIST_ID ? "=" + Math.max(listId, 1) : ">= " + StoredList.STANDARD_LIST_ID); - - if (detailedOnly) { - specifySql.append(" and detailed = 1 "); - } + selection.append("reason "); + selection.append(listId != StoredList.ALL_LIST_ID ? "=" + Math.max(listId, 1) : ">= " + StoredList.STANDARD_LIST_ID); + selection.append(" and detailed = 1 "); + String[] selectionArgs = null; if (cacheType != CacheType.ALL) { - specifySql.append(" and type = "); - specifySql.append(DatabaseUtils.sqlEscapeString(cacheType.id)); + selection.append(" and type = ?"); + selectionArgs = new String[] { String.valueOf(cacheType.id) }; } try { @@ -2226,8 +2076,8 @@ public class cgData { dbTableCaches, new String[]{"geocode", "(abs(latitude-" + String.format((Locale) null, "%.6f", coords.getLatitude()) + ") + abs(longitude-" + String.format((Locale) null, "%.6f", coords.getLongitude()) + ")) as dif"}, - specifySql.toString(), - null, + selection.toString(), + selectionArgs, null, null, "dif", @@ -2236,86 +2086,69 @@ public class cgData { cursor = database.query( dbTableCaches, new String[]{"geocode"}, - specifySql.toString(), - null, + selection.toString(), + selectionArgs, null, null, "geocode"); } - if (cursor.moveToFirst()) { - final int index = cursor.getColumnIndex("geocode"); - - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); + while (cursor.moveToNext()) { + geocodes.add(cursor.getString(0)); } cursor.close(); - - } catch (Exception e) { - Log.e("cgData.loadBatchOfStoredGeocodes: " + e.toString()); + } catch (final Exception e) { + Log.e("cgData.loadBatchOfStoredGeocodes", e); } return geocodes; } - public Set<String> loadBatchOfHistoricGeocodes(final boolean detailedOnly, final CacheType cacheType) { + private static Set<String> loadBatchOfHistoricGeocodes(final boolean detailedOnly, final CacheType cacheType) { init(); - Set<String> geocodes = new HashSet<String>(); + final Set<String> geocodes = new HashSet<String>(); - StringBuilder specifySql = new StringBuilder(); - specifySql.append("visiteddate > 0"); + final StringBuilder selection = new StringBuilder("visiteddate > 0"); if (detailedOnly) { - specifySql.append(" and detailed = 1"); + selection.append(" and detailed = 1"); } + String[] selectionArgs = null; if (cacheType != CacheType.ALL) { - specifySql.append(" and type = "); - specifySql.append(DatabaseUtils.sqlEscapeString(cacheType.id)); + selection.append(" and type = ?"); + selectionArgs = new String[] { String.valueOf(cacheType.id) }; } try { - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableCaches, new String[]{"geocode"}, - specifySql.toString(), - null, + selection.toString(), + selectionArgs, null, null, "visiteddate", null); - - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - int index = cursor.getColumnIndex("geocode"); - - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); - } else { - cursor.close(); - return null; - } - - cursor.close(); + while (cursor.moveToNext()) { + geocodes.add(cursor.getString(0)); } + cursor.close(); } catch (Exception e) { - Log.e("cgData.loadBatchOfHistoricGeocodes: " + e.toString()); + Log.e("cgData.loadBatchOfHistoricGeocodes", e); } return geocodes; } /** Retrieve all stored caches from DB */ - public Set<String> loadCachedInViewport(final Viewport viewport, final CacheType cacheType) { + public static SearchResult loadCachedInViewport(final Viewport viewport, final CacheType cacheType) { return loadInViewport(false, viewport, cacheType); } /** Retrieve stored caches from DB with listId >= 1 */ - public Set<String> loadStoredInViewport(final Viewport viewport, final CacheType cacheType) { + public static SearchResult loadStoredInViewport(final Viewport viewport, final CacheType cacheType) { return loadInViewport(true, viewport, cacheType); } @@ -2331,7 +2164,7 @@ public class cgData { * @param cacheType * @return Set with geocodes */ - private Set<String> loadInViewport(final boolean stored, final Viewport viewport, final CacheType cacheType) { + private static SearchResult loadInViewport(final boolean stored, final Viewport viewport, final CacheType cacheType) { init(); final Set<String> geocodes = new HashSet<String>(); @@ -2342,47 +2175,45 @@ public class cgData { } // viewport limitation - final StringBuilder where = new StringBuilder(buildCoordinateWhere(dbTableCaches, viewport)); + final StringBuilder selection = new StringBuilder(buildCoordinateWhere(dbTableCaches, viewport)); // cacheType limitation + String[] selectionArgs = null; if (cacheType != CacheType.ALL) { - where.append(" and type = "); - where.append(DatabaseUtils.sqlEscapeString(cacheType.id)); + selection.append(" and type = ?"); + selectionArgs = new String[] { String.valueOf(cacheType.id) }; } // offline caches only if (stored) { - where.append(" and reason >= " + StoredList.STANDARD_LIST_ID); + selection.append(" and reason >= " + StoredList.STANDARD_LIST_ID); } try { final Cursor cursor = database.query( dbTableCaches, new String[]{"geocode"}, - where.toString(), - null, + selection.toString(), + selectionArgs, null, null, null, "500"); - if (cursor.moveToFirst()) { - final int index = cursor.getColumnIndex("geocode"); - - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); + while (cursor.moveToNext()) { + geocodes.add(cursor.getString(0)); } + cursor.close(); - } catch (Exception e) { - Log.e("cgData.loadInViewport: " + e.toString()); + } catch (final Exception e) { + Log.e("cgData.loadInViewport", e); } - return geocodes; + return new SearchResult(geocodes); } /** delete caches from the DB store 3 days or more before */ - public void clean() { + public static void clean() { clean(false); } @@ -2392,15 +2223,17 @@ public class cgData { * @param more * true = all caches false = caches stored 3 days or more before */ - public void clean(boolean more) { + public static void clean(final boolean more) { + if (databaseCleaned) { + return; + } + init(); Log.d("Database clean: started"); - Cursor cursor; - Set<String> geocodes = new HashSet<String>(); - try { + Cursor cursor; if (more) { cursor = database.query( dbTableCaches, @@ -2425,44 +2258,31 @@ public class cgData { null); } - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - final int index = cursor.getColumnIndex("geocode"); - - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); - } - - cursor.close(); + Set<String> geocodes = new HashSet<String>(); + while (cursor.moveToNext()) { + geocodes.add(cursor.getString(0)); } - final int size = geocodes.size(); - if (size > 0) { - Log.d("Database clean: removing " + size + " geocaches from listId=0"); + cursor.close(); + if (!geocodes.isEmpty()) { + Log.d("Database clean: removing " + geocodes.size() + " geocaches from listId=0"); removeCaches(geocodes, LoadFlags.REMOVE_ALL); } - - final SQLiteStatement countSql = database.compileStatement("select count(_id) from " + dbTableCaches + " where reason = 0"); - final int count = (int) countSql.simpleQueryForLong(); - countSql.close(); - Log.d("Database clean: " + count + " geocaches remaining for listId=0"); - - } catch (Exception e) { - Log.w("cgData.clean: " + e.toString()); + } catch (final Exception e) { + Log.w("cgData.clean", e); } Log.d("Database clean: finished"); + databaseCleaned = true; } - public void removeAllFromCache() { + public static void removeAllFromCache() { // clean up CacheCache cacheCache.removeAllFromCache(); } - public void removeCache(final String geocode, EnumSet<LoadFlags.RemoveFlag> removeFlags) { + public static void removeCache(final String geocode, EnumSet<LoadFlags.RemoveFlag> removeFlags) { removeCaches(Collections.singleton(geocode), removeFlags); } @@ -2472,7 +2292,7 @@ public class cgData { * @param geocodes * list of geocodes to drop from cache */ - public void removeCaches(final Set<String> geocodes, EnumSet<LoadFlags.RemoveFlag> removeFlags) { + public static void removeCaches(final Set<String> geocodes, EnumSet<LoadFlags.RemoveFlag> removeFlags) { if (CollectionUtils.isEmpty(geocodes)) { return; } @@ -2519,7 +2339,7 @@ public class cgData { } } - public boolean saveLogOffline(String geocode, Date date, LogType type, String log) { + public static boolean saveLogOffline(String geocode, Date date, LogType type, String log) { if (StringUtils.isBlank(geocode)) { Log.e("cgData.saveLogOffline: cannot log a blank geocode"); return false; @@ -2546,16 +2366,15 @@ public class cgData { return id != -1; } - public LogEntry loadLogOffline(String geocode) { + public static LogEntry loadLogOffline(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - LogEntry log = null; - Cursor cursor = database.query( + final Cursor cursor = database.query( dbTableLogsOffline, new String[]{"_id", "type", "log", "date"}, "geocode = ?", @@ -2565,24 +2384,20 @@ public class cgData { "_id desc", "1"); - if (cursor != null && cursor.getCount() > 0) { - cursor.moveToFirst(); - - log = new LogEntry( - cursor.getLong(cursor.getColumnIndex("date")), - LogType.getById(cursor.getInt(cursor.getColumnIndex("type"))), - cursor.getString(cursor.getColumnIndex("log"))); - log.id = cursor.getInt(cursor.getColumnIndex("_id")); + LogEntry log = null; + if (cursor.moveToFirst()) { + log = new LogEntry(cursor.getLong(3), + LogType.getById(cursor.getInt(1)), + cursor.getString(2)); + log.id = cursor.getInt(0); } - if (cursor != null) { - cursor.close(); - } + cursor.close(); return log; } - public void clearLogOffline(String geocode) { + public static void clearLogOffline(String geocode) { if (StringUtils.isBlank(geocode)) { return; } @@ -2592,35 +2407,14 @@ public class cgData { database.delete(dbTableLogsOffline, "geocode = ?", new String[]{geocode}); } - private SQLiteStatement getStatementLogCount() { - return getStatement("LogCountFromGeocode", "SELECT count(_id) FROM " + dbTableLogsOffline + " WHERE geocode = ?"); - } - - private synchronized SQLiteStatement getStatement(final String key, final String query) { - SQLiteStatement statement = statements.get(key); - if (statement == null) { - statement = database.compileStatement(query); - statements.put(key, statement); - } - return statement; - } - - private SQLiteStatement getStatementCountStandardList() { - return getStatement("CountStandardList", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason = " + StoredList.STANDARD_LIST_ID); - } - - private SQLiteStatement getStatementCountAllLists() { - return getStatement("CountAllLists", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason >= " + StoredList.STANDARD_LIST_ID); - } - - public boolean hasLogOffline(final String geocode) { + public static boolean hasLogOffline(final String geocode) { if (StringUtils.isBlank(geocode)) { return false; } init(); try { - final SQLiteStatement logCount = getStatementLogCount(); + final SQLiteStatement logCount = PreparedStatements.getLogCountOfGeocode(); synchronized (logCount) { logCount.bindString(1, geocode); return logCount.simpleQueryForLong() > 0; @@ -2632,7 +2426,7 @@ public class cgData { return false; } - public void setVisitDate(List<String> geocodes, long visitedDate) { + private static void setVisitDate(List<String> geocodes, long visitedDate) { if (geocodes.isEmpty()) { return; } @@ -2641,11 +2435,12 @@ public class cgData { database.beginTransaction(); try { - ContentValues values = new ContentValues(); - values.put("visiteddate", visitedDate); + SQLiteStatement setVisit = PreparedStatements.getUpdateVisitDate(); for (String geocode : geocodes) { - database.update(dbTableCaches, values, "geocode = ?", new String[]{geocode}); + setVisit.bindLong(1, visitedDate); + setVisit.bindString(2, geocode); + setVisit.execute(); } database.setTransactionSuccessful(); } finally { @@ -2653,11 +2448,12 @@ public class cgData { } } - public List<StoredList> getLists(Resources res) { + public static List<StoredList> getLists() { init(); - List<StoredList> lists = new ArrayList<StoredList>(); - lists.add(new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) getStatementCountStandardList().simpleQueryForLong())); + final Resources res = cgeoapplication.getInstance().getResources(); + final List<StoredList> lists = new ArrayList<StoredList>(); + lists.add(new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatements.getCountCachesOnStandardList().simpleQueryForLong())); try { String query = "SELECT l._id as _id, l.title as title, COUNT(c._id) as count" + @@ -2666,47 +2462,38 @@ public class cgData { " GROUP BY l._id" + " ORDER BY l.title COLLATE NOCASE ASC"; - Cursor cursor = database.rawQuery(query, null); + final Cursor cursor = database.rawQuery(query, null); ArrayList<StoredList> storedLists = getListsFromCursor(cursor); lists.addAll(storedLists); - - } catch (Exception e) { - Log.e("cgData.readLists: " + e.toString()); + cursor.close(); + } catch (final Exception e) { + Log.e("cgData.readLists", e); } return lists; } - private static ArrayList<StoredList> getListsFromCursor(Cursor cursor) { - ArrayList<StoredList> result = new ArrayList<StoredList>(); - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - int indexId = cursor.getColumnIndex("_id"); - int indexTitle = cursor.getColumnIndex("title"); - int indexCount = cursor.getColumnIndex("count"); - do { - int count = 0; - if (indexCount >= 0) { - count = cursor.getInt(indexCount); - } - StoredList list = new StoredList(cursor.getInt(indexId) + customListIdOffset, cursor.getString(indexTitle), count); - result.add(list); - } while (cursor.moveToNext()); - } - - cursor.close(); + private static ArrayList<StoredList> getListsFromCursor(final Cursor cursor) { + final int indexId = cursor.getColumnIndex("_id"); + final int indexTitle = cursor.getColumnIndex("title"); + final int indexCount = cursor.getColumnIndex("count"); + final ArrayList<StoredList> result = new ArrayList<StoredList>(); + while (cursor.moveToNext()) { + final int count = indexCount != -1 ? cursor.getInt(indexCount) : 0; + final StoredList list = new StoredList(cursor.getInt(indexId) + customListIdOffset, cursor.getString(indexTitle), count); + result.add(list); } + cursor.close(); return result; } - public StoredList getList(int id, Resources res) { + public static StoredList getList(int id) { init(); if (id >= customListIdOffset) { Cursor cursor = database.query( dbTableLists, new String[]{"_id", "title"}, - "_id = " + (id - customListIdOffset), - null, + "_id = ? ", + new String[] { String.valueOf(id - customListIdOffset) }, null, null, null); @@ -2716,18 +2503,23 @@ public class cgData { } } + Resources res = cgeoapplication.getInstance().getResources(); if (id == StoredList.ALL_LIST_ID) { - return new StoredList(StoredList.ALL_LIST_ID, res.getString(R.string.list_all_lists), (int) getStatementCountAllLists().simpleQueryForLong()); + return new StoredList(StoredList.ALL_LIST_ID, res.getString(R.string.list_all_lists), getAllCachesCount()); } // fall back to standard list in case of invalid list id if (id == StoredList.STANDARD_LIST_ID || id >= customListIdOffset) { - return new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) getStatementCountStandardList().simpleQueryForLong()); + return new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatements.getCountCachesOnStandardList().simpleQueryForLong()); } return null; } + public static int getAllCachesCount() { + return (int) PreparedStatements.getCountAllCaches().simpleQueryForLong(); + } + /** * Create a new list * @@ -2735,7 +2527,7 @@ public class cgData { * Name * @return new listId */ - public int createList(String name) { + public static int createList(String name) { int id = -1; if (StringUtils.isBlank(name)) { return id; @@ -2765,15 +2557,15 @@ public class cgData { * New name of list * @return Number of lists changed */ - public int renameList(final int listId, final String name) { + public static int renameList(final int listId, final String name) { if (StringUtils.isBlank(name) || StoredList.STANDARD_LIST_ID == listId) { return 0; } init(); - int count = 0; database.beginTransaction(); + int count = 0; try { ContentValues values = new ContentValues(); values.put("title", name); @@ -2794,23 +2586,23 @@ public class cgData { * @param listId * @return true if the list got deleted, false else */ - public boolean removeList(int listId) { - boolean status = false; + public static boolean removeList(int listId) { if (listId < customListIdOffset) { - return status; + return false; } init(); database.beginTransaction(); + boolean status = false; try { int cnt = database.delete(dbTableLists, "_id = " + (listId - customListIdOffset), null); if (cnt > 0) { // move caches from deleted list to standard list - ContentValues values = new ContentValues(); - values.put("reason", StoredList.STANDARD_LIST_ID); - database.update(dbTableCaches, values, "reason = " + listId, null); + SQLiteStatement moveToStandard = PreparedStatements.getMoveToStandardList(); + moveToStandard.bindLong(1, listId); + moveToStandard.execute(); status = true; } @@ -2823,7 +2615,7 @@ public class cgData { return status; } - public void moveToList(final List<cgCache> caches, final int listId) { + public static void moveToList(final List<cgCache> caches, final int listId) { if (listId == StoredList.ALL_LIST_ID) { return; } @@ -2832,13 +2624,14 @@ public class cgData { } init(); - final ContentValues values = new ContentValues(); - values.put("reason", listId); + SQLiteStatement move = PreparedStatements.getMoveToList(); database.beginTransaction(); try { for (cgCache cache : caches) { - database.update(dbTableCaches, values, "geocode = ?", new String[]{cache.getGeocode()}); + move.bindLong(1, listId); + move.bindString(2, cache.getGeocode()); + move.execute(); cache.setListId(listId); } database.setTransactionSuccessful(); @@ -2847,61 +2640,39 @@ public class cgData { } } - public synchronized boolean status() { + public static boolean isInitialized() { return database != null; - } - public boolean removeSearchedDestination(Destination destination) { - boolean success = true; + public static boolean removeSearchedDestination(Destination destination) { if (destination == null) { - success = false; - } else { - init(); - - database.beginTransaction(); - try { - database.delete(dbTableSearchDestionationHistory, "_id = " + destination.getId(), null); - database.setTransactionSuccessful(); - } catch (Exception e) { - Log.e("Unable to remove searched destination", e); - success = false; - } finally { - database.endTransaction(); - } + return false; } + init(); - return success; - } - - private SQLiteStatement getStatementDescription() { - return getStatement("descriptionFromGeocode", "SELECT description FROM " + dbTableCaches + " WHERE geocode = ?"); - } - - private SQLiteStatement getStatementListIdFromGeocode() { - return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE geocode = ?"); - } - - private SQLiteStatement getStatementListIdFromGuid() { - return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE guid = ?"); - } - - private SQLiteStatement getStatementCacheId() { - return getStatement("cacheIdFromGeocode", "SELECT cacheid FROM " + dbTableCaches + " WHERE geocode = ?"); - } + database.beginTransaction(); + boolean result = false; + try { + database.delete(dbTableSearchDestionationHistory, "_id = " + destination.getId(), null); + database.setTransactionSuccessful(); + result = true; + } catch (Exception e) { + Log.e("Unable to remove searched destination", e); + } finally { + database.endTransaction(); + } - private SQLiteStatement getStatementGeocode() { - return getStatement("geocodeFromGuid", "SELECT geocode FROM " + dbTableCaches + " WHERE guid = ?"); + return result; } - public String getCacheDescription(String geocode) { + public static String getCacheDescription(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); try { - final SQLiteStatement description = getStatementDescription(); + final SQLiteStatement description = PreparedStatements.getDescriptionOfGeocode(); synchronized (description) { description.bindString(1, geocode); return description.simpleQueryForString(); @@ -2934,7 +2705,7 @@ public class cgData { private static String whereGeocodeIn(Set<String> geocodes) { final StringBuilder where = new StringBuilder(); - if (geocodes != null && geocodes.size() > 0) { + if (geocodes != null && !geocodes.isEmpty()) { StringBuilder all = new StringBuilder(); for (String geocode : geocodes) { if (all.length() > 0) { @@ -2958,7 +2729,7 @@ public class cgData { * @return */ - public Set<cgWaypoint> loadWaypoints(final Viewport viewport, boolean excludeMine, boolean excludeDisabled, CacheType type) { + public static Set<Waypoint> loadWaypoints(final Viewport viewport, boolean excludeMine, boolean excludeDisabled, CacheType type) { final StringBuilder where = new StringBuilder(buildCoordinateWhere(dbTableWaypoints, viewport)); if (excludeMine) { where.append(" and ").append(dbTableCaches).append(".own == 0 and ").append(dbTableCaches).append(".found == 0"); @@ -2967,7 +2738,7 @@ public class cgData { where.append(" and ").append(dbTableCaches).append(".disabled == 0"); } if (type != CacheType.ALL) { - where.append(" and ").append(dbTableCaches).append(".type == '").append(type.id).append("'"); + where.append(" and ").append(dbTableCaches).append(".type == '").append(type.id).append('\''); } init(); @@ -2977,23 +2748,16 @@ public class cgData { } query.append(" FROM ").append(dbTableWaypoints).append(", ").append(dbTableCaches).append(" WHERE ").append(dbTableWaypoints).append(".geocode == ").append(dbTableCaches).append(".geocode and ").append(where); + final Set<Waypoint> waypoints = new HashSet<Waypoint>(); final Cursor cursor = database.rawQuery(query.toString(), null); - try { - if (!cursor.moveToFirst()) { - return Collections.emptySet(); - } - - final Set<cgWaypoint> waypoints = new HashSet<cgWaypoint>(); - do { - waypoints.add(createWaypointFromDatabaseContent(cursor)); - } while (cursor.moveToNext()); - return waypoints; - } finally { - cursor.close(); + while (cursor.moveToNext()) { + waypoints.add(createWaypointFromDatabaseContent(cursor)); } + cursor.close(); + return waypoints; } - public String[] getTrackableCodes() { + public static String[] getTrackableCodes() { init(); final Cursor cursor = database.query( @@ -3005,21 +2769,168 @@ public class cgData { null, "updated DESC", "100"); + return getFirstColumn(cursor); + } + + /** + * Extract the first column of the cursor rows and close the cursor. + * + * @param cursor a database cursor + * @return the first column of each row + */ + private static String[] getFirstColumn(final Cursor cursor) { + final String[] result = new String[cursor.getCount()]; + for (int i = 0; cursor.moveToNext(); i++) { + result[i] = cursor.getString(0); + } + cursor.close(); + return result; + } + + public static boolean saveChangedCache(cgCache cache) { + return cgData.saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.SAVE_CACHE)); + } - final ArrayList<String> list = new ArrayList<String>(); - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); + private static class PreparedStatements { - final int index = cursor.getColumnIndex("tbcode"); - do { - list.add(cursor.getString(index)); - } while (cursor.moveToNext()); + private static HashMap<String, SQLiteStatement> statements = new HashMap<String, SQLiteStatement>(); + + public static SQLiteStatement getMoveToStandardList() { + return getStatement("MoveToStandardList", "UPDATE " + dbTableCaches + " SET reason = " + StoredList.STANDARD_LIST_ID + " WHERE reason = ?"); + } + + public static SQLiteStatement getMoveToList() { + return getStatement("MoveToList", "UPDATE " + dbTableCaches + " SET reason = ? WHERE geocode = ?"); + } + + public static SQLiteStatement getUpdateVisitDate() { + return getStatement("UpdateVisitDate", "UPDATE " + dbTableCaches + " SET visiteddate = ? WHERE geocode = ?"); + } + + public static SQLiteStatement getInsertLogImage() { + return getStatement("InsertLogImage", "INSERT INTO " + dbTableLogImages + " (log_id, title, url) VALUES (?, ?, ?)"); + } + + public static SQLiteStatement getInsertLogCounts() { + return getStatement("InsertLogCounts", "INSERT INTO " + dbTableLogCount + " (geocode, updated, type, count) VALUES (?, ?, ?, ?)"); + } + + public static SQLiteStatement getInsertSpoiler() { + return getStatement("InsertSpoiler", "INSERT INTO " + dbTableSpoilers + " (geocode, updated, url, title, description) VALUES (?, ?, ?, ?, ?)"); + } + + public static SQLiteStatement getInsertSearchDestination(Destination destination) { + final SQLiteStatement statement = getStatement("InsertSearch", "INSERT INTO " + dbTableSearchDestionationHistory + " (date, latitude, longitude) VALUES (?, ?, ?)"); + statement.bindLong(1, destination.getDate()); + final Geopoint coords = destination.getCoords(); + statement.bindDouble(2, coords.getLatitude()); + statement.bindDouble(3, coords.getLongitude()); + return statement; + } + + private static void clearPreparedStatements() { + for (SQLiteStatement statement : statements.values()) { + statement.close(); } - cursor.close(); + statements.clear(); + } + + private static synchronized SQLiteStatement getStatement(final String key, final String query) { + SQLiteStatement statement = statements.get(key); + if (statement == null) { + Log.d("Compiling " + key); + statement = database.compileStatement(query); + statements.put(key, statement); + } + return statement; + } + + public static SQLiteStatement getCountHistoryCaches() { + return getStatement("HistoryCount", "select count(_id) from " + dbTableCaches + " where visiteddate > 0"); } - return list.toArray(new String[list.size()]); + private static SQLiteStatement getLogCountOfGeocode() { + return getStatement("LogCountFromGeocode", "SELECT count(_id) FROM " + cgData.dbTableLogsOffline + " WHERE geocode = ?"); + } + + private static SQLiteStatement getCountCachesOnStandardList() { + return getStatement("CountStandardList", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason = " + StoredList.STANDARD_LIST_ID); + } + + private static SQLiteStatement getCountAllCaches() { + return getStatement("CountAllLists", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason >= " + StoredList.STANDARD_LIST_ID); + } + + private static SQLiteStatement getInsertLog() { + return getStatement("InsertLog", "INSERT INTO " + dbTableLogs + " (geocode, updated, type, author, log, date, found, friend) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); + } + + private static SQLiteStatement getInsertAttribute() { + return getStatement("InsertAttribute", "INSERT INTO " + dbTableAttributes + " (geocode, updated, attribute) VALUES (?, ?, ?)"); + } + + private static SQLiteStatement getDescriptionOfGeocode() { + return getStatement("descriptionFromGeocode", "SELECT description FROM " + dbTableCaches + " WHERE geocode = ?"); + } + + private static SQLiteStatement getListIdOfGeocode() { + return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE geocode = ?"); + } + + private static SQLiteStatement getListIdOfGuid() { + return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE guid = ?"); + } + + private static SQLiteStatement getCacheIdOfGeocode() { + return getStatement("cacheIdFromGeocode", "SELECT cacheid FROM " + dbTableCaches + " WHERE geocode = ?"); + } + + private static SQLiteStatement getGeocodeOfGuid() { + return getStatement("geocodeFromGuid", "SELECT geocode FROM " + dbTableCaches + " WHERE guid = ?"); + } + + } + + public static void saveVisitDate(final String geocode) { + setVisitDate(Collections.singletonList(geocode), System.currentTimeMillis()); + } + + public static void markDropped(List<cgCache> caches) { + moveToList(caches, StoredList.TEMPORARY_LIST_ID); + } + + public static Viewport getBounds(String geocode) { + if (geocode == null) { + return null; + } + + return cgData.getBounds(Collections.singleton(geocode)); + } + + public static void clearVisitDate(List<cgCache> caches) { + ArrayList<String> geocodes = new ArrayList<String>(caches.size()); + for (cgCache cache : caches) { + geocodes.add(cache.getGeocode()); + } + setVisitDate(geocodes, 0); + } + + public static SearchResult getBatchOfStoredCaches(Geopoint coords, CacheType cacheType, int listId) { + final Set<String> geocodes = cgData.loadBatchOfStoredGeocodes(coords, cacheType, listId); + return new SearchResult(geocodes, cgData.getAllStoredCachesCount(cacheType, listId)); + } + + public static SearchResult getHistoryOfCaches(boolean detailedOnly, CacheType cacheType) { + final Set<String> geocodes = cgData.loadBatchOfHistoricGeocodes(detailedOnly, cacheType); + return new SearchResult(geocodes, cgData.getAllHistoryCachesCount()); + } + + public static boolean saveWaypoint(int id, String geocode, Waypoint waypoint) { + if (cgData.saveWaypointInternal(id, geocode, waypoint)) { + cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); + return true; + } + return false; } } diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/cgeo.java index c80ec6f..0091d7c 100644 --- a/main/src/cgeo/geocaching/cgeo.java +++ b/main/src/cgeo/geocaching/cgeo.java @@ -8,17 +8,17 @@ import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.Units; import cgeo.geocaching.maps.CGeoMap; -import cgeo.geocaching.network.StatusUpdater.Status; import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.GeoDirHandler; -import cgeo.geocaching.utils.IObserver; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RunnableWithArgument; import cgeo.geocaching.utils.Version; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import android.app.AlertDialog; +import android.app.AlertDialog.Builder; import android.app.SearchManager; import android.content.DialogInterface; import android.content.Intent; @@ -27,36 +27,28 @@ import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.location.Address; import android.location.Geocoder; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.view.ContextMenu; import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Locale; public class cgeo extends AbstractActivity { private static final String SCAN_INTENT = "com.google.zxing.client.android.SCAN"; - private static final int MENU_ABOUT = 0; - private static final int MENU_HELPERS = 1; - private static final int MENU_SETTINGS = 2; - private static final int MENU_HISTORY = 3; - private static final int MENU_SCAN = 4; private static final int SCAN_REQUEST_CODE = 1; - private static final int MENU_OPEN_LIST = 100; - public static final int SEARCH_REQUEST_CODE = 2; private int version = 0; @@ -172,74 +164,11 @@ public class cgeo extends AbstractActivity { showToast(res.getString(reason == StatusCode.MAINTENANCE ? reason.getErrorString() : R.string.err_login_failed_toast)); } } catch (Exception e) { - Log.w("cgeo.firstLoginHander: " + e.toString()); + Log.w("cgeo.firstLoginHander", e); } } }; - private class StatusHandler extends Handler implements IObserver<Status> { - - @Override - public void update(final Status data) { - obtainMessage(0, data).sendToTarget(); - } - - @Override - public void handleMessage(final Message msg) { - final Status data = (Status) msg.obj; - updateDisplay(data != null && data.message != null ? data : null); - } - - private void updateDisplay(final Status data) { - final ViewGroup status = (ViewGroup) findViewById(R.id.status); - final ImageView statusIcon = (ImageView) findViewById(R.id.status_icon); - final TextView statusMessage = (TextView) findViewById(R.id.status_message); - - if (data == null) { - status.setVisibility(View.GONE); - return; - } - - if (data.icon != null) { - final int iconId = res.getIdentifier(data.icon, "drawable", getPackageName()); - if (iconId != 0) { - statusIcon.setImageResource(iconId); - statusIcon.setVisibility(View.VISIBLE); - } else { - Log.e("StatusHandler: could not find icon corresponding to @drawable/" + data.icon); - statusIcon.setVisibility(View.GONE); - } - } else { - statusIcon.setVisibility(View.GONE); - } - - String message = data.message; - if (data.messageId != null) { - final int messageId = res.getIdentifier(data.messageId, "string", getPackageName()); - if (messageId != 0) { - message = res.getString(messageId); - } - } - - statusMessage.setText(message); - status.setVisibility(View.VISIBLE); - - if (data.url != null) { - status.setOnClickListener(new OnClickListener() { - @Override - public void onClick(final View v) { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(data.url))); - } - }); - } else { - status.setClickable(false); - } - } - - } - - private StatusHandler statusHandler = new StatusHandler(); - public cgeo() { super("c:geo-main-screen"); } @@ -248,6 +177,12 @@ public class cgeo extends AbstractActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { + // If we had been open already, start from the last used activity. + finish(); + return; + } + setContentView(R.layout.main); setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); // type to search @@ -288,7 +223,6 @@ public class cgeo extends AbstractActivity { @Override public void onResume() { super.onResume(); - app.getStatusUpdater().addObserver(statusHandler); locationUpdater.startGeo(); satellitesHandler.startGeo(); updateUserInfoHandler.sendEmptyMessage(-1); @@ -312,7 +246,6 @@ public class cgeo extends AbstractActivity { @Override public void onPause() { initialized = false; - app.getStatusUpdater().deleteObserver(statusHandler); locationUpdater.stopGeo(); satellitesHandler.stopGeo(); super.onPause(); @@ -320,18 +253,15 @@ public class cgeo extends AbstractActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { - menu.add(0, MENU_SETTINGS, 0, res.getString(R.string.menu_settings)).setIcon(R.drawable.ic_menu_preferences); - menu.add(0, MENU_HISTORY, 0, res.getString(R.string.menu_history)).setIcon(R.drawable.ic_menu_recent_history); - menu.add(0, MENU_HELPERS, 0, res.getString(R.string.menu_helpers)).setIcon(R.drawable.ic_menu_shopping); - menu.add(0, MENU_SCAN, 0, res.getString(R.string.menu_scan_geo)).setIcon(R.drawable.ic_menu_barcode); - menu.add(0, MENU_ABOUT, 0, res.getString(R.string.menu_about)).setIcon(R.drawable.ic_menu_info_details); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main_options, menu); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - MenuItem item = menu.findItem(MENU_SCAN); + MenuItem item = menu.findItem(R.id.menu_scan); if (item != null) { item.setEnabled(isIntentAvailable(SCAN_INTENT)); } @@ -350,26 +280,25 @@ public class cgeo extends AbstractActivity { public boolean onOptionsItemSelected(MenuItem item) { final int id = item.getItemId(); switch (id) { - case MENU_ABOUT: + case R.id.menu_about: showAbout(null); return true; - case MENU_HELPERS: + case R.id.menu_helpers: startActivity(new Intent(this, UsefulAppsActivity.class)); return true; - case MENU_SETTINGS: + case R.id.menu_settings: startActivity(new Intent(this, SettingsActivity.class)); return true; - case MENU_HISTORY: + case R.id.menu_history: cgeocaches.startActivityHistory(this); return true; - case MENU_SCAN: + case R.id.menu_scan: startScannerApplication(); return true; default: - break; + return super.onOptionsItemSelected(item); } - return false; } private void startScannerApplication() { @@ -408,90 +337,6 @@ public class cgeo extends AbstractActivity { } } - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); - - // context menu for offline button - if (v.getId() == R.id.search_offline) { - menu.setHeaderTitle(res.getString(R.string.list_title)); - for (final StoredList list : app.getLists()) { - menu.add(Menu.NONE, MENU_OPEN_LIST + list.id, Menu.NONE, list.getTitleAndCount()); - } - return; - } - - // standard context menu - menu.setHeaderTitle(res.getString(R.string.menu_filter)); - - //first add the most used types - menu.add(1, 0, 0, CacheType.ALL.getL10n()); - menu.add(1, 1, 0, CacheType.TRADITIONAL.getL10n()); - menu.add(1, 2, 0, CacheType.MULTI.getL10n()); - menu.add(1, 3, 0, CacheType.MYSTERY.getL10n()); - - // then add all other cache types sorted alphabetically - List<String> sorted = new ArrayList<String>(); - for (CacheType ct : CacheType.values()) { - if (ct == CacheType.ALL || - ct == CacheType.TRADITIONAL || - ct == CacheType.MULTI || - ct == CacheType.MYSTERY) { - continue; - } - sorted.add(ct.getL10n()); - } - Collections.sort(sorted); - for (String choice : sorted) { - menu.add(1, menu.size(), 0, choice); - } - - // mark current filter as checked - menu.setGroupCheckable(1, true, true); - boolean foundItem = false; - int itemCount = menu.size(); - String typeTitle = Settings.getCacheType().getL10n(); - for (int i = 0; i < itemCount; i++) { - if (menu.getItem(i).getTitle().equals(typeTitle)) { - menu.getItem(i).setChecked(true); - foundItem = true; - break; - } - } - if (!foundItem) { - menu.getItem(0).setChecked(true); - } - } - - @Override - public boolean onContextItemSelected(final MenuItem item) { - final int id = item.getItemId(); - if (id < 0) { - return false; - } - - if (id == 0) { - Settings.setCacheType(CacheType.ALL); - setFilterTitle(); - } else if (id > MENU_OPEN_LIST) { - Settings.saveLastList(id - MENU_OPEN_LIST); - cgeocaches.startActivityOffline(this); - } else { - final String itemTitle = item.getTitle().toString(); - CacheType cacheType = CacheType.ALL; - for (final CacheType ct : CacheType.values()) { - if (ct.getL10n().equalsIgnoreCase(itemTitle)) { - cacheType = ct; - break; - } - } - Settings.setCacheType(cacheType); - setFilterTitle(); - } - - return true; - } - private void setFilterTitle() { if (filterTitle == null) { filterTitle = (TextView) findViewById(R.id.filter_button_title); @@ -530,7 +375,22 @@ public class cgeo extends AbstractActivity { cgeoFindByOffline(v); } }); - registerForContextMenu(findByOffline); + findByOffline.setOnLongClickListener(new View.OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + new StoredList.UserInterface(cgeo.this).promptForListSelection(R.string.list_title, new RunnableWithArgument<Integer>() { + + @Override + public void run(Integer selectedListId) { + Settings.saveLastList(selectedListId); + cgeocaches.startActivityOffline(cgeo.this); + } + }); + return true; + } + }); + findByOffline.setLongClickable(true); final View advanced = findViewById(R.id.advanced_button); advanced.setClickable(true); @@ -552,11 +412,18 @@ public class cgeo extends AbstractActivity { final View filter = findViewById(R.id.filter_button); filter.setClickable(true); - registerForContextMenu(filter); filter.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - openContextMenu(v); + selectGlobalTypeFilter(); + } + }); + filter.setOnLongClickListener(new View.OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + selectGlobalTypeFilter(); + return true; } }); @@ -567,12 +434,62 @@ public class cgeo extends AbstractActivity { (new cleanDatabase()).start(); } - private void updateCacheCounter() { + protected void selectGlobalTypeFilter() { + final List<CacheType> cacheTypes = new ArrayList<CacheType>(); + + //first add the most used types + cacheTypes.add(CacheType.ALL); + cacheTypes.add(CacheType.TRADITIONAL); + cacheTypes.add(CacheType.MULTI); + cacheTypes.add(CacheType.MYSTERY); + + // then add all other cache types sorted alphabetically + List<CacheType> sorted = new ArrayList<CacheType>(); + sorted.addAll(Arrays.asList(CacheType.values())); + sorted.removeAll(cacheTypes); + + Collections.sort(sorted, new Comparator<CacheType>() { + + @Override + public int compare(CacheType left, CacheType right) { + return left.getL10n().compareToIgnoreCase(right.getL10n()); + } + }); + + cacheTypes.addAll(sorted); + + int checkedItem = cacheTypes.indexOf(Settings.getCacheType()); + if (checkedItem < 0) { + checkedItem = 0; + } + + String[] items = new String[cacheTypes.size()]; + for (int i = 0; i < cacheTypes.size(); i++) { + items[i] = cacheTypes.get(i).getL10n(); + } + + Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.menu_filter); + builder.setSingleChoiceItems(items, checkedItem, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int position) { + CacheType cacheType = cacheTypes.get(position); + Settings.setCacheType(cacheType); + setFilterTitle(); + dialog.dismiss(); + } + + }); + builder.create().show(); + } + + void updateCacheCounter() { (new CountBubbleUpdateThread()).start(); } private void checkRestore() { - if (!cgData.isNewlyCreatedDatebase() || null == cgData.isRestoreFile()) { + if (!cgData.isNewlyCreatedDatebase() || null == cgData.getRestoreFile()) { return; } new AlertDialog.Builder(this) @@ -585,7 +502,6 @@ public class cgeo extends AbstractActivity { dialog.dismiss(); cgData.resetNewlyCreatedDatabase(); app.restoreDatabase(cgeo.this); - updateCacheCounter(); } }) .setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() { @@ -747,7 +663,7 @@ public class cgeo extends AbstractActivity { countBubble.setVisibility(View.VISIBLE); } } catch (Exception e) { - Log.w("cgeo.countBubbleHander: " + e.toString()); + Log.w("cgeo.countBubbleHander", e); } } }; @@ -759,7 +675,7 @@ public class cgeo extends AbstractActivity { } int checks = 0; - while (!app.storageStatus()) { + while (!cgData.isInitialized()) { try { wait(500); checks++; @@ -772,7 +688,7 @@ public class cgeo extends AbstractActivity { } } - countBubbleCnt = app.getAllStoredCachesCount(true, CacheType.ALL); + countBubbleCnt = cgData.getAllCachesCount(); countBubbleHandler.sendEmptyMessage(0); } @@ -797,7 +713,7 @@ public class cgeo extends AbstractActivity { } cleanupRunning = true; - app.cleanDatabase(more); + cgData.clean(more); cleanupRunning = false; if (version > 0) { diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java index 9e221cd..f25701e 100644 --- a/main/src/cgeo/geocaching/cgeoapplication.java +++ b/main/src/cgeo/geocaching/cgeoapplication.java @@ -1,21 +1,10 @@ package cgeo.geocaching; -import cgeo.geocaching.cgData.StorageLocation; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; -import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; -import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; -import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.network.StatusUpdater; import cgeo.geocaching.utils.IObserver; import cgeo.geocaching.utils.Log; -import org.apache.commons.lang3.StringUtils; - import android.app.Activity; import android.app.Application; import android.app.ProgressDialog; @@ -23,27 +12,17 @@ import android.content.res.Resources; import android.os.Handler; import android.os.Message; -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.EnumSet; -import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; public class cgeoapplication extends Application { - final private cgData storage = new cgData(); private volatile GeoDataProvider geo; private volatile DirectionProvider dir; public boolean firstRun = true; // c:geo is just launched public boolean showLoginToast = true; //login toast shown just once. - private boolean databaseCleaned = false; // database was cleaned private boolean liveMapHintShown = false; // livemap hint has been shown final private StatusUpdater statusUpdater = new StatusUpdater(); - private static cgeoapplication instance = null; + private static cgeoapplication instance; public cgeoapplication() { instance = this; @@ -61,29 +40,21 @@ public class cgeoapplication extends Application { @Override public void onLowMemory() { Log.i("Cleaning applications cache."); - removeAllFromCache(); - } - - public void removeAllFromCache() { - storage.removeAllFromCache(); + cgData.removeAllFromCache(); } @Override public void onTerminate() { Log.d("Terminating c:geo…"); - storage.clean(); - storage.closeDb(); + cgData.clean(); + cgData.closeDb(); super.onTerminate(); } - public String backupDatabase() { - return storage.backupDatabase(); - } - /** - * Move the database to/from external storage in a new thread, + * Move the database to/from external cgdata in a new thread, * showing a progress window * * @param fromActivity @@ -105,18 +76,13 @@ public class cgeoapplication extends Application { @Override public void run() { - atomic.set(storage.moveDatabase()); + atomic.set(cgData.moveDatabase()); handler.sendMessage(handler.obtainMessage()); } }; moveThread.start(); } - - public static File isRestoreFile() { - return cgData.isRestoreFile(); - } - /** * restore the database in a new thread, showing a progress window * @@ -135,12 +101,15 @@ public class cgeoapplication extends Application { boolean restored = atomic.get(); String message = restored ? res.getString(R.string.init_restore_success) : res.getString(R.string.init_restore_failed); ActivityMixin.helpDialog(fromActivity, res.getString(R.string.init_backup_restore), message); + if (fromActivity instanceof cgeo) { + ((cgeo) fromActivity).updateCacheCounter(); + } } }; @Override public void run() { - atomic.set(storage.restoreDatabase()); + atomic.set(cgData.restoreDatabase()); handler.sendMessage(handler.obtainMessage()); } }; @@ -203,280 +172,6 @@ public class cgeoapplication extends Application { return statusUpdater; } - public boolean storageStatus() { - return storage.status(); - } - - public void cleanDatabase(boolean more) { - if (databaseCleaned) { - return; - } - - storage.clean(more); - databaseCleaned = true; - } - - /** {@link cgData#isThere(String, String, boolean, boolean)} */ - public boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) { - return storage.isThere(geocode, guid, detailed, checkTime); - } - - /** {@link cgData#isOffline(String, String)} */ - public boolean isOffline(String geocode, String guid) { - return storage.isOffline(geocode, guid); - } - - /** {@link cgData#getGeocodeForGuid(String)} */ - public String getGeocode(String guid) { - return storage.getGeocodeForGuid(guid); - } - - /** {@link cgData#getCacheidForGeocode(String)} */ - public String getCacheid(String geocode) { - return storage.getCacheidForGeocode(geocode); - } - - public boolean hasUnsavedCaches(final SearchResult search) { - if (search == null) { - return false; - } - - for (final String geocode : search.getGeocodes()) { - if (!isOffline(geocode, null)) { - return true; - } - } - return false; - } - - public cgTrackable getTrackableByGeocode(String geocode) { - if (StringUtils.isBlank(geocode)) { - return null; - } - - return storage.loadTrackable(geocode); - } - - /** {@link cgData#allDetailedThere()} */ - public String[] geocodesInCache() { - return storage.allDetailedThere(); - } - - public Viewport getBounds(String geocode) { - if (geocode == null) { - return null; - } - - return getBounds(Collections.singleton(geocode)); - } - - /** {@link cgData#getBounds(Set)} */ - public Viewport getBounds(final Set<String> geocodes) { - return storage.getBounds(geocodes); - } - - /** {@link cgData#loadBatchOfStoredGeocodes(boolean, Geopoint, CacheType, int)} */ - public SearchResult getBatchOfStoredCaches(final boolean detailedOnly, final Geopoint coords, final CacheType cacheType, final int listId) { - final Set<String> geocodes = storage.loadBatchOfStoredGeocodes(detailedOnly, coords, cacheType, listId); - return new SearchResult(geocodes, getAllStoredCachesCount(true, cacheType, listId)); - } - - /** {@link cgData#loadHistoryOfSearchedLocations()} */ - public List<Destination> getHistoryOfSearchedLocations() { - return storage.loadHistoryOfSearchedLocations(); - } - - public SearchResult getHistoryOfCaches(final boolean detailedOnly, final CacheType cacheType) { - final Set<String> geocodes = storage.loadBatchOfHistoricGeocodes(detailedOnly, cacheType); - return new SearchResult(geocodes, getAllHistoricCachesCount()); - } - - /** {@link cgData#loadCachedInViewport(Viewport, CacheType)} */ - public SearchResult getCachedInViewport(final Viewport viewport, final CacheType cacheType) { - final Set<String> geocodes = storage.loadCachedInViewport(viewport, cacheType); - return new SearchResult(geocodes); - } - - /** {@link cgData#loadStoredInViewport(Viewport, CacheType)} */ - public SearchResult getStoredInViewport(final Viewport viewport, final CacheType cacheType) { - final Set<String> geocodes = storage.loadStoredInViewport(viewport, cacheType); - return new SearchResult(geocodes); - } - - /** {@link cgData#getAllStoredCachesCount(boolean, CacheType, int)} */ - public int getAllStoredCachesCount(final boolean detailedOnly, final CacheType cacheType) { - return storage.getAllStoredCachesCount(detailedOnly, cacheType, 0); - } - - /** {@link cgData#getAllStoredCachesCount(boolean, CacheType, int)} */ - public int getAllStoredCachesCount(final boolean detailedOnly, final CacheType cacheType, final Integer list) { - return storage.getAllStoredCachesCount(detailedOnly, cacheType, list); - } - - /** {@link cgData#getAllHistoricCachesCount()} */ - public int getAllHistoricCachesCount() { - return storage.getAllHistoricCachesCount(); - } - - /** {@link cgData#moveToList(List, int)} */ - public void markStored(List<cgCache> caches, int listId) { - storage.moveToList(caches, listId); - } - - /** {@link cgData#moveToList(List, int)} */ - public void markDropped(List<cgCache> caches) { - storage.moveToList(caches, StoredList.TEMPORARY_LIST_ID); - } - - /** {@link cgData#clearSearchedDestinations()} */ - public boolean clearSearchedDestinations() { - return storage.clearSearchedDestinations(); - } - - /** {@link cgData#saveSearchedDestination(Destination)} */ - public void saveSearchedDestination(Destination destination) { - storage.saveSearchedDestination(destination); - } - - /** {@link cgData#saveWaypoints(cgCache)} */ - public boolean saveWaypoints(final cgCache cache) { - return storage.saveWaypoints(cache); - } - - public boolean saveWaypoint(int id, String geocode, cgWaypoint waypoint) { - if (storage.saveWaypoint(id, geocode, waypoint)) { - this.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); - return true; - } - return false; - } - - /** {@link cgData#deleteWaypoint(int)} */ - public boolean deleteWaypoint(int id) { - return storage.deleteWaypoint(id); - } - - public boolean saveTrackable(cgTrackable trackable) { - return storage.saveTrackable(trackable); - } - - /** {@link cgData#loadLogCounts(String)} */ - public Map<LogType, Integer> loadLogCounts(String geocode) { - return storage.loadLogCounts(geocode); - } - - /** {@link cgData#loadWaypoint(int)} */ - public cgWaypoint loadWaypoint(int id) { - return storage.loadWaypoint(id); - } - - /** {@link cgData#saveLogOffline(String, Date, LogType, String)} */ - public boolean saveLogOffline(String geocode, Date date, LogType logtype, String log) { - return storage.saveLogOffline(geocode, date, logtype, log); - } - - /** {@link cgData#loadLogOffline(String)} */ - public LogEntry loadLogOffline(String geocode) { - return storage.loadLogOffline(geocode); - } - - /** {@link cgData#clearLogOffline(String)} */ - public void clearLogOffline(String geocode) { - storage.clearLogOffline(geocode); - } - - /** {@link cgData#setVisitDate(List, long)} */ - public void saveVisitDate(String geocode) { - storage.setVisitDate(Collections.singletonList(geocode), System.currentTimeMillis()); - } - - /** {@link cgData#setVisitDate(List, long)} */ - public void clearVisitDate(List<cgCache> caches) { - ArrayList<String> geocodes = new ArrayList<String>(caches.size()); - for (cgCache cache : caches) { - geocodes.add(cache.getGeocode()); - } - storage.setVisitDate(geocodes, 0); - } - - /** {@link cgData#getLists(Resources)} */ - public List<StoredList> getLists() { - return storage.getLists(getResources()); - } - - /** {@link cgData#getList(int, Resources)} */ - public StoredList getList(int id) { - return storage.getList(id, getResources()); - } - - /** {@link cgData#createList(String)} */ - public int createList(String title) { - return storage.createList(title); - } - - /** {@link cgData#renameList(int, String)} */ - public int renameList(final int listId, final String title) { - return storage.renameList(listId, title); - } - - /** {@link cgData#removeList(int)} */ - public boolean removeList(int id) { - return storage.removeList(id); - } - - /** {@link cgData#removeSearchedDestination(Destination)} */ - public boolean removeSearchedDestinations(Destination destination) { - return storage.removeSearchedDestination(destination); - } - - /** {@link cgData#moveToList(List, int)} */ - public void moveToList(List<cgCache> caches, int listId) { - storage.moveToList(caches, listId); - } - - /** {@link cgData#getCacheDescription(String)} */ - public String getCacheDescription(String geocode) { - return storage.getCacheDescription(geocode); - } - - /** {@link cgData#loadCaches} */ - public cgCache loadCache(final String geocode, final EnumSet<LoadFlag> loadFlags) { - return storage.loadCache(geocode, loadFlags); - } - - /** {@link cgData#loadCaches} */ - public Set<cgCache> loadCaches(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) { - return storage.loadCaches(geocodes, loadFlags); - } - - /** - * Update a cache in the DB or in the CacheCace depending on it's storage location - * - * {@link cgData#saveCache} - */ - public boolean updateCache(cgCache cache) { - return saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.SAVE_CACHE)); - } - - /** {@link cgData#saveCache} */ - public boolean saveCache(cgCache cache, EnumSet<LoadFlags.SaveFlag> saveFlags) { - return storage.saveCache(cache, saveFlags); - } - - /** {@link cgData#removeCache} */ - public void removeCache(String geocode, EnumSet<LoadFlags.RemoveFlag> removeFlags) { - storage.removeCache(geocode, removeFlags); - } - - /** {@link cgData#removeCaches} */ - public void removeCaches(final Set<String> geocodes, EnumSet<LoadFlags.RemoveFlag> removeFlags) { - storage.removeCaches(geocodes, removeFlags); - } - - public Set<cgWaypoint> getWaypointsInViewport(final Viewport viewport, boolean excludeMine, boolean excludeDisabled, CacheType type) { - return storage.loadWaypoints(viewport, excludeMine, excludeDisabled, type); - } - public boolean isLiveMapHintShown() { return liveMapHintShown; } @@ -485,20 +180,4 @@ public class cgeoapplication extends Application { liveMapHintShown = true; } - public String[] getTrackableCodes() { - return storage.getTrackableCodes(); - } - - public List<LogEntry> loadLogs(final String geocode) { - return storage.loadLogs(geocode); - } - - public List<String> loadAttributes(final String geocode) { - return storage.loadAttributes(geocode); - } - - public List<cgWaypoint> loadWaypoints(final String geocode) { - return storage.loadWaypoints(geocode); - } - } diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 688af99..fa83a60 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -3,9 +3,12 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.AbstractListActivity; import cgeo.geocaching.activity.ActivityMixin; +import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cachelist.CacheListAppFactory; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.capability.ISearchByCenter; import cgeo.geocaching.connector.gc.AbstractSearchThread; import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.connector.gc.SearchHandler; @@ -28,6 +31,8 @@ import cgeo.geocaching.sorting.EventDateComparator; import cgeo.geocaching.sorting.VisitComparator; import cgeo.geocaching.ui.CacheListAdapter; import cgeo.geocaching.ui.LoggingUI; +import cgeo.geocaching.ui.WeakReferenceHandler; +import cgeo.geocaching.utils.DateUtils; import cgeo.geocaching.utils.GeoDirHandler; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.RunnableWithArgument; @@ -60,11 +65,12 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; -public class cgeocaches extends AbstractListActivity { +public class cgeocaches extends AbstractListActivity implements FilteredActivity { private static final String EXTRAS_USERNAME = "username"; private static final String EXTRAS_ADDRESS = "address"; @@ -98,6 +104,7 @@ public class cgeocaches extends AbstractListActivity { private static final int MENU_NAVIGATION = 69; private static final int MENU_STORE_CACHE = 73; private static final int MENU_FILTER = 74; + private static final int MENU_DELETE_EVENTS = 75; private static final int MSG_DONE = -1; private static final int MSG_RESTART_GEO_AND_DIR = -2; @@ -124,11 +131,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void updateGeoData(final IGeoData geo) { - if (adapter == null) { - return; - } - - if (geo.getCoords() != null) { + if (geo.getCoords() != null) { adapter.setActualCoordinates(geo.getCoords()); } if (!Settings.isUseCompass() || geo.getSpeed() > 5) { // use GPS when speed is higher than 18 km/h @@ -138,7 +141,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void updateDirection(final float direction) { - if (adapter == null || !Settings.isLiveList()) { + if (!Settings.isLiveList()) { return; } @@ -156,57 +159,42 @@ public class cgeocaches extends AbstractListActivity { */ private MenuItem navigationMenu; - private Handler loadCachesHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - try { - setAdapter(); - - updateTitle(); - - setDateComparatorForEventList(); + public void handleCachesLoaded() { + try { + setAdapter(); - showFooterMoreCaches(); + updateTitle(); - if (search != null && search.getError() == StatusCode.UNAPPROVED_LICENSE) { - AlertDialog.Builder dialog = new AlertDialog.Builder(cgeocaches.this); - dialog.setTitle(res.getString(R.string.license)); - dialog.setMessage(res.getString(R.string.err_license)); - dialog.setCancelable(true); - dialog.setNegativeButton(res.getString(R.string.license_dismiss), new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int id) { - Cookies.clearCookies(); - dialog.cancel(); - } - }); - dialog.setPositiveButton(res.getString(R.string.license_show), new DialogInterface.OnClickListener() { + setDateComparatorForEventList(); - @Override - public void onClick(DialogInterface dialog, int id) { - Cookies.clearCookies(); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/software/agreement.aspx?ID=0"))); - } - }); + showFooterMoreCaches(); - AlertDialog alert = dialog.create(); - alert.show(); - } else if (search != null && search.getError() != null) { - showToast(res.getString(R.string.err_download_fail) + ' ' + search.getError().getErrorString(res) + '.'); + if (search != null && search.getError() == StatusCode.UNAPPROVED_LICENSE) { + AlertDialog.Builder dialog = new AlertDialog.Builder(this); + dialog.setTitle(res.getString(R.string.license)); + dialog.setMessage(res.getString(R.string.err_license)); + dialog.setCancelable(true); + dialog.setNegativeButton(res.getString(R.string.license_dismiss), new DialogInterface.OnClickListener() { - hideLoading(); - showProgress(false); + @Override + public void onClick(DialogInterface dialog, int id) { + Cookies.clearCookies(); + dialog.cancel(); + } + }); + dialog.setPositiveButton(res.getString(R.string.license_show), new DialogInterface.OnClickListener() { - finish(); - return; - } + @Override + public void onClick(DialogInterface dialog, int id) { + Cookies.clearCookies(); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/software/agreement.aspx?ID=0"))); + } + }); - setAdapterCurrentCoordinates(false); - } catch (Exception e) { - showToast(res.getString(R.string.err_detail_cache_find_any)); - Log.e("cgeocaches.loadCachesHandler: " + e.toString()); + AlertDialog alert = dialog.create(); + alert.show(); + } else if (search != null && search.getError() != null) { + showToast(res.getString(R.string.err_download_fail) + ' ' + search.getError().getErrorString(res) + '.'); hideLoading(); showProgress(false); @@ -215,29 +203,52 @@ public class cgeocaches extends AbstractListActivity { return; } - try { - hideLoading(); - showProgress(false); - } catch (Exception e2) { - Log.e("cgeocaches.loadCachesHandler.2: " + e2.toString()); - } + setAdapterCurrentCoordinates(false); + } catch (Exception e) { + showToast(res.getString(R.string.err_detail_cache_find_any)); + Log.e("cgeocaches.loadCachesHandler", e); - if (adapter != null) { - adapter.setSelectMode(false); + hideLoading(); + showProgress(false); + + finish(); + return; + } + + try { + hideLoading(); + showProgress(false); + } catch (Exception e2) { + Log.e("cgeocaches.loadCachesHandler.2", e2); + } + + adapter.setSelectMode(false); + } + + private Handler loadCachesHandler = new LoadCachesHandler(this); + + private static class LoadCachesHandler extends WeakReferenceHandler<cgeocaches> { + + protected LoadCachesHandler(cgeocaches activity) { + super(activity); + } + + @Override + public void handleMessage(Message msg) { + final cgeocaches activity = getActivity(); + if (activity == null) { + return; } + activity.handleCachesLoaded(); } - }; + } + private Handler loadNextPageHandler = new Handler() { @Override public void handleMessage(Message msg) { try { - if (search != null) { - replaceCacheListFromSearch(); - if (adapter != null) { - adapter.reFilter(); - } - } + replaceCacheListFromSearch(); setAdapter(); updateTitle(); @@ -258,33 +269,41 @@ public class cgeocaches extends AbstractListActivity { setAdapterCurrentCoordinates(false); } catch (Exception e) { showToast(res.getString(R.string.err_detail_cache_find_next)); - Log.e("cgeocaches.loadNextPageHandler: " + e.toString()); + Log.e("cgeocaches.loadNextPageHandler", e); } hideLoading(); showProgress(false); - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); } }; - private Set<cgCache> cachesFromSearchResult; /** - * Loads the caches and fills the cachelist + * Loads the caches and fills the {@link #cacheList} according to {@link #search} content. + * + * If {@link #search} is <code>null</code>, this does nothing. */ private void replaceCacheListFromSearch() { - if (search!=null) { - cachesFromSearchResult = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); + if (search != null) { + final Set<cgCache> cachesFromSearchResult = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); + runOnUiThread(new Runnable() { + @Override + public void run() { + cacheList.clear(); + cacheList.addAll(cachesFromSearchResult); + adapter.reFilter(); + updateTitle(); + showFooterMoreCaches(); + } + }); } - refreshCacheListHandler.sendEmptyMessage(0); } protected void updateTitle() { ArrayList<Integer> numbers = new ArrayList<Integer>(); - if (adapter != null && adapter.isFiltered()) { + if (adapter.isFiltered()) { numbers.add(adapter.getCount()); } if (search != null) { @@ -307,9 +326,7 @@ public class cgeocaches extends AbstractListActivity { if (msg.what > -1) { cacheList.get(msg.what).setStatusChecked(false); - if (adapter != null) { - adapter.notifyDataSetChanged(); - } + adapter.notifyDataSetChanged(); int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000); int minutesRemaining = ((detailTotal - detailProgress) * secondsElapsed / ((detailProgress > 0) ? detailProgress : 1) / 60); @@ -353,9 +370,7 @@ public class cgeocaches extends AbstractListActivity { public void handleMessage(Message msg) { setAdapter(); - if (adapter != null) { - adapter.notifyDataSetChanged(); - } + adapter.notifyDataSetChanged(); if (msg.what == 0) { //no caches progress.setMessage(res.getString(R.string.web_import_waiting)); @@ -377,9 +392,7 @@ public class cgeocaches extends AbstractListActivity { threadWeb.kill(); } } else { - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); replaceCacheListFromSearch(); @@ -392,9 +405,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void handleMessage(Message msg) { if (msg.what != MSG_CANCEL) { - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); refreshCurrentList(); @@ -413,9 +424,7 @@ public class cgeocaches extends AbstractListActivity { if (msg.what > -1) { progress.setProgress(detailProgress); } else { - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); // reload history list (new LoadByHistoryThread()).start(); @@ -479,7 +488,7 @@ public class cgeocaches extends AbstractListActivity { listId = StoredList.STANDARD_LIST_ID; title = res.getString(R.string.stored_caches_button); } else { - final StoredList list = app.getList(listId); + final StoredList list = cgData.getList(listId); // list.id may be different if listId was not valid listId = list.id; title = list.title; @@ -630,10 +639,8 @@ public class cgeocaches extends AbstractListActivity { startGeoAndDir(); - if (adapter != null) { - adapter.setSelectMode(false); - setAdapterCurrentCoordinates(true); - } + adapter.setSelectMode(false); + setAdapterCurrentCoordinates(true); if (loadCachesHandler != null && search != null) { replaceCacheListFromSearch(); @@ -642,7 +649,7 @@ public class cgeocaches extends AbstractListActivity { // refresh standard list if it has changed (new caches downloaded) if (type == CacheListType.OFFLINE && listId >= StoredList.STANDARD_LIST_ID && search != null) { - SearchResult newSearch = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId); + SearchResult newSearch = cgData.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId); if (newSearch != null && newSearch.getTotal() != search.getTotal()) { refreshCurrentList(); } @@ -660,15 +667,6 @@ public class cgeocaches extends AbstractListActivity { } @Override - public void onDestroy() { - if (adapter != null) { - adapter = null; - } - - super.onDestroy(); - } - - @Override public void onPause() { removeGeoAndDir(); @@ -691,6 +689,7 @@ public class cgeocaches extends AbstractListActivity { subMenu.add(0, MENU_DROP_CACHES_AND_LIST, 0, res.getString(R.string.caches_drop_all_and_list)); subMenu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.cache_offline_refresh)); // download details for all caches subMenu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list)); + subMenu.add(0, MENU_DELETE_EVENTS, 0, res.getString(R.string.caches_delete_events)); //TODO: add submenu/AlertDialog and use R.string.gpx_import_title subMenu.add(0, MENU_IMPORT_GPX, 0, res.getString(R.string.gpx_import_title)); @@ -733,7 +732,7 @@ public class cgeocaches extends AbstractListActivity { super.onPrepareOptionsMenu(menu); try { - if (adapter != null && adapter.isSelectMode()) { + if (adapter.isSelectMode()) { menu.findItem(MENU_SWITCH_SELECT_MODE).setTitle(res.getString(R.string.caches_select_mode_exit)) .setIcon(R.drawable.ic_menu_clear_playlist); menu.findItem(MENU_INVERT_SELECTION).setVisible(true); @@ -753,6 +752,7 @@ public class cgeocaches extends AbstractListActivity { setVisible(menu, MENU_REFRESH_STORED, !isEmpty && (isConcrete || type != CacheListType.OFFLINE)); setVisible(menu, MENU_DROP_CACHES, !isEmpty); setVisible(menu, MENU_DROP_CACHES_AND_LIST, isConcrete && !isEmpty); + setVisible(menu, MENU_DELETE_EVENTS, isConcrete && !isEmpty && containsEvents()); setVisible(menu, MENU_MOVE_TO_LIST, !isEmpty); setVisible(menu, MENU_EXPORT, !isEmpty); setVisible(menu, MENU_REMOVE_FROM_HISTORY, !isEmpty); @@ -784,14 +784,14 @@ public class cgeocaches extends AbstractListActivity { item.setVisible(isNonDefaultList); } - final boolean multipleLists = app.getLists().size() >= 2; + final boolean multipleLists = cgData.getLists().size() >= 2; item = menu.findItem(MENU_SWITCH_LIST); if (item != null) { item.setVisible(multipleLists); } item = menu.findItem(MENU_MOVE_TO_LIST); if (item != null) { - item.setVisible(multipleLists && !isEmpty); + item.setVisible(!isEmpty); } setMenuItemLabel(menu, MENU_REMOVE_FROM_HISTORY, R.string.cache_remove_from_history, R.string.cache_clear_history); @@ -803,6 +803,15 @@ public class cgeocaches extends AbstractListActivity { return true; } + private boolean containsEvents() { + for (cgCache cache : adapter.getCheckedOrAllCaches()) { + if (cache.isEventCache()) { + return true; + } + } + return false; + } + private void setMenuItemLabel(final Menu menu, final int menuId, final int resIdSelection, final int resId) { final MenuItem menuItem = menu.findItem(menuId); if (menuItem == null) { @@ -821,9 +830,7 @@ public class cgeocaches extends AbstractListActivity { int itemId = item.getItemId(); switch (itemId) { case MENU_SWITCH_SELECT_MODE: - if (adapter != null) { - adapter.switchSelectMode(); - } + adapter.switchSelectMode(); invalidateOptionsMenuCompatible(); return true; case MENU_REFRESH_STORED: @@ -854,9 +861,7 @@ public class cgeocaches extends AbstractListActivity { renameList(); return false; case MENU_INVERT_SELECTION: - if (adapter != null) { - adapter.invertSelection(); - } + adapter.invertSelection(); invalidateOptionsMenuCompatible(); return false; case MENU_SWITCH_LIST: @@ -864,20 +869,7 @@ public class cgeocaches extends AbstractListActivity { invalidateOptionsMenuCompatible(); return false; case MENU_FILTER: - new FilterUserInterface(this).selectFilter(new RunnableWithArgument<IFilter>() { - @Override - public void run(IFilter selectedFilter) { - if (selectedFilter != null) { - setFilter(selectedFilter); - } - else { - // clear filter - if (adapter != null) { - setFilter(null); - } - } - } - }); + showFilterMenu(null); return true; case MENU_SORT: new ComparatorUserInterface(this).selectComparator(adapter.getCacheComparator(), new RunnableWithArgument<CacheComparator>() { @@ -901,30 +893,61 @@ public class cgeocaches extends AbstractListActivity { moveCachesToOtherList(); invalidateOptionsMenuCompatible(); return true; + case MENU_DELETE_EVENTS: + deletePastEvents(); + invalidateOptionsMenuCompatible(); + return true; + default: + return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, search); } + } - return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, search); + public void deletePastEvents() { + progress.show(this, null, res.getString(R.string.caches_drop_progress), true, dropDetailsHandler.obtainMessage(MSG_CANCEL)); + final List<cgCache> deletion = new ArrayList<cgCache>(); + for (cgCache cache : adapter.getCheckedOrAllCaches()) { + if (cache.isEventCache()) { + final Date eventDate = cache.getHiddenDate(); + if (DateUtils.daysSince(eventDate.getTime()) > 0) { + deletion.add(cache); + } + } + } + new DropDetailsThread(dropDetailsHandler, deletion).start(); + } + + /** + * called from the filter bar view + */ + @Override + public void showFilterMenu(final View view) { + new FilterUserInterface(this).selectFilter(new RunnableWithArgument<IFilter>() { + @Override + public void run(IFilter selectedFilter) { + if (selectedFilter != null) { + setFilter(selectedFilter); + } + else { + // clear filter + setFilter(null); + } + } + }); } private void setComparator(final CacheComparator comparator) { - if (adapter != null) { - adapter.setComparator(comparator); - } + adapter.setComparator(comparator); } @Override public void onCreateContextMenu(final ContextMenu menu, final View view, final ContextMenu.ContextMenuInfo info) { super.onCreateContextMenu(menu, view, info); - if (adapter == null) { - return; - } - AdapterContextMenuInfo adapterInfo = null; try { adapterInfo = (AdapterContextMenuInfo) info; } catch (Exception e) { - Log.w("cgeocaches.onCreateContextMenu: " + e.toString()); + Log.w("cgeocaches.onCreateContextMenu", e); } if (adapterInfo == null || adapterInfo.position >= adapter.getCount()) { @@ -944,10 +967,7 @@ public class cgeocaches extends AbstractListActivity { } if (cache.isOffline()) { menu.add(0, MENU_DROP_CACHE, 0, res.getString(R.string.cache_offline_drop)); - final List<StoredList> cacheLists = app.getLists(); - if (cacheLists.size() > 1) { - menu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list)); - } + menu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list)); menu.add(0, MENU_EXPORT, 0, res.getString(R.string.export)); } else { @@ -960,12 +980,12 @@ public class cgeocaches extends AbstractListActivity { @Override public void run(Integer newListId) { - app.moveToList(adapter.getCheckedOrAllCaches(), newListId); + cgData.moveToList(adapter.getCheckedOrAllCaches(), newListId); adapter.setSelectMode(false); refreshCurrentList(); } - }, true); + }, true, listId); } @Override @@ -983,7 +1003,7 @@ public class cgeocaches extends AbstractListActivity { try { adapterInfo = (AdapterContextMenuInfo) info; } catch (Exception e) { - Log.w("cgeocaches.onContextItemSelected: " + e.toString()); + Log.w("cgeocaches.onContextItemSelected", e); } final cgCache cache = adapterInfo != null ? getCacheFromAdapter(adapterInfo) : null; @@ -1003,7 +1023,7 @@ public class cgeocaches extends AbstractListActivity { break; case MENU_CACHE_DETAILS: final Intent cachesIntent = new Intent(this, CacheDetailActivity.class); - cachesIntent.putExtra("geocode", cache.getGeocode().toUpperCase()); + cachesIntent.putExtra("geocode", cache.getGeocode()); cachesIntent.putExtra("name", cache.getName()); startActivity(cachesIntent); break; @@ -1021,11 +1041,11 @@ public class cgeocaches extends AbstractListActivity { @Override public void run(Integer newListId) { - app.moveToList(Collections.singletonList(cache), newListId); + cgData.moveToList(Collections.singletonList(cache), newListId); adapter.setSelectMode(false); refreshCurrentList(); } - }, true); + }, true, listId); break; case MENU_STORE_CACHE: //FIXME: this must use the same handler like in the CacheDetailActivity. Will be done by moving the handler into the store method. @@ -1062,24 +1082,19 @@ public class cgeocaches extends AbstractListActivity { } private boolean setFilter(IFilter filter) { - if (adapter != null) { - adapter.setFilter(filter); - prepareFilterBar(); - updateTitle(); - invalidateOptionsMenuCompatible(); - return true; - } - return false; + adapter.setFilter(filter); + prepareFilterBar(); + updateTitle(); + invalidateOptionsMenuCompatible(); + return true; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { - if (adapter != null) { - if (adapter.isSelectMode()) { - adapter.setSelectMode(false); - return true; - } + if (adapter.isSelectMode()) { + adapter.setSelectMode(false); + return true; } } return super.onKeyDown(keyCode, event); @@ -1239,7 +1254,7 @@ public class cgeocaches extends AbstractListActivity { dialog.setCancelable(true); dialog.setTitle(res.getString(R.string.caches_drop_stored)); - if (adapter != null && adapter.getCheckedCount() > 0) { + if (adapter.getCheckedCount() > 0) { dialog.setMessage(res.getString(R.string.caches_drop_selected_ask)); } else { dialog.setMessage(res.getString(R.string.caches_drop_all_ask)); @@ -1269,7 +1284,7 @@ public class cgeocaches extends AbstractListActivity { public void dropSelected() { progress.show(this, null, res.getString(R.string.caches_drop_progress), true, dropDetailsHandler.obtainMessage(MSG_CANCEL)); - new DropDetailsThread(dropDetailsHandler).start(); + new DropDetailsThread(dropDetailsHandler, adapter.getCheckedOrAllCaches()).start(); } private class LoadByOfflineThread extends Thread { @@ -1283,7 +1298,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId); + search = cgData.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId); replaceCacheListFromSearch(); loadCachesHandler.sendMessage(Message.obtain()); } @@ -1292,7 +1307,7 @@ public class cgeocaches extends AbstractListActivity { private class LoadByHistoryThread extends Thread { @Override public void run() { - search = cgeoapplication.getInstance().getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL); + search = cgData.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL); replaceCacheListFromSearch(); loadCachesHandler.sendMessage(Message.obtain()); } @@ -1319,7 +1334,17 @@ public class cgeocaches extends AbstractListActivity { @Override public void runSearch() { + search = GCParser.searchByCoords(coords, Settings.getCacheType(), Settings.isShowCaptcha()); + + for (ISearchByCenter centerConn : ConnectorFactory.getSearchByCenterConnectors()) { + if (centerConn.isActivated()) { + SearchResult temp = centerConn.searchByCenter(coords); + if (temp != null) { + search.addGeocodes(temp.getGeocodes()); + } + } + } replaceCacheListFromSearch(); } } @@ -1458,7 +1483,7 @@ public class cgeocaches extends AbstractListActivity { Log.i("Waiting for next cache " + delay + " ms"); } catch (Exception e) { - Log.e("cgeocaches.LoadDetailsThread.sleep: " + e.toString()); + Log.e("cgeocaches.LoadDetailsThread.sleep", e); } } @@ -1476,7 +1501,7 @@ public class cgeocaches extends AbstractListActivity { Log.i(e.getMessage()); return false; } catch (Exception e) { - Log.e("cgeocaches.LoadDetailsThread: " + e.toString()); + Log.e("cgeocaches.LoadDetailsThread", e); } last = System.currentTimeMillis(); @@ -1501,13 +1526,13 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - int ret = MSG_DONE; removeGeoAndDir(); int delay = -1; int times = 0; + int ret = MSG_DONE; while (!needToStop && times < 3 * 60 / 5) // maximum: 3 minutes, every 5 seconds { //download new code @@ -1558,7 +1583,7 @@ public class cgeocaches extends AbstractListActivity { times = 0; } } catch (InterruptedException e) { - Log.e("cgeocaches.LoadFromWebThread.sleep: " + e.toString()); + Log.e("cgeocaches.LoadFromWebThread.sleep", e); } } @@ -1573,15 +1598,15 @@ public class cgeocaches extends AbstractListActivity { final private Handler handler; final private List<cgCache> selected; - public DropDetailsThread(Handler handlerIn) { + public DropDetailsThread(Handler handlerIn, List<cgCache> selectedIn) { handler = handlerIn; - selected = adapter.getCheckedOrAllCaches(); + selected = selectedIn; } @Override public void run() { removeGeoAndDir(); - app.markDropped(selected); + cgData.markDropped(selected); handler.sendEmptyMessage(MSG_DONE); startGeoAndDir(); @@ -1600,7 +1625,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - app.clearVisitDate(selected); + cgData.clearVisitDate(selected); handler.sendEmptyMessage(MSG_DONE); } } @@ -1650,7 +1675,7 @@ public class cgeocaches extends AbstractListActivity { return; } - StoredList list = app.getList(id); + StoredList list = cgData.getList(id); if (list == null) { return; } @@ -1693,32 +1718,11 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { final List<cgCache> caches = adapter.getCheckedCaches(); - app.moveToList(caches, listId); + cgData.moveToList(caches, listId); handler.sendEmptyMessage(listId); } } - /** - * Handler to refresh the current list of caches. This list is shared with the Adapter and therefore must be updated - * in the UI-Thread - */ - - private Handler refreshCacheListHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - cacheList.clear(); - if (cachesFromSearchResult != null) { - cacheList.addAll(cachesFromSearchResult); - } - if (adapter != null) { - adapter.reFilter(); - } - updateTitle(); - showFooterMoreCaches(); - } - }; - - private void renameList() { new StoredList.UserInterface(this).promptForListRename(listId, new Runnable() { @@ -1730,7 +1734,7 @@ public class cgeocaches extends AbstractListActivity { } private void removeListInternal() { - if (app.removeList(listId)) { + if (cgData.removeList(listId)) { showToast(res.getString(R.string.list_dialog_remove_ok)); switchListById(StoredList.STANDARD_LIST_ID); } else { @@ -1783,18 +1787,14 @@ public class cgeocaches extends AbstractListActivity { return; } - SearchResult searchToUse = search; - // apply filter settings (if there's a filter) - if (adapter != null) { - Set<String> geocodes = new HashSet<String>(); - for (cgCache cache : adapter.getFilteredList()) { - geocodes.add(cache.getGeocode()); - } - searchToUse = new SearchResult(geocodes); + Set<String> geocodes = new HashSet<String>(); + for (cgCache cache : adapter.getFilteredList()) { + geocodes.add(cache.getGeocode()); } - int count = searchToUse.getCount(); + final SearchResult searchToUse = new SearchResult(geocodes); + final int count = searchToUse.getCount(); String mapTitle = title; if (count > 0) { mapTitle = title + " [" + count + "]"; diff --git a/main/src/cgeo/geocaching/cgeocoords.java b/main/src/cgeo/geocaching/cgeocoords.java index 1cf9630..0c2ffbf 100644 --- a/main/src/cgeo/geocaching/cgeocoords.java +++ b/main/src/cgeo/geocaching/cgeocoords.java @@ -378,6 +378,8 @@ public class cgeocoords extends Dialog { break; case Plain: // This case has been handled above + default: + throw new IllegalArgumentException(); } return true; diff --git a/main/src/cgeo/geocaching/cgeonavigate.java b/main/src/cgeo/geocaching/cgeonavigate.java index 64b7cd8..3c6bf73 100644 --- a/main/src/cgeo/geocaching/cgeonavigate.java +++ b/main/src/cgeo/geocaching/cgeonavigate.java @@ -61,8 +61,7 @@ public class cgeonavigate extends AbstractActivity { // get parameters Bundle extras = getIntent().getExtras(); if (extras != null) { - final String geocode = extras.getString(EXTRAS_GEOCODE); - title = geocode; + title = extras.getString(EXTRAS_GEOCODE); final String name = extras.getString(EXTRAS_NAME); dstCoords = (Geopoint) extras.getParcelable(EXTRAS_COORDS); info = extras.getString(EXTRAS_CACHE_INFO); @@ -293,7 +292,7 @@ public class cgeonavigate extends AbstractActivity { final Intent navigateIntent = new Intent(context, cgeonavigate.class); navigateIntent.putExtra(EXTRAS_COORDS, coords); - navigateIntent.putExtra(EXTRAS_GEOCODE, geocode.toUpperCase()); + navigateIntent.putExtra(EXTRAS_GEOCODE, geocode); if (null != displayedName) { navigateIntent.putExtra(EXTRAS_NAME, displayedName); } diff --git a/main/src/cgeo/geocaching/cgeopoint.java b/main/src/cgeo/geocaching/cgeopoint.java index 025b96a..e399a97 100644 --- a/main/src/cgeo/geocaching/cgeopoint.java +++ b/main/src/cgeo/geocaching/cgeopoint.java @@ -207,7 +207,7 @@ public class cgeopoint extends AbstractActivity { private List<Destination> getHistoryOfSearchedLocations() { if (historyOfSearchedLocations == null) { // Load from database - historyOfSearchedLocations = app.getHistoryOfSearchedLocations(); + historyOfSearchedLocations = cgData.loadHistoryOfSearchedLocations(); } return historyOfSearchedLocations; @@ -304,7 +304,7 @@ public class cgeopoint extends AbstractActivity { } } - private class changeDistanceUnit implements OnItemSelectedListener { + private static class changeDistanceUnit implements OnItemSelectedListener { private changeDistanceUnit(cgeopoint unitView) { this.unitView = unitView; @@ -393,7 +393,7 @@ public class cgeopoint extends AbstractActivity { getHistoryOfSearchedLocations().add(0, loc); // Save location - app.saveSearchedDestination(loc); + cgData.saveSearchedDestination(loc); // Ensure to remove the footer historyListView.removeFooterView(getEmptyHistoryFooter()); @@ -405,7 +405,7 @@ public class cgeopoint extends AbstractActivity { getHistoryOfSearchedLocations().remove(destination); // Save - app.removeSearchedDestinations(destination); + cgData.removeSearchedDestination(destination); if (getHistoryOfSearchedLocations().isEmpty()) { if (historyListView.getFooterViewsCount() == 0) { @@ -424,7 +424,7 @@ public class cgeopoint extends AbstractActivity { getHistoryOfSearchedLocations().clear(); // Save - app.clearSearchedDestinations(); + cgData.clearSearchedDestinations(); if (historyListView.getFooterViewsCount() == 0) { historyListView.addFooterView(getEmptyHistoryFooter()); @@ -487,8 +487,6 @@ public class cgeopoint extends AbstractActivity { } private Geopoint getDestination() { - Geopoint result; - Geopoint coords; String bearingText = ((EditText) findViewById(R.id.bearing)).getText().toString(); // combine distance from EditText and distanceUnit saved from Spinner @@ -502,6 +500,7 @@ public class cgeopoint extends AbstractActivity { return null; } + Geopoint coords; if (StringUtils.isNotBlank(latText) && StringUtils.isNotBlank(lonText)) { try { coords = new Geopoint(latText, lonText); @@ -518,6 +517,7 @@ public class cgeopoint extends AbstractActivity { coords = app.currentGeo().getCoords(); } + Geopoint result; if (StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) { // bearing & distance double bearing; diff --git a/main/src/cgeo/geocaching/cgeotrackable.java b/main/src/cgeo/geocaching/cgeotrackable.java deleted file mode 100644 index 93b410a..0000000 --- a/main/src/cgeo/geocaching/cgeotrackable.java +++ /dev/null @@ -1,574 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.activity.AbstractActivity; -import cgeo.geocaching.connector.gc.GCParser; -import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Units; -import cgeo.geocaching.network.HtmlImage; -import cgeo.geocaching.ui.CacheDetailsCreator; -import cgeo.geocaching.ui.Formatter; -import cgeo.geocaching.utils.BaseUtils; -import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.UnknownTagsHandler; - -import org.apache.commons.lang3.StringUtils; - -import android.app.ProgressDialog; -import android.content.Intent; -import android.graphics.drawable.BitmapDrawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.view.ContextMenu; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; - -public class cgeotrackable extends AbstractActivity { - private static final int MENU_LOG_TOUCH = 1; - private static final int MENU_BROWSER_TRACKABLE = 2; - private cgTrackable trackable = null; - private String geocode = null; - private String name = null; - private String guid = null; - private String id = null; - private String contextMenuUser = null; - private LayoutInflater inflater = null; - private ProgressDialog waitDialog = null; - private Handler loadTrackableHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - if (trackable == null) { - if (waitDialog != null) { - waitDialog.dismiss(); - } - - if (StringUtils.isNotBlank(geocode)) { - showToast(res.getString(R.string.err_tb_find) + " " + geocode + "."); - } else { - showToast(res.getString(R.string.err_tb_find_that)); - } - - finish(); - return; - } - - try { - inflater = getLayoutInflater(); - geocode = trackable.getGeocode().toUpperCase(); - - if (StringUtils.isNotBlank(trackable.getName())) { - setTitle(Html.fromHtml(trackable.getName()).toString()); - } else { - setTitle(trackable.getName().toUpperCase()); - } - - findViewById(R.id.details_list_box).setVisibility(View.VISIBLE); - final CacheDetailsCreator details = new CacheDetailsCreator(cgeotrackable.this, (LinearLayout) findViewById(R.id.details_list)); - - // action bar icon - if (StringUtils.isNotBlank(trackable.getIconUrl())) { - final TrackableIconHandler iconHandler = new TrackableIconHandler(((TextView) findViewById(R.id.actionbar_title))); - final TrackableIconThread iconThread = new TrackableIconThread(trackable.getIconUrl(), iconHandler); - iconThread.start(); - } - - // trackable name - details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown)); - - // trackable type - String tbType; - if (StringUtils.isNotBlank(trackable.getType())) { - tbType = Html.fromHtml(trackable.getType()).toString(); - } else { - tbType = res.getString(R.string.trackable_unknown); - } - details.add(R.string.trackable_type, tbType); - - // trackable geocode - details.add(R.string.trackable_code, trackable.getGeocode().toUpperCase()); - - // trackable owner - TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown)); - if (StringUtils.isNotBlank(trackable.getOwner())) { - owner.setText(Html.fromHtml(trackable.getOwner()), TextView.BufferType.SPANNABLE); - owner.setOnClickListener(new UserActionsListener()); - } - - // trackable spotted - if (StringUtils.isNotBlank(trackable.getSpottedName()) || - trackable.getSpottedType() == cgTrackable.SPOTTED_UNKNOWN || - trackable.getSpottedType() == cgTrackable.SPOTTED_OWNER - ) { - boolean showTimeSpan = true; - StringBuilder text; - - if (trackable.getSpottedType() == cgTrackable.SPOTTED_CACHE) { - text = new StringBuilder(res.getString(R.string.trackable_spotted_in_cache) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString()); - } else if (trackable.getSpottedType() == cgTrackable.SPOTTED_USER) { - text = new StringBuilder(res.getString(R.string.trackable_spotted_at_user) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString()); - } else if (trackable.getSpottedType() == cgTrackable.SPOTTED_UNKNOWN) { - text = new StringBuilder(res.getString(R.string.trackable_spotted_unknown_location)); - } else if (trackable.getSpottedType() == cgTrackable.SPOTTED_OWNER) { - text = new StringBuilder(res.getString(R.string.trackable_spotted_owner)); - } else { - text = new StringBuilder("N/A"); - showTimeSpan = false; - } - - // days since last spotting - if (showTimeSpan && trackable.getLogs() != null) { - for (LogEntry log : trackable.getLogs()) { - if (log.type == LogType.RETRIEVED_IT || log.type == LogType.GRABBED_IT || log.type == LogType.DISCOVERED_IT || log.type == LogType.PLACED_IT) { - final int days = log.daysSinceLog(); - text.append(" (").append(res.getQuantityString(R.plurals.days_ago, days, days)).append(')'); - break; - } - } - } - - final TextView spotted = details.add(R.string.trackable_spotted, text.toString()); - spotted.setClickable(true); - if (cgTrackable.SPOTTED_CACHE == trackable.getSpottedType()) { - spotted.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View arg0) { - CacheDetailActivity.startActivityGuid(cgeotrackable.this, trackable.getSpottedGuid(), trackable.getSpottedName()); - } - }); - } else if (cgTrackable.SPOTTED_USER == trackable.getSpottedType()) { - spotted.setOnClickListener(new UserActionsListener()); - } - } - - // trackable origin - if (StringUtils.isNotBlank(trackable.getOrigin())) { - TextView origin = details.add(R.string.trackable_origin, ""); - origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE); - } - - // trackable released - if (trackable.getReleased() != null) { - details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime())); - } - - // trackable distance - if (trackable.getDistance() >= 0) { - details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance())); - } - - // trackable goal - if (StringUtils.isNotBlank(trackable.getGoal())) { - findViewById(R.id.goal_box).setVisibility(View.VISIBLE); - TextView descView = (TextView) findViewById(R.id.goal); - descView.setVisibility(View.VISIBLE); - descView.setText(Html.fromHtml(trackable.getGoal(), new HtmlImage(geocode, true, 0, false), null), TextView.BufferType.SPANNABLE); - descView.setMovementMethod(LinkMovementMethod.getInstance()); - } - - // trackable details - if (StringUtils.isNotBlank(trackable.getDetails())) { - findViewById(R.id.details_box).setVisibility(View.VISIBLE); - TextView descView = (TextView) findViewById(R.id.details); - descView.setVisibility(View.VISIBLE); - descView.setText(Html.fromHtml(trackable.getDetails(), new HtmlImage(geocode, true, 0, false), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE); - descView.setMovementMethod(LinkMovementMethod.getInstance()); - } - - // trackable image - if (StringUtils.isNotBlank(trackable.getImage())) { - findViewById(R.id.image_box).setVisibility(View.VISIBLE); - LinearLayout imgView = (LinearLayout) findViewById(R.id.image); - - final ImageView trackableImage = (ImageView) inflater.inflate(R.layout.trackable_image, null); - - trackableImage.setImageResource(R.drawable.image_not_loaded); - trackableImage.setClickable(true); - trackableImage.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View arg0) { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getImage()))); - } - }); - - // try to load image - final Handler handler = new Handler() { - - @Override - public void handleMessage(Message message) { - BitmapDrawable image = (BitmapDrawable) message.obj; - if (image != null) { - trackableImage.setImageDrawable((BitmapDrawable) message.obj); - } - } - }; - - new Thread() { - - @Override - public void run() { - BitmapDrawable image; - try { - HtmlImage imgGetter = new HtmlImage(geocode, true, 0, false); - - image = imgGetter.getDrawable(trackable.getImage()); - Message message = handler.obtainMessage(0, image); - handler.sendMessage(message); - } catch (Exception e) { - Log.e("cgeospoilers.onCreate.onClick.run: " + e.toString()); - } - } - }.start(); - - imgView.addView(trackableImage); - } - } catch (Exception e) { - Log.e("cgeotrackable.loadTrackableHandler: " + e.toString() + Arrays.toString(e.getStackTrace())); - } - - displayLogs(); - - if (waitDialog != null) { - waitDialog.dismiss(); - } - } - }; - - public cgeotrackable() { - super("c:geo-trackable-details"); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setTheme(); - setContentView(R.layout.trackable_detail); - setTitle(res.getString(R.string.trackable)); - - // get parameters - Bundle extras = getIntent().getExtras(); - Uri uri = getIntent().getData(); - - // try to get data from extras - if (extras != null) { - geocode = extras.getString("geocode"); - name = extras.getString("name"); - guid = extras.getString("guid"); - id = extras.getString("id"); - } - - // try to get data from URI - if (geocode == null && guid == null && id == null && uri != null) { - String uriHost = uri.getHost().toLowerCase(); - if (uriHost.contains("geocaching.com")) { - geocode = uri.getQueryParameter("tracker"); - guid = uri.getQueryParameter("guid"); - id = uri.getQueryParameter("id"); - - if (StringUtils.isNotBlank(geocode)) { - geocode = geocode.toUpperCase(); - guid = null; - id = null; - } else if (StringUtils.isNotBlank(guid)) { - geocode = null; - guid = guid.toLowerCase(); - id = null; - } else if (StringUtils.isNotBlank(id)) { - geocode = null; - guid = null; - id = id.toLowerCase(); - } else { - showToast(res.getString(R.string.err_tb_details_open)); - finish(); - return; - } - } else if (uriHost.contains("coord.info")) { - String uriPath = uri.getPath().toLowerCase(); - if (uriPath != null && uriPath.startsWith("/tb")) { - geocode = uriPath.substring(1).toUpperCase(); - guid = null; - id = null; - } else { - showToast(res.getString(R.string.err_tb_details_open)); - finish(); - return; - } - } - } - - // no given data - if (geocode == null && guid == null && id == null) { - showToast(res.getString(R.string.err_tb_display)); - finish(); - return; - } - - String message; - if (StringUtils.isNotBlank(name)) { - message = Html.fromHtml(name).toString(); - } else if (StringUtils.isNotBlank(geocode)) { - message = geocode.toUpperCase(); - } else { - message = res.getString(R.string.trackable); - } - waitDialog = ProgressDialog.show(this, message, res.getString(R.string.trackable_details_loading), true, true); - - LoadTrackableThread thread = new LoadTrackableThread(loadTrackableHandler, geocode, guid, id); - thread.start(); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) { - super.onCreateContextMenu(menu, view, info); - final int viewId = view.getId(); - - if (viewId == R.id.author) { // Log item author - contextMenuUser = ((TextView) view).getText().toString(); - } else { // Trackable owner, and user holding trackable now - RelativeLayout itemLayout = (RelativeLayout) view.getParent(); - TextView itemName = (TextView) itemLayout.findViewById(R.id.name); - - String selectedName = itemName.getText().toString(); - if (selectedName.equals(res.getString(R.string.trackable_owner))) { - contextMenuUser = trackable.getOwner(); - } else if (selectedName.equals(res.getString(R.string.trackable_spotted))) { - contextMenuUser = trackable.getSpottedName(); - } - } - - menu.setHeaderTitle(res.getString(R.string.user_menu_title) + " " + contextMenuUser); - menu.add(viewId, 1, 0, res.getString(R.string.user_menu_view_hidden)); - menu.add(viewId, 2, 0, res.getString(R.string.user_menu_view_found)); - menu.add(viewId, 3, 0, res.getString(R.string.user_menu_open_browser)); - } - - @Override - public boolean onContextItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case 1: - cgeocaches.startActivityOwner(this, contextMenuUser); - return true; - case 2: - cgeocaches.startActivityUserName(this, contextMenuUser); - return true; - case 3: - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + URLEncoder.encode(contextMenuUser)))); - return true; - default: - return false; - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - menu.add(0, MENU_LOG_TOUCH, 0, res.getString(R.string.trackable_log_touch)).setIcon(R.drawable.ic_menu_agenda); // log touch - menu.add(0, MENU_BROWSER_TRACKABLE, 0, res.getString(R.string.trackable_browser_open)).setIcon(R.drawable.ic_menu_info_details); // browser - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case MENU_LOG_TOUCH: - LogTrackableActivity.startActivity(this, trackable); - return true; - case MENU_BROWSER_TRACKABLE: - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl()))); - return true; - } - return false; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - menu.findItem(MENU_LOG_TOUCH).setEnabled(StringUtils.isNotBlank(geocode) && trackable.isLoggable()); - menu.findItem(MENU_BROWSER_TRACKABLE).setEnabled(StringUtils.isNotBlank(trackable.getUrl())); - return super.onPrepareOptionsMenu(menu); - } - - private class LoadTrackableThread extends Thread { - final private Handler handler; - final private String geocode; - final private String guid; - final private String id; - - public LoadTrackableThread(Handler handlerIn, String geocodeIn, String guidIn, String idIn) { - handler = handlerIn; - geocode = geocodeIn; - guid = guidIn; - id = idIn; - } - - @Override - public void run() { - // for non TB trackables, we should just use what we have in the database - trackable = cgeoapplication.getInstance().getTrackableByGeocode(geocode); - - if ((trackable == null || trackable.isLoggable()) && !StringUtils.startsWithIgnoreCase(geocode, "GK")) { - trackable = GCParser.searchTrackable(geocode, guid, id); - } - handler.sendMessage(Message.obtain()); - } - } - - private void displayLogs() { - // trackable logs - LinearLayout listView = (LinearLayout) findViewById(R.id.log_list); - listView.removeAllViews(); - - RelativeLayout rowView; - - if (trackable != null && trackable.getLogs() != null) { - for (LogEntry log : trackable.getLogs()) { - rowView = (RelativeLayout) inflater.inflate(R.layout.trackable_logs_item, null); - - if (log.date > 0) { - ((TextView) rowView.findViewById(R.id.added)).setText(Formatter.formatShortDate(log.date)); - } - - ((TextView) rowView.findViewById(R.id.type)).setText(log.type.getL10n()); - ((TextView) rowView.findViewById(R.id.author)).setText(Html.fromHtml(log.author), TextView.BufferType.SPANNABLE); - - if (StringUtils.isBlank(log.cacheName)) { - rowView.findViewById(R.id.location).setVisibility(View.GONE); - } else { - ((TextView) rowView.findViewById(R.id.location)).setText(Html.fromHtml(log.cacheName)); - final String cacheGuid = log.cacheGuid; - final String cacheName = log.cacheName; - rowView.findViewById(R.id.location).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View arg0) { - CacheDetailActivity.startActivityGuid(cgeotrackable.this, cacheGuid, Html.fromHtml(cacheName).toString()); - } - }); - } - - TextView logView = (TextView) rowView.findViewById(R.id.log); - logView.setMovementMethod(LinkMovementMethod.getInstance()); - - String logText = log.log; - if (BaseUtils.containsHtml(logText)) { - logText = log.getDisplayText(); - logView.setText(Html.fromHtml(logText, new HtmlImage(null, false, StoredList.TEMPORARY_LIST_ID, false), null), TextView.BufferType.SPANNABLE); - } - else { - logView.setText(logText); - } - - // add LogImages - LinearLayout logLayout = (LinearLayout) rowView.findViewById(R.id.log_layout); - - if (log.hasLogImages()) { - - final ArrayList<cgImage> logImages = new ArrayList<cgImage>(log.getLogImages()); - - final View.OnClickListener listener = new View.OnClickListener() { - @Override - public void onClick(View v) { - ImagesActivity.startActivityLogImages(cgeotrackable.this, trackable.getGeocode(), logImages); - } - }; - - LinearLayout log_imgView = (LinearLayout) getLayoutInflater().inflate(R.layout.trackable_logs_img, null); - TextView log_img_title = (TextView) log_imgView.findViewById(R.id.title); - log_img_title.setText(log.getImageTitles()); - log_img_title.setOnClickListener(listener); - logLayout.addView(log_imgView); - } - - rowView.findViewById(R.id.author).setOnClickListener(new UserActionsListener()); - listView.addView(rowView); - } - - if (trackable.getLogs().size() > 0) { - findViewById(R.id.log_box).setVisibility(View.VISIBLE); - } - } - } - - private class UserActionsListener implements View.OnClickListener { - - @Override - public void onClick(View view) { - if (view == null) { - return; - } - - try { - registerForContextMenu(view); - openContextMenu(view); - } catch (Exception e) { - Log.e("cgeotrackable.UserActionsListener.onClick ", e); - } - } - } - - private class TrackableIconThread extends Thread { - final private String url; - final private Handler handler; - - public TrackableIconThread(String urlIn, Handler handlerIn) { - url = urlIn; - handler = handlerIn; - } - - @Override - public void run() { - if (url == null || handler == null) { - return; - } - - BitmapDrawable image; - try { - HtmlImage imgGetter = new HtmlImage(trackable.getGeocode(), false, 0, false); - - image = imgGetter.getDrawable(url); - Message message = handler.obtainMessage(0, image); - handler.sendMessage(message); - } catch (Exception e) { - Log.e("cgeotrackable.TrackableIconThread.run: " + e.toString()); - } - } - } - - private static class TrackableIconHandler extends Handler { - final private TextView view; - - public TrackableIconHandler(TextView viewIn) { - view = viewIn; - } - - @Override - public void handleMessage(Message message) { - final BitmapDrawable image = (BitmapDrawable) message.obj; - if (image != null && view != null) { - image.setBounds(0, 0, view.getHeight(), view.getHeight()); - view.setCompoundDrawables(image, null, null, null); - } - } - } - - public static void startActivity(final AbstractActivity fromContext, - final String guid, final String geocode, final String name) { - final Intent trackableIntent = new Intent(fromContext, cgeotrackable.class); - trackableIntent.putExtra("guid", guid); - trackableIntent.putExtra("geocode", geocode); - trackableIntent.putExtra("name", name); - fromContext.startActivity(trackableIntent); - } -} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Dummy.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java index 9c2bb8c..6a23ed5 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Dummy.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java @@ -3,9 +3,9 @@ package cgeo.geocaching.compatibility; import android.app.Activity; /** - * dummy class which has no functionality in the level 11 API + * implement level 11 API using older methods */ -public class AndroidLevel11Dummy implements AndroidLevel11Interface { +public class AndroidLevel11Emulation implements AndroidLevel11Interface { @Override public void invalidateOptionsMenu(final Activity activity) { diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java new file mode 100644 index 0000000..4eac205 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java @@ -0,0 +1,31 @@ +package cgeo.geocaching.compatibility; + +import cgeo.geocaching.cgeoapplication; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Point; +import android.view.WindowManager; + +@TargetApi(value = 13) +public class AndroidLevel13 implements AndroidLevel13Interface { + + @Override + public int getDisplayWidth() { + return getDisplaySize().x; + } + + @Override + public Point getDisplaySize() { + Point dimensions = new Point(); + ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay().getSize(dimensions); + return dimensions; + } + + @Override + public int getDisplayHeight() { + return getDisplaySize().y; + } + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java new file mode 100644 index 0000000..2257d83 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java @@ -0,0 +1,33 @@ +package cgeo.geocaching.compatibility; + +import cgeo.geocaching.cgeoapplication; + +import android.content.Context; +import android.graphics.Point; +import android.view.Display; +import android.view.WindowManager; + +@SuppressWarnings("deprecation") +public class AndroidLevel13Emulation implements AndroidLevel13Interface { + + @Override + public int getDisplayWidth() { + return getDisplay().getWidth(); + } + + @Override + public int getDisplayHeight() { + return getDisplay().getHeight(); + } + + @Override + public Point getDisplaySize() { + final Display display = getDisplay(); + return new Point(display.getWidth(), display.getHeight()); + } + + private static Display getDisplay() { + return ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay(); + } +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java new file mode 100644 index 0000000..f4e1975 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java @@ -0,0 +1,11 @@ +package cgeo.geocaching.compatibility; + +import android.graphics.Point; + +public interface AndroidLevel13Interface { + int getDisplayWidth(); + + int getDisplayHeight(); + + Point getDisplaySize(); +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java index ea5a795..a388adb 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java @@ -6,6 +6,7 @@ import android.annotation.TargetApi; import android.app.Activity; import android.app.backup.BackupManager; import android.view.Display; +import android.view.Surface; @TargetApi(8) public class AndroidLevel8 implements AndroidLevel8Interface { @@ -21,4 +22,23 @@ public class AndroidLevel8 implements AndroidLevel8Interface { Log.i("Requesting settings backup with settings manager"); BackupManager.dataChanged(name); } + + @Override + public int getRotationOffset(final Activity activity) { + try { + final int rotation = getRotation(activity); + if (rotation == Surface.ROTATION_90) { + return 90; + } else if (rotation == Surface.ROTATION_180) { + return 180; + } else if (rotation == Surface.ROTATION_270) { + return 270; + } + } catch (final Exception e) { + // This should never happen: IllegalArgumentException, IllegalAccessException or InvocationTargetException + Log.e("Cannot call getRotation()", e); + } + + return 0; + } } diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Dummy.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Dummy.java deleted file mode 100644 index d0ab911..0000000 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Dummy.java +++ /dev/null @@ -1,16 +0,0 @@ -package cgeo.geocaching.compatibility; - -import android.app.Activity; - -public class AndroidLevel8Dummy implements AndroidLevel8Interface { - - @Override - public int getRotation(final Activity activity) { - return 0; - } - - @Override - public void dataChanged(final String name) { - // do nothing - } -} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java new file mode 100644 index 0000000..197993d --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java @@ -0,0 +1,30 @@ +package cgeo.geocaching.compatibility; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.res.Configuration; +import android.view.Display; + +@TargetApi(value = 7) +public class AndroidLevel8Emulation implements AndroidLevel8Interface { + + @Override + public int getRotation(final Activity activity) { + return 0; + } + + @Override + public void dataChanged(final String name) { + // do nothing + } + + @Override + public int getRotationOffset(Activity activity) { + final Display display = activity.getWindowManager().getDefaultDisplay(); + final int rotation = display.getOrientation(); + if (rotation == Configuration.ORIENTATION_LANDSCAPE) { + return 90; + } + return 0; + } +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java index b1c4f81..761c23a 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java @@ -6,4 +6,5 @@ public interface AndroidLevel8Interface { public int getRotation(final Activity activity); public void dataChanged(final String name); + public int getRotationOffset(final Activity activity); }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java index 0821655..05a3331 100644 --- a/main/src/cgeo/geocaching/compatibility/Compatibility.java +++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java @@ -8,11 +8,9 @@ import org.apache.commons.lang3.reflect.MethodUtils; import android.app.Activity; import android.content.Intent; -import android.content.res.Configuration; +import android.graphics.Point; import android.os.Build; import android.text.InputType; -import android.view.Display; -import android.view.Surface; import android.widget.EditText; public final class Compatibility { @@ -23,19 +21,26 @@ public final class Compatibility { private final static AndroidLevel8Interface level8; private final static AndroidLevel11Interface level11; + private final static AndroidLevel13Interface level13; static { if (isLevel8) { level8 = new AndroidLevel8(); } else { - level8 = new AndroidLevel8Dummy(); + level8 = new AndroidLevel8Emulation(); } if (sdkVersion >= 11) { level11 = new AndroidLevel11(); } else { - level11 = new AndroidLevel11Dummy(); + level11 = new AndroidLevel11Emulation(); + } + if (sdkVersion >= 13) { + level13 = new AndroidLevel13(); + } + else { + level13 = new AndroidLevel13Emulation(); } } @@ -47,29 +52,7 @@ public final class Compatibility { * @return the adjusted direction, in the [0, 360[ range */ public static float getDirectionNow(final float directionNowPre, final Activity activity) { - float offset = 0; - if (isLevel8) { - try { - final int rotation = level8.getRotation(activity); - if (rotation == Surface.ROTATION_90) { - offset = 90; - } else if (rotation == Surface.ROTATION_180) { - offset = 180; - } else if (rotation == Surface.ROTATION_270) { - offset = 270; - } - } catch (final Exception e) { - // This should never happen: IllegalArgumentException, IllegalAccessException or InvocationTargetException - Log.e("Cannot call getRotation()", e); - } - } else { - final Display display = activity.getWindowManager().getDefaultDisplay(); - final int rotation = display.getOrientation(); - if (rotation == Configuration.ORIENTATION_LANDSCAPE) { - offset = 90; - } - } - return AngleUtils.normalize(directionNowPre + offset); + return AngleUtils.normalize(directionNowPre + level8.getRotationOffset(activity)); } public static void dataChanged(final String name) { @@ -113,4 +96,16 @@ public final class Compatibility { level11.invalidateOptionsMenu(activity); } + public static int getDisplayWidth() { + return level13.getDisplayWidth(); + } + + public static int getDisplayHeight() { + return level13.getDisplayHeight(); + } + + public static Point getDisplaySize() { + return level13.getDisplaySize(); + } + } diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java index 112d6cf..9604b5f 100644 --- a/main/src/cgeo/geocaching/connector/AbstractConnector.java +++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java @@ -1,8 +1,8 @@ package cgeo.geocaching.connector; -import cgeo.geocaching.SearchResult; import cgeo.geocaching.cgCache; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.enumerations.CacheRealm; +import cgeo.geocaching.geopoint.Geopoint; import org.apache.commons.lang3.StringUtils; @@ -19,6 +19,31 @@ public abstract class AbstractConnector implements IConnector { } @Override + public boolean supportsOwnCoordinates() { + return false; + } + + /** + * Uploading modified coordinates to website + * + * @param cache + * @param wpt + * @return success + */ + @Override + public boolean uploadModifiedCoordinates(cgCache cache, Geopoint wpt) { + throw new UnsupportedOperationException(); + } + + /** + * {@link IConnector} + */ + @Override + public boolean deleteModifiedCoordinates(cgCache cache) { + throw new UnsupportedOperationException(); + } + + @Override public boolean supportsFavoritePoints() { return false; } @@ -38,11 +63,6 @@ public abstract class AbstractConnector implements IConnector { return false; } - @Override - public SearchResult searchByViewport(Viewport viewport, String tokens[]) { - return null; - } - protected static boolean isNumericId(final String string) { try { return Integer.parseInt(string) > 0; @@ -81,4 +101,20 @@ public abstract class AbstractConnector implements IConnector { } abstract protected String getCacheUrlPrefix(); + + /** + * {@link IConnector} + */ + @Override + public CacheRealm getCacheRealm() { + return CacheRealm.OTHER; + } + + /** + * {@link IConnector} + */ + @Override + public boolean isActivated() { + return false; + } } diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java index bc4dcc0..6c8b7d9 100644 --- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java +++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java @@ -2,26 +2,32 @@ package cgeo.geocaching.connector; import cgeo.geocaching.ICache; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.cgTrackable; +import cgeo.geocaching.Trackable; +import cgeo.geocaching.connector.capability.ISearchByCenter; +import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.oc.OCApiConnector; import cgeo.geocaching.connector.oc.OCConnector; +import cgeo.geocaching.connector.oc.OCXMLApiConnector; import cgeo.geocaching.connector.ox.OXConnector; import cgeo.geocaching.geopoint.Viewport; import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; +import java.util.List; + public final class ConnectorFactory { private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector(); private static final IConnector[] connectors = new IConnector[] { GCConnector.getInstance(), - new OCConnector("OpenCaching.DE", "www.opencaching.de", "OC"), + new OCXMLApiConnector("OpenCaching.DE", "www.opencaching.de", "OC"), new OCConnector("OpenCaching.CZ", "www.opencaching.cz", "OZ"), new OCApiConnector("OpenCaching.CO.UK", "www.opencaching.org.uk", "OK", "arU4okouc4GEjMniE2fq"), new OCConnector("OpenCaching.ES", "www.opencachingspain.es", "OC"), new OCConnector("OpenCaching.IT", "www.opencaching.it", "OC"), new OCConnector("OpenCaching.JP", "www.opencaching.jp", "OJ"), - new OCConnector("OpenCaching.NO/SE", "www.opencaching.no", "OS"), + new OCConnector("OpenCaching.NO/SE", "www.opencaching.se", "OS"), new OCApiConnector("OpenCaching.NL", "www.opencaching.nl", "OB", "PdzU8jzIlcfMADXaYN8j"), new OCApiConnector("OpenCaching.PL", "www.opencaching.pl", "OP", "GkxM47WkUkLQXXsZ9qSh"), new OCApiConnector("OpenCaching.US", "www.opencaching.us", "OU", "pTsYAYSXFcfcRQnYE6uA"), @@ -31,10 +37,37 @@ public final class ConnectorFactory { UNKNOWN_CONNECTOR // the unknown connector MUST be the last one }; + private static final ISearchByViewPort[] searchByViewPortConns; + + private static final ISearchByCenter[] searchByCenterConns; + + static { + List<ISearchByViewPort> vpConns = new ArrayList<ISearchByViewPort>(); + for (IConnector conn : connectors) { + if (conn instanceof ISearchByViewPort) { + vpConns.add((ISearchByViewPort) conn); + } + } + searchByViewPortConns = vpConns.toArray(new ISearchByViewPort[] {}); + + List<ISearchByCenter> centerConns = new ArrayList<ISearchByCenter>(); + for (IConnector conn : connectors) { + // GCConnector is handled specially, omit it here! + if (conn instanceof ISearchByCenter && !(conn instanceof GCConnector)) { + centerConns.add((ISearchByCenter) conn); + } + } + searchByCenterConns = centerConns.toArray(new ISearchByCenter[] {}); + } + public static IConnector[] getConnectors() { return connectors; } + public static ISearchByCenter[] getSearchByCenterConnectors() { + return searchByCenterConns; + } + public static boolean canHandle(final String geocode) { if (isInvalidGeocode(geocode)) { return false; @@ -51,7 +84,7 @@ public final class ConnectorFactory { return getConnector(cache.getGeocode()); } - public static IConnector getConnector(cgTrackable trackable) { + public static IConnector getConnector(Trackable trackable) { return getConnector(trackable.getGeocode()); } @@ -74,11 +107,19 @@ public final class ConnectorFactory { return StringUtils.isBlank(geocode) || !Character.isLetterOrDigit(geocode.charAt(0)); } - /** @see IConnector#searchByViewport */ + /** @see ISearchByViewPort#searchByViewport */ public static SearchResult searchByViewport(final Viewport viewport, final String[] tokens) { - // We have only connector capable of doing a 'searchByViewport()' - // If there is a second connector the information has to be collected from all collectors - return GCConnector.getInstance().searchByViewport(viewport, tokens); + + SearchResult result = new SearchResult(); + for (ISearchByViewPort vpconn : searchByViewPortConns) { + if (vpconn.isActivated()) { + SearchResult temp = vpconn.searchByViewport(viewport, tokens); + if (temp != null) { + result.addGeocodes(temp.getGeocodes()); + } + } + } + return result; } public static String getGeocodeFromURL(final String url) { diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java index d6ac2ff..2944bed 100644 --- a/main/src/cgeo/geocaching/connector/IConnector.java +++ b/main/src/cgeo/geocaching/connector/IConnector.java @@ -1,8 +1,8 @@ package cgeo.geocaching.connector; -import cgeo.geocaching.SearchResult; import cgeo.geocaching.cgCache; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.enumerations.CacheRealm; +import cgeo.geocaching.geopoint.Geopoint; public interface IConnector { /** @@ -72,15 +72,6 @@ public interface IConnector { public boolean supportsUserActions(); /** - * Search caches by viewport. - * - * @param viewport - * @param tokens - * @return - */ - public SearchResult searchByViewport(final Viewport viewport, final String[] tokens); - - /** * return true if this is a ZIP file containing a GPX file * * @param fileName @@ -106,10 +97,48 @@ public interface IConnector { /** * extract a geocode from the given URL, if this connector can handle that URL somehow - * + * * @param url * @return */ public String getGeocodeFromUrl(final String url); + /** + * enable/disable uploading modified coordinates to website + * + * @return true, when uploading is possible + */ + public boolean supportsOwnCoordinates(); + + /** + * Uploading modified coordinates to website + * + * @param cache + * @param wpt + * @return success + */ + public boolean uploadModifiedCoordinates(cgCache cache, Geopoint wpt); + + /** + * Reseting of modified coordinates on website to details + * + * @param cache + * @return success + */ + public boolean deleteModifiedCoordinates(cgCache cache); + + /** + * The CacheRealm this cache belongs to + * + * @return + */ + public CacheRealm getCacheRealm(); + + /** + * Return true if this connector is activated for online + * interaction (download details, do searches, ...) + * + * @return + */ + public boolean isActivated(); } diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java index 62645c2..3fdd61f 100644 --- a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java +++ b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java @@ -10,4 +10,5 @@ import cgeo.geocaching.geopoint.Geopoint; public interface ISearchByCenter { public SearchResult searchByCenter(final Geopoint center); + public boolean isActivated(); } diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java index 316cf00..f1bd2ce 100644 --- a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java +++ b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java @@ -5,4 +5,6 @@ import cgeo.geocaching.geopoint.Viewport; public interface ISearchByViewPort { public SearchResult searchByViewport(final Viewport viewport, final String[] tokens); + + public boolean isActivated(); } diff --git a/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java index d0e45f6..f19064d 100644 --- a/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java +++ b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java @@ -12,7 +12,7 @@ abstract public class AbstractSearchThread extends Thread { private final Handler handler; private static AbstractSearchThread currentInstance; - public AbstractSearchThread(final Handler handler) { + protected AbstractSearchThread(final Handler handler) { this.handler = handler; } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index 197d4e6..8943835 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -3,10 +3,12 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.connector.capability.ISearchByCenter; import cgeo.geocaching.connector.capability.ISearchByGeocode; +import cgeo.geocaching.connector.capability.ISearchByViewPort; +import cgeo.geocaching.enumerations.CacheRealm; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.Viewport; @@ -18,21 +20,24 @@ import org.apache.commons.lang3.StringUtils; import java.util.regex.Pattern; -public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter { +public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort { private static final String HTTP_COORD_INFO = "http://coord.info/"; - private static GCConnector instance; private static final Pattern gpxZipFilePattern = Pattern.compile("\\d{7,}(_.+)?\\.zip", Pattern.CASE_INSENSITIVE); private GCConnector() { // singleton } + /** + * initialization on demand holder pattern + */ + private static class Holder { + private static final GCConnector INSTANCE = new GCConnector(); + } + public static GCConnector getInstance() { - if (instance == null) { - instance = new GCConnector(); - } - return instance; + return Holder.INSTANCE; } @Override @@ -50,6 +55,11 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override + public boolean supportsOwnCoordinates() { + return true; + } + + @Override public boolean supportsWatchList() { return true; } @@ -83,11 +93,10 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, if (StringUtils.isEmpty(page)) { final SearchResult search = new SearchResult(); - if (cgeoapplication.getInstance().isThere(geocode, guid, true, false)) { + if (cgData.isThere(geocode, guid, true, false)) { if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(guid)) { Log.i("Loading old cache from cache."); - - search.addGeocode(cgeoapplication.getInstance().getGeocode(guid)); + search.addGeocode(cgData.getGeocodeForGuid(guid)); } else { search.addGeocode(geocode); } @@ -103,7 +112,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, final SearchResult searchResult = GCParser.parseCache(page, handler); if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) { - Log.e("GCConnector.searchByGeocode: No cache parsed"); + Log.w("GCConnector.searchByGeocode: No cache parsed"); return searchResult; } @@ -129,7 +138,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, public static boolean addToWatchlist(cgCache cache) { final boolean added = GCParser.addToWatchlist(cache); if (added) { - cgeoapplication.getInstance().updateCache(cache); + cgData.saveChangedCache(cache); } return added; } @@ -137,28 +146,64 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, public static boolean removeFromWatchlist(cgCache cache) { final boolean removed = GCParser.removeFromWatchlist(cache); if (removed) { - cgeoapplication.getInstance().updateCache(cache); + cgData.saveChangedCache(cache); } return removed; } + /** + * Add a cache to the favorites list. + * + * This must not be called from the UI thread. + * + * @param cache the cache to add + * @return <code>true</code> if the cache was sucessfully added, <code>false</code> otherwise + */ + public static boolean addToFavorites(cgCache cache) { final boolean added = GCParser.addToFavorites(cache); if (added) { - cgeoapplication.getInstance().updateCache(cache); + cgData.saveChangedCache(cache); } return added; } + /** + * Remove a cache from the favorites list. + * + * This must not be called from the UI thread. + * + * @param cache the cache to add + * @return <code>true</code> if the cache was sucessfully added, <code>false</code> otherwise + */ + public static boolean removeFromFavorites(cgCache cache) { final boolean removed = GCParser.removeFromFavorites(cache); if (removed) { - cgeoapplication.getInstance().updateCache(cache); + cgData.saveChangedCache(cache); } return removed; } @Override + public boolean uploadModifiedCoordinates(cgCache cache, Geopoint wpt) { + final boolean uploaded = GCParser.uploadModifiedCoordinates(cache, wpt); + if (uploaded) { + cgData.saveChangedCache(cache); + } + return uploaded; + } + + @Override + public boolean deleteModifiedCoordinates(cgCache cache) { + final boolean deleted = GCParser.deleteModifiedCoordinates(cache); + if (deleted) { + cgData.saveChangedCache(cache); + } + return deleted; + } + + @Override public SearchResult searchByCenter(Geopoint center) { // TODO make search by coordinate use this method. currently it is just a marker that this connector supports search by center return null; @@ -173,4 +218,14 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, protected String getCacheUrlPrefix() { return HTTP_COORD_INFO; } + + @Override + public CacheRealm getCacheRealm() { + return CacheRealm.GC; + } + + @Override + public boolean isActivated() { + return true; + } } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java index 2b4ca46..282c88c 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java @@ -1,5 +1,6 @@ package cgeo.geocaching.connector.gc; +import java.util.Locale; import java.util.regex.Pattern; /** @@ -49,7 +50,7 @@ public final class GCConstants { public final static Pattern PATTERN_FAVORITE = Pattern.compile("<div id=\"pnlFavoriteCache\">"); // without 'class="hideMe"' inside the tag ! public final static Pattern PATTERN_FAVORITECOUNT = Pattern.compile("<a id=\"uxFavContainerLink\"[^>]+>[^<]*<div[^<]*<span class=\"favorite-value\">\\D*([0-9]+?)</span>"); public final static Pattern PATTERN_COUNTLOGS = Pattern.compile("<span id=\"ctl00_ContentBody_lblFindCounts\"><p(.+?)</p></span>"); - public final static Pattern PATTERN_LOGBOOK = Pattern.compile("initalLogs = (\\{.+\\});"); + public final static Pattern PATTERN_LOGBOOK = Pattern.compile("initalLogs = (\\{.+\\});"); // The "inital" typo really comes from gc.com site /** Two groups ! */ public final static Pattern PATTERN_COUNTLOG = Pattern.compile("<img src=\"/images/logtypes/([0-9]+)\\.png\"[^>]+> (\\d*[,.]?\\d+)"); public static final Pattern PATTERN_PREMIUMMEMBERS = Pattern.compile("<p class=\"Warning NoBottomSpacing\">This is a Premium Member Only cache.</p>"); @@ -103,7 +104,7 @@ public final class GCConstants { public final static Pattern PATTERN_TRACKABLE_ICON = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"([^\"]+)\"[^>]*>"); public final static Pattern PATTERN_TRACKABLE_TYPE = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"[^\"]+\" alt=\"([^\"]+)\"[^>]*>"); public final static Pattern PATTERN_TRACKABLE_DISTANCE = Pattern.compile("<h4[^>]*\\W*Tracking History \\(([0-9.,]+(km|mi))[^\\)]*\\)"); - public final static Pattern PATTERN_TRACKABLE_LOG = Pattern.compile("<tr class=\"Data BorderTop .+?src=\"/images/logtypes/([^.]+)\\.png[^>]+> ([^<]+)</td>.+?guid.+?>([^<]+)</a>.+?(?:guid=([^\"]+)\">(<span[^>]+>)?([^<]+)</.+?)?<td colspan=\"4\">(.+?)(?:<ul.+?ul>)?\\s*</td>\\s*</tr>"); + public final static Pattern PATTERN_TRACKABLE_LOG = Pattern.compile("<tr class=\"Data BorderTop .+?src=\"/images/logtypes/([^.]+)\\.png[^>]+> ([^<]+)</td>.+?guid.+?>([^<]+)</a>.+?(?:guid=([^\"]+)\">(<span[^>]+>)?([^<]+)</.+?)?<td colspan=\"4\">\\s*<div>(.*?)</div>\\s*(?:<ul.+?ul>)?\\s*</td>\\s*</tr>"); public final static Pattern PATTERN_TRACKABLE_LOG_IMAGES = Pattern.compile("<li><a href=\"([^\"]+)\".+?LogImgTitle.+?>([^<]+)</"); /** @@ -164,8 +165,9 @@ public final class GCConstants { public final static String STRING_PREMIUMONLY_2 = "Sorry, the owner of this listing has made it viewable to Premium Members only."; public final static String STRING_PREMIUMONLY_1 = "has chosen to make this cache listing visible to Premium Members only."; - public final static String STRING_UNPUBLISHED_OWNER = "Cache is Unpublished"; + public final static String STRING_UNPUBLISHED_OWNER = "cache has not been published yet"; public final static String STRING_UNPUBLISHED_OTHER = "you cannot view this cache listing until it has been published"; + public final static String STRING_UNPUBLISHED_FROM_SEARCH = "UnpublishedCacheSearchWidget"; public final static String STRING_UNKNOWN_ERROR = "An Error Has Occurred"; public final static String STRING_DISABLED = "<li>This cache is temporarily unavailable."; public final static String STRING_ARCHIVED = "<li>This cache has been archived,"; @@ -185,14 +187,14 @@ public final class GCConstants { * see http://support.groundspeak.com/index.php?pg=kb.printer.friendly&id=1#p221 */ public static long gccodeToGCId(final String gccode) { - long gcid = 0; long base = GC_BASE31; - String geocodeWO = gccode.substring(2).toUpperCase(); + String geocodeWO = gccode.substring(2).toUpperCase(Locale.US); if ((geocodeWO.length() < 4) || (geocodeWO.length() == 4 && SEQUENCE_GCID.indexOf(geocodeWO.charAt(0)) < 16)) { base = GC_BASE16; } + long gcid = 0; for (int p = 0; p < geocodeWO.length(); p++) { gcid = base * gcid + SEQUENCE_GCID.indexOf(geocodeWO.charAt(p)); } diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java index 681a1d7..9a8123d 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCMap.java +++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java @@ -3,6 +3,7 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; @@ -40,10 +41,10 @@ public class GCMap { final SearchResult result = new SearchResult(); final String geocodeList = StringUtils.join(geocodes.toArray(), "|"); - final String referer = GCConstants.URL_LIVE_MAP_DETAILS; try { final Parameters params = new Parameters("i", geocodeList, "_", String.valueOf(System.currentTimeMillis())); + final String referer = GCConstants.URL_LIVE_MAP_DETAILS; final String data = StringUtils.defaultString(Tile.requestMapInfo(referer, params, referer)); // Example JSON information @@ -166,6 +167,8 @@ public class GCMap { // iterate over the data and construct all caches in this tile Map<String, List<UTFGridPosition>> positions = new HashMap<String, List<UTFGridPosition>>(); // JSON id as key + Map<String, List<UTFGridPosition>> singlePositions = new HashMap<String, List<UTFGridPosition>>(); // JSON id as key + for (int i = 1; i < keys.length(); i++) { // index 0 is empty String key = keys.getString(i); if (StringUtils.isNotBlank(key)) { @@ -177,12 +180,20 @@ public class GCMap { nameCache.put(id, cacheInfo.getString("n")); List<UTFGridPosition> listOfPositions = positions.get(id); + List<UTFGridPosition> singleListOfPositions = singlePositions.get(id); + if (listOfPositions == null) { listOfPositions = new ArrayList<UTFGridPosition>(); positions.put(id, listOfPositions); + singleListOfPositions = new ArrayList<UTFGridPosition>(); + singlePositions.put(id, singleListOfPositions); } listOfPositions.add(pos); + if (dataForKey.length() == 1) { + singleListOfPositions.add(pos); + } + } } } @@ -198,12 +209,16 @@ public class GCMap { cache.setName(nameCache.get(id)); cache.setZoomlevel(tile.getZoomlevel()); cache.setCoords(tile.getCoord(xy)); - if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && positions.size() < 64 && bitmap != null) { - // don't parse if there are too many caches. The decoding would return too much wrong results - IconDecoder.parseMapPNG(cache, bitmap, xy, tile.getZoomlevel()); + if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && bitmap != null) { + for (UTFGridPosition singlePos : singlePositions.get(id)) { + if (IconDecoder.parseMapPNG(cache, bitmap, singlePos, tile.getZoomlevel())) { + break; // cache parsed + } + } } else { cache.setType(CacheType.UNKNOWN); } + boolean exclude = false; if (Settings.isExcludeMyCaches() && (cache.isFound() || cache.isOwn())) { // workaround for BM exclude = true; @@ -313,7 +328,7 @@ public class GCMap { String data = Tile.requestMapInfo(GCConstants.URL_MAP_INFO, params, GCConstants.URL_LIVE_MAP); if (StringUtils.isEmpty(data)) { - Log.e("GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")"); + Log.w("GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")"); } else { final SearchResult search = GCMap.parseMapJSON(data, tile, bitmap, strategy); if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) { @@ -341,7 +356,7 @@ public class GCMap { if (search != null && !search.isEmpty()) { final Set<String> geocodes = search.getGeocodes(); if (Settings.isPremiumMember()) { - lastSearchViewport = cgeoapplication.getInstance().getBounds(geocodes); + lastSearchViewport = cgData.getBounds(geocodes); } else { lastSearchViewport = new Viewport(center, center); } diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index 158a201..274ba0d 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -4,11 +4,12 @@ import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; +import cgeo.geocaching.Trackable; import cgeo.geocaching.TrackableLog; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgImage; -import cgeo.geocaching.cgTrackable; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.cgData; +import cgeo.geocaching.Image; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; @@ -30,6 +31,7 @@ import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.LazyInitializedList; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import ch.boye.httpclientandroidlib.HttpResponse; @@ -43,12 +45,7 @@ import org.json.JSONObject; import android.net.Uri; import android.text.Html; -import android.text.Spannable; -import android.text.Spanned; -import android.text.style.ForegroundColorSpan; -import android.text.style.StrikethroughSpan; -import java.net.URLDecoder; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -58,7 +55,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Set; -import java.util.regex.Matcher; public abstract class GCParser { private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009 @@ -71,8 +67,6 @@ public abstract class GCParser { } final List<String> cids = new ArrayList<String>(); - String recaptchaChallenge = null; - String recaptchaText = null; String page = pageContent; final SearchResult searchResult = new SearchResult(); @@ -81,6 +75,7 @@ public abstract class GCParser { // recaptcha AbstractSearchThread thread = AbstractSearchThread.getCurrentInstance(); + String recaptchaChallenge = null; if (showCaptcha) { String recaptchaJsParam = BaseUtils.getMatch(page, GCConstants.PATTERN_SEARCH_RECAPTCHA, false, null); @@ -133,7 +128,7 @@ public abstract class GCParser { } try { - final Matcher matcherGuidAndDisabled = GCConstants.PATTERN_SEARCH_GUIDANDDISABLED.matcher(row); + final MatcherWrapper matcherGuidAndDisabled = new MatcherWrapper(GCConstants.PATTERN_SEARCH_GUIDANDDISABLED, row); while (matcherGuidAndDisabled.find()) { if (matcherGuidAndDisabled.groupCount() > 0) { @@ -163,29 +158,32 @@ public abstract class GCParser { continue; } - String inventoryPre = null; - - cache.setGeocode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true).toUpperCase()); + cache.setGeocode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true)); // cache type cache.setType(CacheType.getByPattern(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, true, 1, null, true))); // cache direction - image if (Settings.getLoadDirImg()) { - cache.setDirectionImg(URLDecoder.decode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION, true, 1, cache.getDirectionImg(), true))); + cache.setDirectionImg(Network.decode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION, true, 1, cache.getDirectionImg(), true))); } // cache inventory - final Matcher matcherTbs = GCConstants.PATTERN_SEARCH_TRACKABLES.matcher(row); + final MatcherWrapper matcherTbs = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLES, row); + String inventoryPre = null; while (matcherTbs.find()) { if (matcherTbs.groupCount() > 0) { - cache.setInventoryItems(Integer.parseInt(matcherTbs.group(1))); + try { + cache.setInventoryItems(Integer.parseInt(matcherTbs.group(1))); + } catch (NumberFormatException e) { + Log.e("Error parsing trackables count", e); + } inventoryPre = matcherTbs.group(2); } } if (StringUtils.isNotBlank(inventoryPre)) { - final Matcher matcherTbsInside = GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE.matcher(inventoryPre); + final MatcherWrapper matcherTbsInside = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE, inventoryPre); while (matcherTbsInside.find()) { if (matcherTbsInside.groupCount() == 2 && matcherTbsInside.group(2) != null && @@ -222,16 +220,6 @@ public abstract class GCParser { Log.w("GCParser.parseSearch: Failed to parse favourite count"); } - if (cache.getNameSp() == null) { - cache.setNameSp((new Spannable.Factory()).newSpannable(cache.getName())); - if (cache.isDisabled() || cache.isArchived()) { // strike - cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - if (cache.isArchived()) { - cache.getNameSp().setSpan(new ForegroundColorSpan(cgeoapplication.getInstance().getResources().getColor(R.color.archived_cache_color)), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - searchResult.addCache(cache); } @@ -245,6 +233,7 @@ public abstract class GCParser { Log.w("GCParser.parseSearch: Failed to parse cache count"); } + String recaptchaText = null; if (thread != null && recaptchaChallenge != null) { if (thread.getText() == null) { thread.waitForUser(); @@ -253,7 +242,7 @@ public abstract class GCParser { recaptchaText = thread.getText(); } - if (cids.size() > 0 && (Settings.isPremiumMember() || showCaptcha) && (recaptchaChallenge == null || StringUtils.isNotBlank(recaptchaText))) { + if (!cids.isEmpty() && (Settings.isPremiumMember() || showCaptcha) && (recaptchaChallenge == null || StringUtils.isNotBlank(recaptchaText))) { Log.i("Trying to get .loc for " + cids.size() + " caches"); try { @@ -295,7 +284,7 @@ public abstract class GCParser { LocParser.parseLoc(searchResult, coordinates); } catch (Exception e) { - Log.e("GCParser.parseSearch.CIDs: " + e.toString()); + Log.e("GCParser.parseSearch.CIDs", e); } } @@ -317,16 +306,14 @@ public abstract class GCParser { if (searchResult != null && !searchResult.getGeocodes().isEmpty()) { final cgCache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); getExtraOnlineInfo(cache, page, handler); - cache.setUpdated(System.currentTimeMillis()); - cache.setDetailedUpdate(cache.getUpdated()); - cache.setDetailed(true); + cache.setDetailedUpdatedNow(); if (CancellableHandler.isCancelled(handler)) { return null; } // save full detailed caches CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_cache); - cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); // update progress message so user knows we're still working. This is more of a place holder than // actual indication of what the program is doing @@ -345,7 +332,7 @@ public abstract class GCParser { final SearchResult searchResult = new SearchResult(); - if (page.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || page.contains(GCConstants.STRING_UNPUBLISHED_OWNER)) { + if (page.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || page.contains(GCConstants.STRING_UNPUBLISHED_OWNER) || page.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) { searchResult.setError(StatusCode.UNPUBLISHED_CACHE); return searchResult; } @@ -383,10 +370,12 @@ public abstract class GCParser { cache.setName(cacheName); // owner real name - cache.setOwnerUserId(URLDecoder.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId()))); + cache.setOwnerUserId(Network.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId()))); cache.setOwn(StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), Settings.getUsername())); + cache.setUserModifiedCoords(false); + String tableInside = page; int pos = tableInside.indexOf(GCConstants.STRING_CACHEDETAILS); @@ -401,13 +390,21 @@ public abstract class GCParser { // cache terrain String result = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_TERRAIN, true, null); if (result != null) { - cache.setTerrain(Float.parseFloat(StringUtils.replaceChars(result, '_', '.'))); + try { + cache.setTerrain(Float.parseFloat(StringUtils.replaceChars(result, '_', '.'))); + } catch (NumberFormatException e) { + Log.e("Error parsing terrain value", e); + } } // cache difficulty result = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_DIFFICULTY, true, null); if (result != null) { - cache.setDifficulty(Float.parseFloat(StringUtils.replaceChars(result, '_', '.'))); + try { + cache.setDifficulty(Float.parseFloat(StringUtils.replaceChars(result, '_', '.'))); + } catch (NumberFormatException e) { + Log.e("Error parsing difficulty value", e); + } } // owner @@ -432,10 +429,14 @@ public abstract class GCParser { } // favourite - cache.setFavoritePoints(Integer.parseInt(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0"))); + try { + cache.setFavoritePoints(Integer.parseInt(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0"))); + } catch (NumberFormatException e) { + Log.e("Error parsing favourite count", e); + } // cache size - cache.setSize(CacheSize.getById(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_SIZE, true, CacheSize.NOT_CHOSEN.id).toLowerCase())); + cache.setSize(CacheSize.getById(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_SIZE, true, CacheSize.NOT_CHOSEN.id))); } // cache found @@ -465,7 +466,7 @@ public abstract class GCParser { cache.setCoords(new Geopoint(cache.getLatlon())); cache.setReliableLatLon(true); } catch (Geopoint.GeopointException e) { - Log.w("GCParser.parseCache: Failed to parse cache coordinates: " + e.toString()); + Log.w("GCParser.parseCache: Failed to parse cache coordinates", e); } } @@ -497,21 +498,21 @@ public abstract class GCParser { try { final String attributesPre = BaseUtils.getMatch(page, GCConstants.PATTERN_ATTRIBUTES, true, null); if (null != attributesPre) { - final Matcher matcherAttributesInside = GCConstants.PATTERN_ATTRIBUTESINSIDE.matcher(attributesPre); + final MatcherWrapper matcherAttributesInside = new MatcherWrapper(GCConstants.PATTERN_ATTRIBUTESINSIDE, attributesPre); final ArrayList<String> attributes = new ArrayList<String>(); while (matcherAttributesInside.find()) { if (matcherAttributesInside.groupCount() > 1 && !matcherAttributesInside.group(2).equalsIgnoreCase("blank")) { // by default, use the tooltip of the attribute - String attribute = matcherAttributesInside.group(2).toLowerCase(); + String attribute = matcherAttributesInside.group(2).toLowerCase(Locale.US); // if the image name can be recognized, use the image name as attribute - String imageName = matcherAttributesInside.group(1).trim(); - if (imageName.length() > 0) { + final String imageName = matcherAttributesInside.group(1).trim(); + if (StringUtils.isNotEmpty(imageName)) { int start = imageName.lastIndexOf('/'); int end = imageName.lastIndexOf('.'); if (start >= 0 && end >= 0) { - attribute = imageName.substring(start + 1, end).replace('-', '_').toLowerCase(); + attribute = imageName.substring(start + 1, end).replace('-', '_').toLowerCase(Locale.US); } } attributes.add(attribute); @@ -531,26 +532,22 @@ public abstract class GCParser { } CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers); - final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILER_IMAGE.matcher(page); + final MatcherWrapper matcherSpoilersInside = new MatcherWrapper(GCConstants.PATTERN_SPOILER_IMAGE, page); while (matcherSpoilersInside.find()) { // the original spoiler URL (include .../display/... contains a low-resolution image // if we shorten the URL we get the original-resolution image - // - // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch()) - String url = new String(matcherSpoilersInside.group(1).replace("/display", "")); + String url = matcherSpoilersInside.group(1).replace("/display", ""); String title = null; if (matcherSpoilersInside.group(3) != null) { - // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch()) - title = new String(matcherSpoilersInside.group(3)); + title = matcherSpoilersInside.group(3); } String description = null; if (matcherSpoilersInside.group(4) != null) { - // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch()) - description = new String(matcherSpoilersInside.group(4)); + description = matcherSpoilersInside.group(4); } - cache.addSpoiler(new cgImage(url, title, description)); + cache.addSpoiler(new Image(url, title, description)); } } catch (Exception e) { // failed to parse cache spoilers @@ -561,25 +558,23 @@ public abstract class GCParser { try { cache.setInventoryItems(0); - final Matcher matcherInventory = GCConstants.PATTERN_INVENTORY.matcher(page); + final MatcherWrapper matcherInventory = new MatcherWrapper(GCConstants.PATTERN_INVENTORY, page); if (matcherInventory.find()) { if (cache.getInventory() == null) { - cache.setInventory(new ArrayList<cgTrackable>()); + cache.setInventory(new ArrayList<Trackable>()); } if (matcherInventory.groupCount() > 1) { final String inventoryPre = matcherInventory.group(2); if (StringUtils.isNotBlank(inventoryPre)) { - final Matcher matcherInventoryInside = GCConstants.PATTERN_INVENTORYINSIDE.matcher(inventoryPre); + final MatcherWrapper matcherInventoryInside = new MatcherWrapper(GCConstants.PATTERN_INVENTORYINSIDE, inventoryPre); while (matcherInventoryInside.find()) { if (matcherInventoryInside.groupCount() > 0) { - final cgTrackable inventoryItem = new cgTrackable(); - // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch()) - inventoryItem.setGuid(new String(matcherInventoryInside.group(1))); - // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch()) - inventoryItem.setName(new String(matcherInventoryInside.group(2))); + final Trackable inventoryItem = new Trackable(); + inventoryItem.setGuid(matcherInventoryInside.group(1)); + inventoryItem.setName(matcherInventoryInside.group(2)); cache.getInventory().add(inventoryItem); cache.setInventoryItems(cache.getInventoryItems() + 1); @@ -594,14 +589,12 @@ public abstract class GCParser { } // cache logs counts - try - { + try { final String countlogs = BaseUtils.getMatch(page, GCConstants.PATTERN_COUNTLOGS, true, null); if (null != countlogs) { - final Matcher matcherLog = GCConstants.PATTERN_COUNTLOG.matcher(countlogs); + final MatcherWrapper matcherLog = new MatcherWrapper(GCConstants.PATTERN_COUNTLOG, countlogs); - while (matcherLog.find()) - { + while (matcherLog.find()) { String typeStr = matcherLog.group(1); String countStr = matcherLog.group(2).replaceAll("[.,]", ""); @@ -612,21 +605,20 @@ public abstract class GCParser { } } } - } catch (Exception e) - { + } catch (Exception e) { // failed to parse logs Log.w("GCParser.parseCache: Failed to parse cache log count"); } // waypoints - reset collection - cache.setWaypoints(Collections.<cgWaypoint> emptyList(), false); + cache.setWaypoints(Collections.<Waypoint> emptyList(), false); // add waypoint for original coordinates in case of user-modified listing-coordinates try { final String originalCoords = BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null); if (null != originalCoords) { - final cgWaypoint waypoint = new cgWaypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.WAYPOINT, false); + final Waypoint waypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false); waypoint.setCoords(new Geopoint(originalCoords)); cache.addOrChangeWaypoint(waypoint, false); cache.setUserModifiedCoords(true); @@ -634,10 +626,7 @@ public abstract class GCParser { } catch (Geopoint.GeopointException e) { } - int wpBegin; - int wpEnd; - - wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">"); + int wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">"); if (wpBegin != -1) { // parse waypoints if (CancellableHandler.isCancelled(handler)) { return null; @@ -646,7 +635,7 @@ public abstract class GCParser { String wpList = page.substring(wpBegin); - wpEnd = wpList.indexOf("</p>"); + int wpEnd = wpList.indexOf("</p>"); if (wpEnd > -1 && wpEnd <= wpList.length()) { wpList = wpList.substring(0, wpEnd); } @@ -663,9 +652,8 @@ public abstract class GCParser { final String[] wpItems = wpList.split("<tr"); - String[] wp; for (int j = 1; j < wpItems.length; j++) { - wp = wpItems[j].split("<td"); + String[] wp = wpItems[j].split("<td"); // waypoint name // res is null during the unit tests @@ -674,7 +662,7 @@ public abstract class GCParser { // waypoint type final String resulttype = BaseUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null); - final cgWaypoint waypoint = new cgWaypoint(name, WaypointType.findById(resulttype), false); + final Waypoint waypoint = new Waypoint(name, WaypointType.findById(resulttype), false); // waypoint prefix waypoint.setPrefix(BaseUtils.getMatch(wp[4], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getPrefix(), false)); @@ -756,7 +744,7 @@ public abstract class GCParser { final SearchResult searchResult = parseSearch(url, page, showCaptcha); if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) { - Log.e("GCParser.searchByNextPage: No cache parsed"); + Log.w("GCParser.searchByNextPage: No cache parsed"); return search; } @@ -896,13 +884,13 @@ public abstract class GCParser { return null; } - public static cgTrackable searchTrackable(final String geocode, final String guid, final String id) { + public static Trackable searchTrackable(final String geocode, final String guid, final String id) { if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid) && StringUtils.isBlank(id)) { Log.w("GCParser.searchTrackable: No geocode nor guid nor id given"); return null; } - cgTrackable trackable = new cgTrackable(); + Trackable trackable = new Trackable(); final Parameters params = new Parameters(); if (StringUtils.isNotBlank(geocode)) { @@ -923,7 +911,7 @@ public abstract class GCParser { trackable = parseTrackable(page, geocode); if (trackable == null) { - Log.e("GCParser.searchTrackable: No trackable parsed"); + Log.w("GCParser.searchTrackable: No trackable parsed"); return null; } @@ -1004,7 +992,7 @@ public abstract class GCParser { // maintenance, archived needs to be confirmed - final Matcher matcher = GCConstants.PATTERN_MAINTENANCE.matcher(page); + final MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_MAINTENANCE, page); try { if (matcher.find() && matcher.groupCount() > 0) { @@ -1048,17 +1036,17 @@ public abstract class GCParser { page = Network.getResponseData(Network.postRequest(uri, params)); } } catch (Exception e) { - Log.e("GCParser.postLog.confim: " + e.toString()); + Log.e("GCParser.postLog.confim", e); } try { - final Matcher matcherOk = GCConstants.PATTERN_OK1.matcher(page); + final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK1, page); if (matcherOk.find()) { Log.i("Log successfully posted to cache #" + cacheid); if (geocode != null) { - cgeoapplication.getInstance().saveVisitDate(geocode); + cgData.saveVisitDate(geocode); } Login.getLoginStatus(page); @@ -1069,7 +1057,7 @@ public abstract class GCParser { return StatusCode.NO_ERROR; } } catch (Exception e) { - Log.e("GCParser.postLog.check: " + e.toString()); + Log.e("GCParser.postLog.check", e); } Log.e("GCParser.postLog: Failed to post log because of unknown error"); @@ -1122,13 +1110,13 @@ public abstract class GCParser { try { - final Matcher matcherOk = GCConstants.PATTERN_OK2.matcher(page); + final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK2, page); if (matcherOk.find()) { Log.i("Log successfully posted to trackable #" + trackingCode); return StatusCode.NO_ERROR; } } catch (Exception e) { - Log.e("GCParser.postLogTrackable.check: " + e.toString()); + Log.e("GCParser.postLogTrackable.check", e); } Log.e("GCParser.postLogTrackable: Failed to post log because of unknown error"); @@ -1211,6 +1199,8 @@ public abstract class GCParser { /** * Adds the cache to the favorites of the user. * + * This must not be called from the UI thread. + * * @param cache * the cache to add * @return <code>false</code> if an error occurred, <code>true</code> otherwise @@ -1241,7 +1231,9 @@ public abstract class GCParser { } /** - * Removes the cache from the Favorites + * Removes the cache from the favorites. + * + * This must not be called from the UI thread. * * @param cache * the cache to remove @@ -1252,15 +1244,13 @@ public abstract class GCParser { } /** - * Parse a trackable HTML description into a cgTrackable object + * Parse a trackable HTML description into a Trackable object * * @param page * the HTML page to parse, already processed through {@link BaseUtils#replaceWhitespace} - * @param app - * if not null, the application to use to save the trackable * @return the parsed trackable, or null if none could be parsed */ - static cgTrackable parseTrackable(final String page, final String possibleTrackingcode) { + static Trackable parseTrackable(final String page, final String possibleTrackingcode) { if (StringUtils.isBlank(page)) { Log.e("GCParser.parseTrackable: No page given"); return null; @@ -1270,10 +1260,10 @@ public abstract class GCParser { return null; } - final cgTrackable trackable = new cgTrackable(); + final Trackable trackable = new Trackable(); // trackable geocode - trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()).toUpperCase()); + trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode())); // trackable id trackable.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid())); @@ -1291,7 +1281,7 @@ public abstract class GCParser { // trackable owner name try { - final Matcher matcherOwner = GCConstants.PATTERN_TRACKABLE_OWNER.matcher(page); + final MatcherWrapper matcherOwner = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_OWNER, page); if (matcherOwner.find() && matcherOwner.groupCount() > 0) { trackable.setOwnerGuid(matcherOwner.group(1)); trackable.setOwner(matcherOwner.group(2).trim()); @@ -1306,26 +1296,26 @@ public abstract class GCParser { // trackable spotted try { - final Matcher matcherSpottedCache = GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE.matcher(page); + final MatcherWrapper matcherSpottedCache = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE, page); if (matcherSpottedCache.find() && matcherSpottedCache.groupCount() > 0) { trackable.setSpottedGuid(matcherSpottedCache.group(1)); trackable.setSpottedName(matcherSpottedCache.group(2).trim()); - trackable.setSpottedType(cgTrackable.SPOTTED_CACHE); + trackable.setSpottedType(Trackable.SPOTTED_CACHE); } - final Matcher matcherSpottedUser = GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER.matcher(page); + final MatcherWrapper matcherSpottedUser = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER, page); if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) { trackable.setSpottedGuid(matcherSpottedUser.group(1)); trackable.setSpottedName(matcherSpottedUser.group(2).trim()); - trackable.setSpottedType(cgTrackable.SPOTTED_USER); + trackable.setSpottedType(Trackable.SPOTTED_USER); } if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) { - trackable.setSpottedType(cgTrackable.SPOTTED_UNKNOWN); + trackable.setSpottedType(Trackable.SPOTTED_UNKNOWN); } if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) { - trackable.setSpottedType(cgTrackable.SPOTTED_OWNER); + trackable.setSpottedType(Trackable.SPOTTED_OWNER); } } catch (Exception e) { // failed to parse trackable last known place @@ -1356,7 +1346,7 @@ public abstract class GCParser { // trackable details & image try { - final Matcher matcherDetailsImage = GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE.matcher(page); + final MatcherWrapper matcherDetailsImage = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE, page); if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) { final String image = StringUtils.trim(matcherDetailsImage.group(3)); final String details = StringUtils.trim(matcherDetailsImage.group(4)); @@ -1375,7 +1365,7 @@ public abstract class GCParser { // trackable logs try { - final Matcher matcherLogs = GCConstants.PATTERN_TRACKABLE_LOG.matcher(page); + final MatcherWrapper matcherLogs = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG, page); /* * 1. Type (image) * 2. Date @@ -1404,13 +1394,14 @@ public abstract class GCParser { } // Apply the pattern for images in a trackable log entry against each full log (group(0)) - final Matcher matcherLogImages = GCConstants.PATTERN_TRACKABLE_LOG_IMAGES.matcher(matcherLogs.group(0)); + final String logEntry = matcherLogs.group(0); + final MatcherWrapper matcherLogImages = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG_IMAGES, logEntry); /* * 1. Image URL * 2. Image title */ while (matcherLogImages.find()) { - final cgImage logImage = new cgImage(matcherLogImages.group(1), matcherLogImages.group(2)); + final Image logImage = new Image(matcherLogImages.group(1), matcherLogImages.group(2)); logDone.addLogImage(logImage); } @@ -1418,7 +1409,7 @@ public abstract class GCParser { } } catch (Exception e) { // failed to parse logs - Log.w("GCParser.parseCache: Failed to parse cache logs" + e.toString()); + Log.w("GCParser.parseCache: Failed to parse cache logs", e); } // tracking code @@ -1427,7 +1418,7 @@ public abstract class GCParser { } if (cgeoapplication.getInstance() != null) { - cgeoapplication.getInstance().saveTrackable(trackable); + cgData.saveTrackable(trackable); } return trackable; @@ -1454,7 +1445,7 @@ public abstract class GCParser { String rawResponse; if (!getDataFromPage) { - final Matcher userTokenMatcher = GCConstants.PATTERN_USERTOKEN.matcher(page); + final MatcherWrapper userTokenMatcher = new MatcherWrapper(GCConstants.PATTERN_USERTOKEN, page); if (!userTokenMatcher.find()) { Log.e("GCParser.loadLogsFromDetails: unable to extract userToken"); return null; @@ -1532,7 +1523,7 @@ public abstract class GCParser { final JSONObject image = images.getJSONObject(i); String url = "http://img.geocaching.com/cache/log/" + image.getString("FileName"); String title = image.getString("Name"); - final cgImage logImage = new cgImage(url, title); + final Image logImage = new Image(url, title); logDone.addLogImage(logImage); } @@ -1553,7 +1544,7 @@ public abstract class GCParser { final List<LogType> types = new ArrayList<LogType>(); - final Matcher typeBoxMatcher = GCConstants.PATTERN_TYPEBOX.matcher(page); + final MatcherWrapper typeBoxMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPEBOX, page); String typesText = null; if (typeBoxMatcher.find()) { if (typeBoxMatcher.groupCount() > 0) { @@ -1563,13 +1554,16 @@ public abstract class GCParser { if (typesText != null) { - final Matcher typeMatcher = GCConstants.PATTERN_TYPE2.matcher(typesText); + final MatcherWrapper typeMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPE2, typesText); while (typeMatcher.find()) { if (typeMatcher.groupCount() > 1) { - final int type = Integer.parseInt(typeMatcher.group(2)); - - if (type > 0) { - types.add(LogType.getById(type)); + try { + int type = Integer.parseInt(typeMatcher.group(2)); + if (type > 0) { + types.add(LogType.getById(type)); + } + } catch (NumberFormatException e) { + Log.e("Error parsing log types", e); } } } @@ -1598,7 +1592,7 @@ public abstract class GCParser { final List<TrackableLog> trackableLogs = new ArrayList<TrackableLog>(); - final Matcher trackableMatcher = GCConstants.PATTERN_TRACKABLE.matcher(page); + final MatcherWrapper trackableMatcher = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE, page); while (trackableMatcher.find()) { if (trackableMatcher.groupCount() > 0) { @@ -1679,4 +1673,48 @@ public abstract class GCParser { } } + public static boolean uploadModifiedCoordinates(cgCache cache, Geopoint wpt) { + return editModifiedCoordinates(cache, wpt); + } + + public static boolean deleteModifiedCoordinates(cgCache cache) { + return editModifiedCoordinates(cache, null); + } + + public static boolean editModifiedCoordinates(cgCache cache, Geopoint wpt) { + final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0"); + final String userToken = BaseUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, ""); + if (StringUtils.isEmpty(userToken)) { + return false; + } + + try { + JSONObject jo; + if (wpt != null) { + jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken) + .put("data", new JSONObject() + .put("lat", wpt.getLatitudeE6() / 1E6) + .put("lng", wpt.getLongitudeE6() / 1E6)))); + } else { + jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken))); + } + + final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate"; + + final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; + HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); + Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString()); + + if (response != null && response.getStatusLine().getStatusCode() == 200) { + Log.i("GCParser.editModifiedCoordinates - edited on GC.com"); + return true; + } + + } catch (JSONException e) { + Log.e("Unknown exception with json wrap code", e); + } + Log.e("GCParser.deleteModifiedCoordinates - cannot delete modified coords"); + return false; + } + } diff --git a/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java b/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java index 1083a89..eba9301 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java +++ b/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java @@ -26,7 +26,7 @@ public class GCSmiliesProvider { public final String text; - private Smiley(final String text) { + Smiley(final String text) { this.text = text; } diff --git a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java index 50c0a6a..9c28048 100644 --- a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java +++ b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java @@ -10,153 +10,496 @@ import android.graphics.Bitmap; * */ public abstract class IconDecoder { + private static final int CT_TRADITIONAL = 0; + private static final int CT_MULTI = 1; + private static final int CT_MYSTERY = 2; + private static final int CT_EVENT = 3; + private static final int CT_EARTH = 4; + private static final int CT_FOUND = 5; + private static final int CT_OWN = 6; + private static final int CT_MEGAEVENT = 7; + private static final int CT_CITO = 8; + private static final int CT_WEBCAM = 9; + private static final int CT_WHEREIGO = 10; + private static final int CT_VIRTUAL = 11; + private static final int CT_LETTERBOX = 12; - public static void parseMapPNG(final cgCache cache, Bitmap bitmap, UTFGridPosition xy, int zoomlevel) { - if (zoomlevel >= 14) { - parseMapPNG14(cache, bitmap, xy); - } else { - parseMapPNG13(cache, bitmap, xy); + public static boolean parseMapPNG(final cgCache cache, Bitmap bitmap, UTFGridPosition xy, int zoomlevel) { + final int topX = xy.getX() * 4; + final int topY = xy.getY() * 4; + final int bitmapWidth = bitmap.getWidth(); + final int bitmapHeight = bitmap.getHeight(); + + if ((topX < 0) || (topY < 0) || (topX + 4 > bitmapWidth) || (topY + 4 > bitmapHeight)) { + return false; //out of image position } - } - private static final int[] OFFSET_X = new int[] { 0, -1, -1, 0, 1, 1, 1, 0, -1, -2, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2 }; - private static final int[] OFFSET_Y = new int[] { 0, 0, 1, 1, 1, 0, -1, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2 }; + int numberOfDetections = 7; //for level 12 and 13; + if (zoomlevel < 12) { + numberOfDetections = 5; + } + if (zoomlevel > 13) { + numberOfDetections = 13; + } - /** - * The icon decoder walks a spiral around the center pixel position of the cache - * and searches for characteristic colors. - * - * @param cache - * @param bitmap - * @param xy - */ - private static void parseMapPNG13(final cgCache cache, Bitmap bitmap, UTFGridPosition xy) { - final int xCenter = xy.getX() * 4 + 2; - final int yCenter = xy.getY() * 4 + 2; - final int bitmapWidth = bitmap.getWidth(); - final int bitmapHeight = bitmap.getHeight(); + int[] pngType = new int[numberOfDetections]; + for (int x = topX; x < topX + 4; x++) { + for (int y = topY; y < topY + 4; y++) { + int color = bitmap.getPixel(x, y); - int countMulti = 0; - int countFound = 0; + if ((color >>> 24) != 255) { + continue; //transparent pixels (or semi_transparent) are only shadows of border + } - for (int i = 0; i < OFFSET_X.length; i++) { + int r = (color & 0xFF0000) >> 16; + int g = (color & 0xFF00) >> 8; + int b = color & 0xFF; - // assert that we are still in the tile - final int x = xCenter + OFFSET_X[i]; - if (x < 0 || x >= bitmapWidth) { - continue; - } + if (isPixelDuplicated(r, g, b, zoomlevel)) { + continue; + } - final int y = yCenter + OFFSET_Y[i]; - if (y < 0 || y >= bitmapHeight) { - continue; + int type; + if (zoomlevel < 12) { + type = getCacheTypeFromPixel11(r, g, b); + } else { + if (zoomlevel > 13) { + type = getCacheTypeFromPixel14(r, g, b); + } else { + type = getCacheTypeFromPixel13(r, g, b); + } + } + pngType[type]++; } + } - int color = bitmap.getPixel(x, y) & 0x00FFFFFF; + int type = -1; + int count = 0; - // transparent pixels are not interesting - if (color == 0) { - continue; + for (int x = 0; x < pngType.length; x++) + { + if (pngType[x] > count) { + count = pngType[x]; + type = x; } + } - int red = (color & 0xFF0000) >> 16; - int green = (color & 0xFF00) >> 8; - int blue = color & 0xFF; + if (count > 1) { // 2 pixels need to detect same type and we say good to go + switch (type) { + case CT_TRADITIONAL: + cache.setType(CacheType.TRADITIONAL); + return true; + case CT_MULTI: + cache.setType(CacheType.MULTI); + return true; + case CT_MYSTERY: + cache.setType(CacheType.MYSTERY); + return true; + case CT_EVENT: + cache.setType(CacheType.EVENT); + return true; + case CT_EARTH: + cache.setType(CacheType.EARTH); + return true; + case CT_FOUND: + cache.setFound(true); + return true; + case CT_OWN: + cache.setOwn(true); + return true; + case CT_MEGAEVENT: + cache.setType(CacheType.MEGA_EVENT); + return true; + case CT_CITO: + cache.setType(CacheType.CITO); + return true; + case CT_WEBCAM: + cache.setType(CacheType.WEBCAM); + return true; + case CT_WHEREIGO: + cache.setType(CacheType.WHERIGO); + return true; + case CT_VIRTUAL: + cache.setType(CacheType.VIRTUAL); + return true; + case CT_LETTERBOX: + cache.setType(CacheType.LETTERBOX); + return true; + } + } + return false; + } - // these are quite sure, so one pixel is enough for matching - if (green > 0x80 && green > red && green > blue) { - cache.setType(CacheType.TRADITIONAL); - return; + /** + * A method that returns true if pixel color appears on more then one cache type and shall be excluded from parsing + * + * @param r + * red value + * @param g + * green value + * @param b + * blue value + * @param zoomlevel + * zoom level of map + * @return true if parsing should not be performed + */ + private static boolean isPixelDuplicated(int r, int g, int b, int zoomlevel) { + if (zoomlevel < 12) { + if (((r == g) && (g == b)) || ((r == 233) && (g == 233) && (b == 234))) { + return true; } - if (blue > 0x80 && blue > red && blue > green) { - cache.setType(CacheType.MYSTERY); - return; + return false; + } + if (zoomlevel > 13) { + if ((r == g) && (g == b)) { + if ((r == 119) || (r == 231) || (r == 5) || (r == 230) || (r == 244) || (r == 93) || (r == 238) || (r == 73) || (r == 9) || (r == 225) || (r == 162) || (r == 153) || (r == 32) || + (r == 50) || (r == 20) || (r == 232) || (r == 224) || (r == 192) || (r == 248) || (r == 152) || (r == 128) || (r == 176) || (r == 184) || (r == 200)) { + return false; + } + return true; } - if (red > 0x90 && blue < 0x10 && green < 0x10) { - cache.setType(CacheType.EVENT); - return; + if ((r == 44) && (b == 44) && (g == 17) || + (r == 228) && (b == 228) && (g == 255) || + (r == 236) && (b == 236) && (g == 255) || + (r == 252) && (b == 225) && (g == 83) || + (r == 252) && (b == 221) && (g == 81) || + (r == 252) && (b == 216) && (g == 79) || + (r == 252) && (b == 211) && (g == 77) || + (r == 251) && (b == 206) && (g == 75) || + (r == 251) && (b == 201) && (g == 73) || + (r == 251) && (b == 196) && (g == 71) || + (r == 251) && (b == 191) && (g == 69) || + (r == 243) && (b == 153) && (g == 36)) { + return true; } + return false; + } + //zoom level 12, 13 + if ((r == 95) && (g == 95) && (b == 95)) { + return true; + } + return false; + } - // next two are hard to distinguish, therefore we sample all pixels of the spiral - if (red > 0xFA && green > 0xD0) { - countMulti++; + /** + * This method returns detected type from specific pixel from geocaching.com live map. + * It was constructed based on classification tree made by Orange (http://orange.biolab.si/) + * Input file was made from every non-transparent pixel of every possible "middle" cache icon from GC map + * + * @param r + * Red component of pixel (from 0 - 255) + * @param g + * Green component of pixel (from 0 - 255) + * @param b + * Blue component of pixel (from 0 - 255) + * @return Value from 0 to 6 representing detected type or state of the cache. + */ + private static int getCacheTypeFromPixel13(int r, int g, int b) { + if (b < 130) { + if (r < 41) { + return CT_MYSTERY; + } + if (g < 74) { + return CT_EVENT; + } + if (r < 130) { + return CT_TRADITIONAL; } - if (red < 0xF3 && red > 0xa0 && green > 0x20 && blue < 0x80) { - countFound++; + if (b < 31) { + return CT_MULTI; } + if (b < 101) { + if (g < 99) { + return r < 178 ? CT_FOUND : CT_EVENT; + } + if (b < 58) { + if (g < 174) { + return CT_FOUND; + } + if (r < 224) { + return CT_OWN; + } + if (b < 49) { + return g < 210 ? CT_FOUND : CT_OWN; + } + if (g < 205) { + return g < 202 ? CT_FOUND : CT_OWN; + } + return CT_FOUND; + } + if (r < 255) { + return CT_FOUND; + } + return g < 236 ? CT_MULTI : CT_FOUND; + } + return g < 182 ? CT_EVENT : CT_MULTI; } - - // now check whether we are sure about found/multi - if (countFound > countMulti && countFound >= 2) { - cache.setFound(true); + if (r < 136) { + return CT_MYSTERY; } - if (countMulti > countFound && countMulti >= 5) { - cache.setType(CacheType.MULTI); + if (b < 168) { + return g < 174 ? CT_EARTH : CT_TRADITIONAL; } + return CT_EARTH; } - // Pixel colors in tile - private final static int COLOR_BORDER_GRAY = 0x5F5F5F; - private final static int COLOR_TRADITIONAL = 0x316013; - private final static int COLOR_MYSTERY = 0x243C97; - private final static int COLOR_MULTI = 0xFFDE19; - private final static int COLOR_FOUND = 0xFF0000; - - // Offset inside cache icon - private final static int POSX_TRADI = 7; - private final static int POSY_TRADI = -12; - private final static int POSX_MULTI = 5; // for orange 8 - private final static int POSY_MULTI = -9; // for orange 10 - private final static int POSX_MYSTERY = 5; - private final static int POSY_MYSTERY = -13; - private final static int POSX_FOUND = 9; - private final static int POSY_FOUND = -6; - /** - * For level 14 find the borders of the icons and then use a single pixel and color to match. + * This method returns detected type from specific pixel from geocaching.com live map level 14 or higher. + * It was constructed based on classification tree made by Orange (http://orange.biolab.si/) + * Input file was made from every non-transparent pixel of every possible "full" cache icon from GC map * - * @param cache - * @param bitmap - * @param xy + * @param r + * Red component of pixel (from 0 - 255) + * @param g + * Green component of pixel (from 0 - 255) + * @param b + * Blue component of pixel (from 0 - 255) + * @return Value from 0 to 6 representing detected type or state of the cache. */ - private static void parseMapPNG14(cgCache cache, Bitmap bitmap, UTFGridPosition xy) { - int x = xy.getX() * 4 + 2; - int y = xy.getY() * 4 + 2; - - // search for left border - int countX = 0; - while ((bitmap.getPixel(x, y) & 0x00FFFFFF) != COLOR_BORDER_GRAY) { - if (--x < 0 || ++countX > 20) { - return; + private static int getCacheTypeFromPixel14(int r, int g, int b) { + if (b < 128) { + if (r < 214) { + if (b < 37) { + if (g < 50) { + if (b < 19) { + if (g < 16) { + if (b < 4) { + return CT_FOUND; + } + return r < 8 ? CT_VIRTUAL : CT_WEBCAM; + } + return CT_FOUND; + } + return CT_WEBCAM; + } + if (b < 24) { + if (b < 18) { + return CT_EARTH; + } + return r < 127 ? CT_TRADITIONAL : CT_EARTH; + } + return CT_FOUND; + } + if (r < 142) { + if (r < 63) { + if (r < 26) { + return CT_CITO; + } + return r < 51 ? CT_WEBCAM : CT_CITO; + } + return g < 107 ? CT_WEBCAM : CT_MULTI; + } + if (g < 138) { + return r < 178 ? CT_MEGAEVENT : CT_EVENT; + } + return b < 71 ? CT_FOUND : CT_EARTH; + } + if (b < 77) { + if (g < 166) { + if (r < 238) { + return g < 120 ? CT_MULTI : CT_OWN; + } + if (b < 57) { + if (r < 254) { + if (b < 39) { + if (r < 239) { + return CT_OWN; + } + if (b < 36) { + if (g < 150) { + if (b < 24) { + return b < 22 ? CT_FOUND : CT_OWN; + } + if (g < 138) { + return b < 25 ? CT_FOUND : CT_OWN; + } + return CT_FOUND; + } + return CT_OWN; + } + if (b < 38) { + if (b < 37) { + if (g < 153) { + return r < 242 ? CT_OWN : CT_FOUND; + } + return CT_OWN; + } + return CT_FOUND; + } + return CT_OWN; + } + if (g < 148) { + return CT_OWN; + } + if (r < 244) { + return CT_FOUND; + } + if (b < 45) { + if (b < 42) { + return CT_FOUND; + } + if (g < 162) { + return r < 245 ? CT_OWN : CT_FOUND; + } + return CT_OWN; + } + return CT_FOUND; + } + return g < 3 ? CT_FOUND : CT_VIRTUAL; + } + return CT_OWN; + } + if (b < 51) { + if (r < 251) { + return CT_OWN; + } + return g < 208 ? CT_EARTH : CT_MULTI; + } + if (b < 63) { + if (r < 247) { + return CT_FOUND; + } + if (r < 250) { + if (g < 169) { + return CT_FOUND; + } + if (g < 192) { + if (b < 54) { + return CT_OWN; + } + if (r < 248) { + return g < 180 ? CT_FOUND : CT_OWN; + } + return CT_OWN; + } + return g < 193 ? CT_FOUND : CT_OWN; + } + return CT_FOUND; + } + return CT_FOUND; + } + if (g < 177) { + return CT_OWN; } + if (r < 239) { + return CT_FOUND; + } + if (g < 207) { + return CT_OWN; + } + return r < 254 ? CT_FOUND : CT_EARTH; } - // search for bottom border - int countY = 0; - while ((bitmap.getPixel(x, y) & 0x00FFFFFF) != 0x000000) { - if (++y >= Tile.TILE_SIZE || ++countY > 20) { - return; + if (r < 203) { + if (b < 218) { + if (g < 158) { + if (g < 71) { + return CT_MYSTERY; + } + return r < 153 ? CT_WHEREIGO : CT_WEBCAM; + } + if (b < 167) { + return r < 157 ? CT_TRADITIONAL : CT_WEBCAM; + } + return CT_WHEREIGO; + } + if (g < 199) { + if (r < 142) { + return CT_LETTERBOX; + } + return r < 175 ? CT_CITO : CT_LETTERBOX; } + if (g < 207) { + return r < 167 ? CT_MEGAEVENT : CT_CITO; + } + return CT_EARTH; } - - try { - if ((bitmap.getPixel(x + POSX_TRADI, y + POSY_TRADI) & 0x00FFFFFF) == COLOR_TRADITIONAL) { - cache.setType(CacheType.TRADITIONAL); - return; + if (b < 224) { + if (g < 235) { + if (b < 163) { + if (r < 249) { + return b < 133 ? CT_FOUND : CT_OWN; + } + return CT_FOUND; + } + if (r < 235) { + if (r < 213) { + if (r < 207) { + return CT_FOUND; + } + if (g < 206) { + return CT_OWN; + } + return g < 207 ? CT_FOUND : CT_OWN; + } + return g < 194 ? CT_OWN : CT_FOUND; + } + if (g < 230) { + return CT_OWN; + } + return b < 205 ? CT_FOUND : CT_OWN; } - if ((bitmap.getPixel(x + POSX_MYSTERY, y + POSY_MYSTERY) & 0x00FFFFFF) == COLOR_MYSTERY) { - cache.setType(CacheType.MYSTERY); - return; + if (r < 238) { + return CT_CITO; } - if ((bitmap.getPixel(x + POSX_MULTI, y + POSY_MULTI) & 0x00FFFFFF) == COLOR_MULTI) { - cache.setType(CacheType.MULTI); - return; + return b < 170 ? CT_EVENT : CT_FOUND; + } + if (r < 251) { + if (r < 210) { + return CT_MYSTERY; } - if ((bitmap.getPixel(x + POSX_FOUND, y + POSY_FOUND) & 0x00FFFFFF) == COLOR_FOUND) { - cache.setFound(true); + if (b < 252) { + if (r < 243) { + if (r < 225) { + return CT_WHEREIGO; + } + if (b < 232) { + if (g < 228) { + return CT_WEBCAM; + } + return r < 231 ? CT_VIRTUAL : CT_TRADITIONAL; + } + if (r < 236) { + return CT_WHEREIGO; + } + return r < 240 ? CT_WEBCAM : CT_WHEREIGO; + } + if (g < 247) { + return r < 245 ? CT_WEBCAM : CT_FOUND; + } + return CT_WHEREIGO; } - } catch (IllegalArgumentException e) { - // intentionally left blank + return CT_LETTERBOX; } + if (r < 255) { + return CT_OWN; + } + return g < 254 ? CT_FOUND : CT_OWN; + } + /** + * This method returns detected type from specific pixel from geocaching.com live map level 11 or lower. + * It was constructed based on classification tree made by Orange (http://orange.biolab.si/) + * Input file was made from every non-transparent pixel of every possible "full" cache icon from GC map + * + * @param r + * Red component of pixel (from 0 - 255) + * @param g + * Green component of pixel (from 0 - 255) + * @param b + * Blue component of pixel (from 0 - 255) + * @return Value from 0 to 4 representing detected type or state of the cache. + */ + private static int getCacheTypeFromPixel11(int r, int g, int b) { + if (g < 136) { + if (r < 90) { + return g < 111 ? CT_MYSTERY : CT_TRADITIONAL; + } + return b < 176 ? CT_EVENT : CT_MYSTERY; + } + if (r < 197) { + return CT_TRADITIONAL; + } + return b < 155 ? CT_MULTI : CT_EARTH; } + } diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java index c3f29cc..9a60f65 100644 --- a/main/src/cgeo/geocaching/connector/gc/Login.java +++ b/main/src/cgeo/geocaching/connector/gc/Login.java @@ -10,6 +10,7 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import ch.boye.httpclientandroidlib.HttpResponse; @@ -26,7 +27,6 @@ import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.regex.Matcher; public abstract class Login { @@ -349,7 +349,7 @@ public abstract class Login { } int count = 1; - final Matcher matcherViewstateCount = GCConstants.PATTERN_VIEWSTATEFIELDCOUNT.matcher(page); + final MatcherWrapper matcherViewstateCount = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATEFIELDCOUNT, page); if (matcherViewstateCount.find()) { try { count = Integer.parseInt(matcherViewstateCount.group(1)); @@ -361,14 +361,13 @@ public abstract class Login { String[] viewstates = new String[count]; // Get the viewstates - int no; - final Matcher matcherViewstates = GCConstants.PATTERN_VIEWSTATES.matcher(page); + final MatcherWrapper matcherViewstates = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATES, page); while (matcherViewstates.find()) { String sno = matcherViewstates.group(1); // number of viewstate - if (sno.length() == 0) { + int no; + if (StringUtils.isEmpty(sno)) { no = 0; - } - else { + } else { try { no = Integer.parseInt(sno); } catch (NumberFormatException e) { diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java index 5404446..73ded4d 100644 --- a/main/src/cgeo/geocaching/connector/gc/Tile.java +++ b/main/src/cgeo/geocaching/connector/gc/Tile.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.Locale; import java.util.Set; /** @@ -99,7 +100,7 @@ public class Tile { /** * Calculate latitude/longitude for a given x/y position in this tile. - * + * * @see <a * href="http://developers.cloudmade.com/projects/tiles/examples/convert-coordinates-to-tile-numbers">Cloudmade</a> */ @@ -115,7 +116,7 @@ public class Tile { @Override public String toString() { - return String.format("(%d/%d), zoom=%d", tileX, tileY, zoomlevel); + return String.format(Locale.US, "(%d/%d), zoom=%d", tileX, tileY, zoomlevel); } /** diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java index a4eeff5..6d20eb6 100644 --- a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java +++ b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java @@ -29,7 +29,7 @@ public final class UTFGrid { } /** Calculate from a list of positions (x/y) the coords */ - protected static UTFGridPosition getPositionInGrid(List<UTFGridPosition> positions) { + public static UTFGridPosition getPositionInGrid(List<UTFGridPosition> positions) { int minX = GRID_MAXX; int maxX = 0; int minY = GRID_MAXY; diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java index e34d277..5965fff 100644 --- a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java +++ b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java @@ -1,6 +1,7 @@ package cgeo.geocaching.connector.gc; -import java.util.regex.Matcher; +import cgeo.geocaching.utils.MatcherWrapper; + import java.util.regex.Pattern; @@ -35,7 +36,7 @@ public final class UTFGridPosition { * @return */ static UTFGridPosition fromString(String key) { - final Matcher matcher = UTFGridPosition.PATTERN_JSON_KEY.matcher(key); + final MatcherWrapper matcher = new MatcherWrapper(UTFGridPosition.PATTERN_JSON_KEY, key); try { if (matcher.matches()) { final int x = Integer.parseInt(matcher.group(1)); diff --git a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java new file mode 100644 index 0000000..068ac88 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java @@ -0,0 +1,570 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.LogEntry; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.enumerations.CacheSize; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.StringUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import android.sax.Element; +import android.sax.EndElementListener; +import android.sax.EndTextElementListener; +import android.sax.RootElement; +import android.sax.StartElementListener; +import android.util.Xml; + +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class OC11XMLParser { + + private static final String PARAGRAPH_END = "</p>"; + private static final String PARAGRAPH_BEGIN = "<p>"; + private static Pattern STRIP_DATE = Pattern.compile("\\+0([0-9]){1}\\:00"); + private static Pattern LOCAL_URL = Pattern.compile("href=\"(.*)\""); + private static final int CACHE_PARSE_LIMIT = 250; + + private static class CacheHolder { + public cgCache cache; + public String latitude; + public String longitude; + } + + private static class CacheLog { + public String cacheId; + public LogEntry logEntry; + } + + private static class CacheDescription { + public String cacheId; + public String shortDesc; + public String desc; + public String hint; + } + + private static Date parseFullDate(final String date) { + final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US); + ISO8601DATEFORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); + final String strippedDate = STRIP_DATE.matcher(date).replaceAll("+0$100"); + try { + return ISO8601DATEFORMAT.parse(strippedDate); + } catch (ParseException e) { + Log.e("OC11XMLParser.parseFullDate", e); + } + return null; + } + + private static Date parseDayDate(final String date) { + final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US); + ISO8601DATEFORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); + final String strippedDate = STRIP_DATE.matcher(date).replaceAll("+0$100"); + try { + return ISO8601DATEFORMAT.parse(strippedDate); + } catch (ParseException e) { + Log.e("OC11XMLParser.parseDayDate", e); + } + return null; + } + + private static CacheSize getCacheSize(final String sizeId) { + try { + int size = Integer.parseInt(sizeId); + + switch (size) { + case 1: + return CacheSize.OTHER; + case 2: + return CacheSize.MICRO; + case 3: + return CacheSize.SMALL; + case 4: + return CacheSize.REGULAR; + case 5: + case 6: + return CacheSize.LARGE; + case 8: + return CacheSize.VIRTUAL; + default: + break; + } + } catch (NumberFormatException e) { + Log.e("OC11XMLParser.getCacheSize", e); + } + return CacheSize.NOT_CHOSEN; + } + + private static CacheType getCacheType(final String typeId) { + try { + int type = Integer.parseInt(typeId); + switch (type) { + case 1: // Other/unbekannter Cachetyp + return CacheType.UNKNOWN; + case 2: // Trad./normaler Cache + return CacheType.TRADITIONAL; + case 3: // Multi/Multicache + return CacheType.MULTI; + case 4: // Virt./virtueller Cache + return CacheType.VIRTUAL; + case 5: // ICam./Webcam-Cache + return CacheType.WEBCAM; + case 6: // Event/Event-Cache + return CacheType.EVENT; + case 7: // Quiz/Rätselcache + return CacheType.MYSTERY; + case 8: // Math/Mathe-/Physikcache + return CacheType.MYSTERY; + case 9: // Moving/beweglicher Cache + return CacheType.VIRTUAL; + case 10: // Driv./Drive-In + return CacheType.TRADITIONAL; + } + } catch (NumberFormatException e) { + Log.e("OC11XMLParser.getCacheType", e); + } + return CacheType.UNKNOWN; + } + + private static LogType getLogType(final int typeId) { + switch (typeId) { + case 1: + return LogType.FOUND_IT; + case 2: + return LogType.DIDNT_FIND_IT; + case 3: + return LogType.NOTE; + case 7: + return LogType.ATTENDED; + case 8: + return LogType.WILL_ATTEND; + default: + return LogType.UNKNOWN; + } + } + + private static void setCacheStatus(final int statusId, final cgCache cache) { + switch (statusId) { + case 1: + cache.setArchived(false); + cache.setDisabled(false); + break; + case 2: + cache.setArchived(false); + cache.setDisabled(true); + break; + default: + cache.setArchived(true); + cache.setDisabled(false); + break; + } + } + + private static void resetCache(final CacheHolder cacheHolder) { + cacheHolder.cache = new cgCache(null); + cacheHolder.cache.setReliableLatLon(true); + cacheHolder.cache.setDescription(StringUtils.EMPTY); + cacheHolder.latitude = "0.0"; + cacheHolder.longitude = "0.0"; + } + + private static void resetLog(final CacheLog log) { + log.cacheId = StringUtils.EMPTY; + log.logEntry = new LogEntry("", 0, LogType.UNKNOWN, ""); + } + + private static void resetDesc(final CacheDescription desc) { + desc.cacheId = StringUtils.EMPTY; + desc.shortDesc = StringUtils.EMPTY; + desc.desc = StringUtils.EMPTY; + desc.hint = StringUtils.EMPTY; + } + + public static Collection<cgCache> parseCaches(final InputStream stream) throws IOException { + + final Map<String, cgCache> caches = new HashMap<String, cgCache>(); + + final CacheHolder cacheHolder = new CacheHolder(); + final CacheLog logHolder = new CacheLog(); + final CacheDescription descHolder = new CacheDescription(); + + final RootElement root = new RootElement("oc11xml"); + final Element cacheNode = root.getChild("cache"); + + // cache + cacheNode.setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attributes) { + resetCache(cacheHolder); + } + + }); + + cacheNode.setEndElementListener(new EndElementListener() { + + @Override + public void end() { + cgCache cache = cacheHolder.cache; + Geopoint coords = new Geopoint(cacheHolder.latitude, cacheHolder.longitude); + if (StringUtils.isNotBlank(cache.getGeocode()) + && !coords.equals(Geopoint.ZERO) + && !cache.isArchived() + && caches.size() < CACHE_PARSE_LIMIT) { + cache.setCoords(coords); + cache.setDetailedUpdatedNow(); + caches.put(cache.getCacheId(), cache); + } + } + }); + + // cache.id + cacheNode.getChild("id").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + cacheHolder.cache.setCacheId(body); + } + }); + + // cache.longitude + cacheNode.getChild("longitude").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + String longitude = body.trim(); + if (StringUtils.isNotBlank(longitude)) { + cacheHolder.longitude = longitude; + } + } + }); + + // cache.latitude + cacheNode.getChild("latitude").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + String latitude = body.trim(); + if (StringUtils.isNotBlank(latitude)) { + cacheHolder.latitude = latitude; + } + } + }); + + // cache.name + cacheNode.getChild("name").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + final String content = body.trim(); + cacheHolder.cache.setName(content); + } + }); + + // cache.waypoints[oc] + cacheNode.getChild("waypoints").setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attrs) { + if (attrs.getIndex("oc") > -1) { + cacheHolder.cache.setGeocode(attrs.getValue("oc")); + } + if (attrs.getIndex("gccom") > -1) { + String gccode = attrs.getValue("gccom"); + if (!StringUtils.isBlank(gccode)) { + cacheHolder.cache.setDescription(String.format("Listed on geocaching com: <a href=\"http://coord.info/%s\">%s</a><br /><br />", gccode, gccode)); + } + } + } + }); + + // cache.type[id] + cacheNode.getChild("type").setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attrs) { + if (attrs.getIndex("id") > -1) { + final String typeId = attrs.getValue("id"); + cacheHolder.cache.setType(getCacheType(typeId)); + } + } + }); + + // cache.status[id] + cacheNode.getChild("status").setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attrs) { + if (attrs.getIndex("id") > -1) { + try { + final int statusId = Integer.parseInt(attrs.getValue("id")); + setCacheStatus(statusId, cacheHolder.cache); + } catch (NumberFormatException e) { + Log.w(String.format("Failed to parse status of cache '%s'.", cacheHolder.cache.getGeocode())); + } + } + } + }); + + // cache.size[id] + cacheNode.getChild("size").setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attrs) { + if (attrs.getIndex("id") > -1) { + final String typeId = attrs.getValue("id"); + cacheHolder.cache.setSize(getCacheSize(typeId)); + } + } + }); + + // cache.difficulty + cacheNode.getChild("difficulty").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + final String content = body.trim(); + try { + cacheHolder.cache.setDifficulty(Float.valueOf(content)); + } catch (NumberFormatException e) { + Log.e("OC11XMLParser: unknown difficulty " + content, e); + } + } + }); + + // cache.terrain + cacheNode.getChild("terrain").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + final String content = body.trim(); + try { + cacheHolder.cache.setTerrain(Float.valueOf(content)); + } catch (NumberFormatException e) { + Log.e("OC11XMLParser: unknown terrain " + content, e); + } + } + }); + + // cache.terrain + cacheNode.getChild("datehidden").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + final String content = body.trim(); + cacheHolder.cache.setHidden(parseFullDate(content)); + } + }); + + // cache.attributes.attribute + cacheNode.getChild("attributes").getChild("attribute").setEndTextElementListener(new EndTextElementListener() { + @Override + public void end(String body) { + if (StringUtils.isNotBlank(body)) { + cacheHolder.cache.getAttributes().add(body.trim()); + } + } + }); + + // cachedesc + final Element cacheDesc = root.getChild("cachedesc"); + + cacheDesc.setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attributes) { + resetDesc(descHolder); + } + }); + + cacheDesc.setEndElementListener(new EndElementListener() { + + @Override + public void end() { + final cgCache cache = caches.get(descHolder.cacheId); + if (cache != null) { + cache.setShortdesc(descHolder.shortDesc); + cache.setDescription(cache.getDescription() + descHolder.desc); + cache.setHint(descHolder.hint); + } + } + }); + + // cachedesc.cacheid + cacheDesc.getChild("cacheid").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + descHolder.cacheId = body; + } + }); + + // cachedesc.desc + cacheDesc.getChild("shortdesc").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + final String content = body.trim(); + descHolder.shortDesc = linkify(content); + } + }); + + // cachedesc.desc + cacheDesc.getChild("desc").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + final String content = body.trim(); + descHolder.desc = linkify(content); + } + }); + + // cachedesc.hint + cacheDesc.getChild("hint").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + final String content = body.trim(); + descHolder.hint = content; + } + }); + + // cachelog + final Element cacheLog = root.getChild("cachelog"); + + cacheLog.setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attrs) { + resetLog(logHolder); + } + }); + + cacheLog.setEndElementListener(new EndElementListener() { + + @Override + public void end() { + final cgCache cache = caches.get(logHolder.cacheId); + if (cache != null && logHolder.logEntry.type != LogType.UNKNOWN) { + cache.getLogs().prepend(logHolder.logEntry); + if (logHolder.logEntry.type == LogType.FOUND_IT + && StringUtils.equalsIgnoreCase(logHolder.logEntry.author, Settings.getOCConnectorUserName())) { + cache.setFound(true); + cache.setVisitedDate(logHolder.logEntry.date); + } + } + } + }); + + // cachelog.cacheid + cacheLog.getChild("cacheid").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + logHolder.cacheId = body; + } + }); + + // cachelog.date + cacheLog.getChild("date").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + try { + logHolder.logEntry.date = parseDayDate(body).getTime(); + } catch (NullPointerException e) { + Log.w("Failed to parse log date", e); + } + } + }); + + // cachelog.logtype + cacheLog.getChild("logtype").setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attrs) { + if (attrs.getIndex("id") > -1) { + final String id = attrs.getValue("id"); + try { + final int typeId = Integer.parseInt(id); + logHolder.logEntry.type = getLogType(typeId); + } catch (NumberFormatException e) { + Log.e("OC11XMLParser, unknown logtype " + id, e); + } + } + } + }); + + // cachelog.userid + cacheLog.getChild("userid").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String finderName) { + logHolder.logEntry.author = finderName; + } + }); + + // cachelog.text + cacheLog.getChild("text").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String logText) { + logHolder.logEntry.log = stripMarkup(logText); + } + }); + + try { + Xml.parse(stream, Xml.Encoding.UTF_8, root.getContentHandler()); + return caches.values(); + } catch (SAXException e) { + Log.e("Cannot parse .gpx file as oc11xml: could not parse XML", e); + return null; + } + } + + private static String linkify(String input) { + String result = input; + Matcher matcher = LOCAL_URL.matcher(result); + while (matcher.find()) { + String url = matcher.group(1); + if (!url.contains(":/")) { + IConnector ocConnector = ConnectorFactory.getConnector("OCXXX"); + String prefix = "http://" + ocConnector.getHost() + "/"; + result = StringUtils.replace(result, url, prefix + url); + matcher = LOCAL_URL.matcher(result); + } + } + return result; + } + + /** + * Removes unneeded markup. Log texts are typically encapsulated in paragraph tags which lead to more empty space on + * rendering. + */ + protected static String stripMarkup(String input) { + if (StringUtils.startsWith(input, PARAGRAPH_BEGIN) && StringUtils.endsWith(input, PARAGRAPH_END)) { + String inner = input.substring(PARAGRAPH_BEGIN.length(), input.length() - PARAGRAPH_END.length()); + if (inner.indexOf(PARAGRAPH_BEGIN) < 0) { + return inner; + } + } + return input; + } +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java index 17c961a..74968e7 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java @@ -34,4 +34,10 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { } return new SearchResult(cache); } + + @Override + public boolean isActivated() { + // currently always active, but only for details download + return true; + } } diff --git a/main/src/cgeo/geocaching/connector/oc/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java index c098d12..24fd7d6 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java @@ -2,6 +2,7 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.cgCache; import cgeo.geocaching.connector.AbstractConnector; +import cgeo.geocaching.enumerations.CacheRealm; import java.util.regex.Pattern; @@ -51,4 +52,9 @@ public class OCConnector extends AbstractConnector { return "http://" + host + "/viewcache.php?wp="; } + @Override + public CacheRealm getCacheRealm() { + return CacheRealm.OC; + } + } diff --git a/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java new file mode 100644 index 0000000..3a2f42e --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java @@ -0,0 +1,52 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.connector.capability.ISearchByCenter; +import cgeo.geocaching.connector.capability.ISearchByGeocode; +import cgeo.geocaching.connector.capability.ISearchByViewPort; +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.utils.CancellableHandler; + +public class OCXMLApiConnector extends OCConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort { + + private final static double SEARCH_DISTANCE_LIMIT = 15.0; + private final static double NEARBY_SEARCH_DISTANCE = 5.0; + + public OCXMLApiConnector(String name, String host, String prefix) { + super(name, host, prefix); + } + + @Override + public SearchResult searchByGeocode(final String geocode, final String guid, CancellableHandler handler) { + final cgCache cache = OCXMLClient.getCache(geocode); + if (cache == null) { + return null; + } + return new SearchResult(cache); + } + + @Override + public SearchResult searchByCenter(final Geopoint center) { + return new SearchResult(OCXMLClient.getCachesAround(center, NEARBY_SEARCH_DISTANCE)); + } + + @Override + public SearchResult searchByViewport(final Viewport viewport, final String[] tokens) { + final Geopoint center = viewport.getCenter(); + double distance = center.distanceTo(viewport.bottomLeft) * 1.15; + if (distance > SEARCH_DISTANCE_LIMIT) { + distance = SEARCH_DISTANCE_LIMIT; + } + return new SearchResult(OCXMLClient.getCachesAround(center, distance)); + } + + @Override + public boolean isActivated() { + // currently only tested and working with oc.de + return Settings.isOCConnectorActive(); + } + +} diff --git a/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java b/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java new file mode 100644 index 0000000..88ba5a1 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java @@ -0,0 +1,108 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgData; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.enumerations.LoadFlags; +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.GeopointFormatter; +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 java.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.Locale; +import java.util.zip.GZIPInputStream; + +public class OCXMLClient { + + private static final String SERVICE_CACHE = "/xml/ocxml11.php"; + + // Url for single cache requests + // http://www.opencaching.de/xml/ocxml11.php?modifiedsince=20060320000000&user=0&cache=1&cachedesc=1&cachelog=1&picture=1&removedobject=0&session=0&doctype=0&charset=utf-8&wp=OCC9BE + + public static cgCache getCache(final String geoCode) { + try { + final Parameters params = getOCXmlQueryParameters(true, true); + params.put("wp", geoCode); + final InputStream data = request(ConnectorFactory.getConnector(geoCode), SERVICE_CACHE, params); + + if (data == null) { + return null; + } + + Collection<cgCache> caches = OC11XMLParser.parseCaches(new GZIPInputStream(data)); + if (caches.iterator().hasNext()) { + cgCache cache = caches.iterator().next(); + cgData.saveCache(cache, LoadFlags.SAVE_ALL); + return cache; + } + return null; + } catch (IOException e) { + Log.e("Error parsing cache '" + geoCode + "'", e); + return null; + } + } + + public static Collection<cgCache> getCachesAround(final Geopoint center, final double distance) { + try { + final Parameters params = getOCXmlQueryParameters(false, false); + params.put("lat", GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center)); + params.put("lon", GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center)); + params.put("distance", String.format(Locale.US, "%f", distance)); + final InputStream data = request(ConnectorFactory.getConnector("OCXXX"), SERVICE_CACHE, params); + + if (data == null) { + return Collections.emptyList(); + } + + return OC11XMLParser.parseCaches(new GZIPInputStream(data)); + } catch (IOException e) { + Log.e("Error parsing nearby search result", e); + return Collections.emptyList(); + } + } + + private static InputStream request(final IConnector connector, final String service, final Parameters params) { + if (connector == null) { + return null; + } + if (!(connector instanceof OCXMLApiConnector)) { + return null; + } + + final String host = connector.getHost(); + if (StringUtils.isBlank(host)) { + return null; + } + + final String uri = "http://" + host + service; + HttpResponse resp = Network.getRequest(uri, params); + if (resp != null) { + try { + return resp.getEntity().getContent(); + } catch (IllegalStateException e) { + // fall through and return null + } catch (IOException e) { + // fall through and return null + } + } + return null; + } + + private static Parameters getOCXmlQueryParameters(final boolean withDescription, final boolean withLogs) { + final Parameters params = new Parameters("modifiedsince", "20060320000000", + "user", "0", "cache", "1", "cachedesc", withDescription ? "1" : "0", + "cachelog", withLogs ? "1" : "0", "picture", "0", "removedobject", "0", + "session", "0", "doctype", "0", "charset", "utf-8", "zip", "gzip"); + return params; + } +} diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index 87cc3a1..508d0b5 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -1,9 +1,9 @@ package cgeo.geocaching.connector.oc; +import cgeo.geocaching.Image; import cgeo.geocaching.LogEntry; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgImage; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.enumerations.CacheSize; @@ -153,13 +153,12 @@ final public class OkapiClient { final JSONArray images = response.getJSONArray(CACHE_IMAGES); if (images != null) { - JSONObject imageResponse; for (int i = 0; i < images.length(); i++) { - imageResponse = images.getJSONObject(i); + JSONObject imageResponse = images.getJSONObject(i); if (imageResponse.getBoolean(CACHE_IMAGE_IS_SPOILER)) { final String title = imageResponse.getString(CACHE_IMAGE_CAPTION); final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode()); - cache.addSpoiler(new cgImage(url, title)); + cache.addSpoiler(new Image(url, title)); } } } @@ -168,12 +167,9 @@ final public class OkapiClient { cache.setLogs(parseLogs(response.getJSONArray(CACHE_LATEST_LOGS))); cache.setHidden(parseDate(response.getString(CACHE_HIDDEN))); - cache.setUpdated(System.currentTimeMillis()); - cache.setDetailedUpdate(cache.getUpdated()); - cache.setDetailed(true); - + cache.setDetailedUpdatedNow(); // save full detailed caches - cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); } catch (JSONException e) { Log.e("OkapiClient.parseCache", e); } diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java index a31b0cc..01d76f5 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java +++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java @@ -88,7 +88,7 @@ public enum CacheAttribute { public final int stringIdYes; public final int stringIdNo; - private CacheAttribute(final int id, final String gcRawName, final int drawableId, final int stringIdYes, final int stringIdNo) { + CacheAttribute(final int id, final String gcRawName, final int drawableId, final int stringIdYes, final int stringIdNo) { this.id = id; this.gcRawName = gcRawName; this.drawableId = drawableId; @@ -110,15 +110,6 @@ public enum CacheAttribute { FIND_BY_GCRAWNAME = Collections.unmodifiableMap(mapGcRawNames); } - public static CacheAttribute getById(final int id) { - for (CacheAttribute attr : values()) { - if (attr.id == id) { - return attr; - } - } - return UNKNOWN; - } - public static CacheAttribute getByGcRawName(final String gcRawName) { final CacheAttribute result = gcRawName != null ? FIND_BY_GCRAWNAME.get(gcRawName) : null; if (result == null) { diff --git a/main/src/cgeo/geocaching/enumerations/CacheRealm.java b/main/src/cgeo/geocaching/enumerations/CacheRealm.java new file mode 100644 index 0000000..5a203ab --- /dev/null +++ b/main/src/cgeo/geocaching/enumerations/CacheRealm.java @@ -0,0 +1,22 @@ +package cgeo.geocaching.enumerations; + +import cgeo.geocaching.R; + +public enum CacheRealm { + + GC("gc", "geocaching.com", R.drawable.marker, R.drawable.marker_disabled), + OC("oc", "OpenCaching Network", R.drawable.marker_oc, R.drawable.marker_disabled_oc), + OTHER("other", "Other", R.drawable.marker_other, R.drawable.marker_disabled_other); + + public final String id; + public final String name; + public final int markerId; + public final int markerDisabledId; + + CacheRealm(String id, String name, int markerId, int markerDisabledId) { + this.id = id; + this.name = name; + this.markerId = markerId; + this.markerDisabledId = markerDisabledId; + } +} diff --git a/main/src/cgeo/geocaching/enumerations/CacheSize.java b/main/src/cgeo/geocaching/enumerations/CacheSize.java index 155c9a5..726ebe2 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheSize.java +++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java @@ -5,6 +5,7 @@ import cgeo.geocaching.cgeoapplication; import java.util.Collections; import java.util.HashMap; +import java.util.Locale; import java.util.Map; /** @@ -24,7 +25,7 @@ public enum CacheSize { public final int comparable; private final int stringId; - private CacheSize(String id, int comparable, int stringId) { + CacheSize(String id, int comparable, int stringId) { this.id = id; this.comparable = comparable; this.stringId = stringId; @@ -34,7 +35,7 @@ public enum CacheSize { static { final HashMap<String, CacheSize> mapping = new HashMap<String, CacheSize>(); for (CacheSize cs : values()) { - mapping.put(cs.id.toLowerCase(), cs); + mapping.put(cs.id.toLowerCase(Locale.US), cs); } // add medium as additional string for Regular mapping.put("medium", CacheSize.REGULAR); @@ -51,7 +52,7 @@ public enum CacheSize { return result; } // only if String was not found, normalize it - final CacheSize resultNormalized = CacheSize.FIND_BY_ID.get(id.toLowerCase().trim()); + final CacheSize resultNormalized = CacheSize.FIND_BY_ID.get(id.toLowerCase(Locale.US).trim()); if (resultNormalized != null) { return resultNormalized; } diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java index 730c989..88bded2 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheType.java @@ -5,6 +5,7 @@ import cgeo.geocaching.cgeoapplication; import java.util.Collections; import java.util.HashMap; +import java.util.Locale; import java.util.Map; /** @@ -44,7 +45,7 @@ public enum CacheType { private final int stringId; public final int markerId; - private CacheType(String id, String pattern, String guid, int stringId, int markerId) { + CacheType(String id, String pattern, String guid, int stringId, int markerId) { this.id = id; this.pattern = pattern; this.guid = guid; @@ -59,14 +60,14 @@ public enum CacheType { final HashMap<String, CacheType> mappingPattern = new HashMap<String, CacheType>(); for (CacheType ct : values()) { mappingId.put(ct.id, ct); - mappingPattern.put(ct.pattern.toLowerCase(), ct); + mappingPattern.put(ct.pattern.toLowerCase(Locale.US), ct); } FIND_BY_ID = Collections.unmodifiableMap(mappingId); FIND_BY_PATTERN = Collections.unmodifiableMap(mappingPattern); } public static CacheType getById(final String id) { - final CacheType result = (id != null) ? CacheType.FIND_BY_ID.get(id.toLowerCase().trim()) : null; + final CacheType result = (id != null) ? CacheType.FIND_BY_ID.get(id.toLowerCase(Locale.US).trim()) : null; if (result == null) { return UNKNOWN; } @@ -74,7 +75,7 @@ public enum CacheType { } public static CacheType getByPattern(final String pattern) { - final CacheType result = (pattern != null) ? CacheType.FIND_BY_PATTERN.get(pattern.toLowerCase().trim()) : null; + final CacheType result = (pattern != null) ? CacheType.FIND_BY_PATTERN.get(pattern.toLowerCase(Locale.US).trim()) : null; if (result == null) { return UNKNOWN; } @@ -88,4 +89,9 @@ public enum CacheType { public boolean isEvent() { return CacheType.EVENT == this || CacheType.MEGA_EVENT == this || CacheType.CITO == this || CacheType.LOSTANDFOUND == this; } + + @Override + public String toString() { + return getL10n(); + } } diff --git a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java index e9dbc5d..5f5b2c9 100644 --- a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java +++ b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java @@ -26,7 +26,7 @@ public interface LiveMapStrategy { public final EnumSet<StrategyFlag> flags; private final int stringId; - private Strategy(int id, EnumSet<StrategyFlag> flags, int stringId) { + Strategy(int id, EnumSet<StrategyFlag> flags, int stringId) { this.id = id; this.flags = flags; this.stringId = stringId; diff --git a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java b/main/src/cgeo/geocaching/enumerations/LocationProviderType.java index 36a09bf..f2c79fe 100644 --- a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java +++ b/main/src/cgeo/geocaching/enumerations/LocationProviderType.java @@ -9,7 +9,7 @@ public enum LocationProviderType { public final int resourceId; - private LocationProviderType(final int resourceId) { + LocationProviderType(final int resourceId) { this.resourceId = resourceId; } } diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java index 332ef03..71a5146 100644 --- a/main/src/cgeo/geocaching/enumerations/LogType.java +++ b/main/src/cgeo/geocaching/enumerations/LogType.java @@ -5,6 +5,7 @@ import cgeo.geocaching.cgeoapplication; import java.util.Collections; import java.util.HashMap; +import java.util.Locale; import java.util.Map; @@ -14,43 +15,50 @@ import java.util.Map; */ public enum LogType { - FOUND_IT(2, "2", "found it", R.string.log_found), - DIDNT_FIND_IT(3, "3", "didn't find it", R.string.log_dnf), + FOUND_IT(2, "2", "found it", R.string.log_found, R.drawable.mark_green), + DIDNT_FIND_IT(3, "3", "didn't find it", R.string.log_dnf, R.drawable.mark_red), NOTE(4, "4", "write note", R.string.log_note), - PUBLISH_LISTING(1003, "24", "publish listing", R.string.log_published), - ENABLE_LISTING(23, "23", "enable listing", R.string.log_enabled), - ARCHIVE(5, "5", "archive", R.string.log_archived), - UNARCHIVE(12, "12", "unarchive", R.string.log_unarchived), - TEMP_DISABLE_LISTING(22, "22", "temporarily disable listing", R.string.log_disabled), - NEEDS_ARCHIVE(7, "7", "needs archived", R.string.log_needs_archived), + PUBLISH_LISTING(1003, "24", "publish listing", R.string.log_published, R.drawable.mark_green_more), + ENABLE_LISTING(23, "23", "enable listing", R.string.log_enabled, R.drawable.mark_green_more), + ARCHIVE(5, "5", "archive", R.string.log_archived, R.drawable.mark_red_more), + UNARCHIVE(12, "12", "unarchive", R.string.log_unarchived, R.drawable.mark_green_more), + TEMP_DISABLE_LISTING(22, "22", "temporarily disable listing", R.string.log_disabled, R.drawable.mark_red_more), + NEEDS_ARCHIVE(7, "7", "needs archived", R.string.log_needs_archived, R.drawable.mark_red), WILL_ATTEND(9, "9", "will attend", R.string.log_attend), - ATTENDED(10, "10", "attended", R.string.log_attended), - RETRIEVED_IT(13, "13", "retrieved it", R.string.log_retrieved), - PLACED_IT(14, "14", "placed it", R.string.log_placed), - GRABBED_IT(19, "19", "grabbed it", R.string.log_grabbed), - NEEDS_MAINTENANCE(45, "45", "needs maintenance", R.string.log_maintenance_needed), - OWNER_MAINTENANCE(46, "46", "owner maintenance", R.string.log_maintained), + ATTENDED(10, "10", "attended", R.string.log_attended, R.drawable.mark_green), + RETRIEVED_IT(13, "13", "retrieved it", R.string.log_retrieved, R.drawable.mark_green_more), + PLACED_IT(14, "14", "placed it", R.string.log_placed, R.drawable.mark_green_more), + GRABBED_IT(19, "19", "grabbed it", R.string.log_grabbed, R.drawable.mark_green_more), + NEEDS_MAINTENANCE(45, "45", "needs maintenance", R.string.log_maintenance_needed, R.drawable.mark_red), + OWNER_MAINTENANCE(46, "46", "owner maintenance", R.string.log_maintained, R.drawable.mark_green_more), UPDATE_COORDINATES(47, "47", "update coordinates", R.string.log_update), - DISCOVERED_IT(48, "48", "discovered it", R.string.log_discovered), + DISCOVERED_IT(48, "48", "discovered it", R.string.log_discovered, R.drawable.mark_green), POST_REVIEWER_NOTE(18, "68", "post reviewer note", R.string.log_reviewer), - VISIT(1001, "75", "visit", R.string.log_tb_visit), - WEBCAM_PHOTO_TAKEN(11, "11", "webcam photo taken", R.string.log_webcam), + VISIT(1001, "75", "visit", R.string.log_tb_visit, R.drawable.mark_green), + WEBCAM_PHOTO_TAKEN(11, "11", "webcam photo taken", R.string.log_webcam, R.drawable.mark_green), ANNOUNCEMENT(74, "74", "announcement", R.string.log_announcement), MOVE_COLLECTION(69, "69", "unused_collection", R.string.log_movecollection), MOVE_INVENTORY(70, "70", "unused_inventory", R.string.log_moveinventory), RETRACT(25, "25", "retract listing", R.string.log_retractlisting), - UNKNOWN(0, "unknown", "", R.string.err_unknown); // LogType not init. yet + MARKED_MISSING(16, "16", "marked missing", R.string.log_marked_missing, R.drawable.mark_red), + UNKNOWN(0, "unknown", "", R.string.err_unknown, R.drawable.mark_red); // LogType not init. yet public final int id; public final String iconName; public final String type; private final int stringId; + public final int markerId; - private LogType(int id, String iconName, String type, int stringId) { + LogType(int id, String iconName, String type, int stringId, int markerId) { this.id = id; this.iconName = iconName; this.type = type; this.stringId = stringId; + this.markerId = markerId; + } + + LogType(int id, String iconName, String type, int stringId) { + this(id, iconName, type, stringId, R.drawable.mark_gray); } private final static Map<String, LogType> FIND_BY_ICONNAME; @@ -76,7 +84,7 @@ public enum LogType { } public static LogType getByIconName(final String imageType) { - final LogType result = imageType != null ? LogType.FIND_BY_ICONNAME.get(imageType.toLowerCase().trim()) : null; + final LogType result = imageType != null ? LogType.FIND_BY_ICONNAME.get(imageType.toLowerCase(Locale.US).trim()) : null; if (result == null) { return UNKNOWN; } @@ -84,7 +92,7 @@ public enum LogType { } public static LogType getByType(final String type) { - final LogType result = type != null ? LogType.FIND_BY_TYPE.get(type.toLowerCase().trim()) : null; + final LogType result = type != null ? LogType.FIND_BY_TYPE.get(type.toLowerCase(Locale.US).trim()) : null; if (result == null) { return UNKNOWN; } diff --git a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java index 13b8d03..68a17a5 100644 --- a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java +++ b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java @@ -11,7 +11,7 @@ public enum LogTypeTrackable { final public String action; final public int resourceId; - private LogTypeTrackable(int id, String action, int resourceId) { + LogTypeTrackable(int id, String action, int resourceId) { this.id = id; this.action = action; this.resourceId = resourceId; diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java index 52eb318..748c432 100644 --- a/main/src/cgeo/geocaching/enumerations/WaypointType.java +++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java @@ -19,13 +19,14 @@ public enum WaypointType { PUZZLE("puzzle", R.string.wp_puzzle, R.drawable.waypoint_puzzle), STAGE("stage", R.string.wp_stage, R.drawable.waypoint_stage), TRAILHEAD("trailhead", R.string.wp_trailhead, R.drawable.waypoint_trailhead), - WAYPOINT("waypoint", R.string.wp_waypoint, R.drawable.waypoint_waypoint); + WAYPOINT("waypoint", R.string.wp_waypoint, R.drawable.waypoint_waypoint), + ORIGINAL("original", R.string.wp_original, R.drawable.waypoint_waypoint); public final String id; public final int stringId; public final int markerId; - private WaypointType(String id, int stringId, int markerId) { + WaypointType(String id, int stringId, int markerId) { this.id = id; this.stringId = stringId; this.markerId = markerId; @@ -36,13 +37,13 @@ public enum WaypointType { * non public so that <code>null</code> handling can be handled centrally in the enum type itself */ private static final Map<String, WaypointType> FIND_BY_ID; - public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN = new HashSet<WaypointType>(); + public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL = new HashSet<WaypointType>(); static { final HashMap<String, WaypointType> mapping = new HashMap<String, WaypointType>(); for (WaypointType wt : values()) { mapping.put(wt.id, wt); - if (wt != WaypointType.OWN) { - ALL_TYPES_EXCEPT_OWN.add(wt); + if (wt != WaypointType.OWN && wt != WaypointType.ORIGINAL) { + ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL.add(wt); } } FIND_BY_ID = Collections.unmodifiableMap(mapping); @@ -67,7 +68,6 @@ public enum WaypointType { return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId); } - @Override public final String toString() { return getL10n(); diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java index 11214db..de78c22 100644 --- a/main/src/cgeo/geocaching/export/FieldnoteExport.java +++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java @@ -2,16 +2,18 @@ package cgeo.geocaching.export; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; -import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.Progress; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgData; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.utils.IOUtils; import cgeo.geocaching.utils.Log; +import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import android.app.Activity; @@ -31,6 +33,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.TimeZone; /** * Exports offline-logs in the Groundspeak Field Note format.<br> @@ -42,6 +45,9 @@ import java.util.Locale; class FieldnoteExport extends AbstractExport { private static final File exportLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/field-notes"); private static final SimpleDateFormat fieldNoteDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + static { + fieldNoteDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + } protected FieldnoteExport() { super(getString(R.string.export_fieldnotes)); @@ -135,13 +141,11 @@ class FieldnoteExport extends AbstractExport { @Override protected Boolean doInBackground(Void... params) { final StringBuilder fieldNoteBuffer = new StringBuilder(); - final cgeoapplication app = cgeoapplication.getInstance(); - try { int i = 0; for (cgCache cache : caches) { if (cache.isLogOffline()) { - appendFieldNote(fieldNoteBuffer, cache, app.loadLogOffline(cache.getGeocode())); + appendFieldNote(fieldNoteBuffer, cache, cgData.loadLogOffline(cache.getGeocode())); publishProgress(++i); } } @@ -152,40 +156,30 @@ class FieldnoteExport extends AbstractExport { fieldNoteBuffer.append('\n'); - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - exportLocation.mkdirs(); + if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + return false; + } - SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US); - exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt"); + exportLocation.mkdirs(); - OutputStream os; - Writer fw = null; - try { - os = new FileOutputStream(exportFile); - fw = new OutputStreamWriter(os, "UTF-16"); - fw.write(fieldNoteBuffer.toString()); - } catch (IOException e) { - Log.e("FieldnoteExport.ExportTask export", e); - return false; - } finally { - if (fw != null) { - try { - fw.close(); - } catch (IOException e) { - Log.e("FieldnoteExport.ExportTask export", e); - return false; - } - } - } - } else { + SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US); + exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt"); + + Writer fw = null; + try { + OutputStream os = new FileOutputStream(exportFile); + fw = new OutputStreamWriter(os, CharEncoding.UTF_16); + fw.write(fieldNoteBuffer.toString()); + } catch (IOException e) { + Log.e("FieldnoteExport.ExportTask export", e); return false; + } finally { + IOUtils.closeQuietly(fw); } if (upload) { publishProgress(STATUS_UPLOAD); - final String uri = "http://www.geocaching.com/my/uploadfieldnotes.aspx"; - if (!Login.isActualLoginStatus()) { // no need to upload (possibly large file) if we're not logged in final StatusCode loginState = Login.login(); @@ -194,6 +188,7 @@ class FieldnoteExport extends AbstractExport { } } + final String uri = "http://www.geocaching.com/my/uploadfieldnotes.aspx"; String page = Network.getResponseData(Network.getRequest(uri)); if (!Login.getLoginStatus(page)) { diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java index 7573db9..9f6642f 100644 --- a/main/src/cgeo/geocaching/export/GpxExport.java +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -3,9 +3,9 @@ package cgeo.geocaching.export; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.Settings; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.enumerations.CacheAttribute; @@ -51,7 +51,7 @@ class GpxExport extends AbstractExport { if (null == activity) { // No activity given, so no user interaction possible. // Start export with default parameters. - new ExportTask(caches, activity).execute((Void) null); + new ExportTask(caches, null).execute((Void) null); } else { // Show configuration dialog @@ -143,8 +143,7 @@ class GpxExport extends AbstractExport { gpx.write("<gpx version=\"1.0\" creator=\"c:geo - http://www.cgeo.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/cache.xsd\">"); for (int i = 0; i < caches.size(); i++) { - // reload the cache. otherwise logs, attributes and other detailed information is not available - final cgCache cache = cgeoapplication.getInstance().loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY); + final cgCache cache = cgData.loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY); gpx.write("<wpt "); gpx.write("lat=\""); @@ -283,10 +282,10 @@ class GpxExport extends AbstractExport { } private void writeWaypoints(final cgCache cache) throws IOException { - List<cgWaypoint> waypoints = cache.getWaypoints(); - List<cgWaypoint> ownWaypoints = new ArrayList<cgWaypoint>(waypoints.size()); - List<cgWaypoint> originWaypoints = new ArrayList<cgWaypoint>(waypoints.size()); - for (cgWaypoint wp : cache.getWaypoints()) { + List<Waypoint> waypoints = cache.getWaypoints(); + List<Waypoint> ownWaypoints = new ArrayList<Waypoint>(waypoints.size()); + List<Waypoint> originWaypoints = new ArrayList<Waypoint>(waypoints.size()); + for (Waypoint wp : cache.getWaypoints()) { if (wp.isUserDefined()) { ownWaypoints.add(wp); } else { @@ -294,7 +293,7 @@ class GpxExport extends AbstractExport { } } int maxPrefix = 0; - for (cgWaypoint wp : originWaypoints) { + for (Waypoint wp : originWaypoints) { String prefix = wp.getPrefix(); try { maxPrefix = Math.max(Integer.parseInt(prefix), maxPrefix); @@ -303,7 +302,7 @@ class GpxExport extends AbstractExport { } writeCacheWaypoint(wp, prefix); } - for (cgWaypoint wp : ownWaypoints) { + for (Waypoint wp : ownWaypoints) { maxPrefix++; String prefix = StringUtils.leftPad(String.valueOf(maxPrefix), 2, '0'); writeCacheWaypoint(wp, prefix); @@ -319,7 +318,7 @@ class GpxExport extends AbstractExport { * @param prefix * @throws IOException */ - private void writeCacheWaypoint(final cgWaypoint wp, final String prefix) throws IOException { + private void writeCacheWaypoint(final Waypoint wp, final String prefix) throws IOException { gpx.write("<wpt lat=\""); final Geopoint coords = wp.getCoords(); gpx.write(coords != null ? Double.toString(coords.getLatitude()) : ""); // TODO: check whether is the best way to handle unknown waypoint coordinates diff --git a/main/src/cgeo/geocaching/files/FileList.java b/main/src/cgeo/geocaching/files/FileList.java index df95085..42c9f16 100644 --- a/main/src/cgeo/geocaching/files/FileList.java +++ b/main/src/cgeo/geocaching/files/FileList.java @@ -4,6 +4,7 @@ import cgeo.geocaching.R; import cgeo.geocaching.StoredList; import cgeo.geocaching.activity.AbstractListActivity; import cgeo.geocaching.utils.FileUtils; +import cgeo.geocaching.utils.IOUtils; import cgeo.geocaching.utils.Log; import org.apache.commons.collections.CollectionUtils; @@ -182,7 +183,7 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis Log.w("No external media mounted."); } } catch (Exception e) { - Log.e("cgFileList.loadFiles.run: " + e.toString()); + Log.e("cgFileList.loadFiles.run", e); } changeWaitDialogHandler.sendMessage(Message.obtain(changeWaitDialogHandler, 0, "loaded directories")); @@ -242,15 +243,8 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis Log.e("Could not get additional mount points for user content. " + "Proceeding with external storage only (" + extStorage + ")"); } finally { - try { - if (fr != null) { - fr.close(); - } - if (br != null) { - br.close(); - } - } catch (IOException e) { - } + IOUtils.closeQuietly(fr); + IOUtils.closeQuietly(br); } } return storages; @@ -283,8 +277,8 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis private void setExtensions(final String[] extensionsIn) { extensions = extensionsIn; for (int i = 0; i < extensions.length; i++) { - String extension = extensions[i]; - if (extension.length() == 0 || extension.charAt(0) != '.') { + final String extension = extensions[i]; + if (StringUtils.isEmpty(extension) || extension.charAt(0) != '.') { extensions[i] = "." + extension; } } diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java index fb78360..750d5e0 100644 --- a/main/src/cgeo/geocaching/files/GPXImporter.java +++ b/main/src/cgeo/geocaching/files/GPXImporter.java @@ -5,7 +5,7 @@ import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings;
import cgeo.geocaching.StaticMapsProvider;
import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.IAbstractActivity;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -124,7 +124,7 @@ public class GPXImporter { final Handler importStepHandler;
final CancellableHandler progressHandler;
- public ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ protected ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
this.listId = listId;
this.importStepHandler = importStepHandler;
this.progressHandler = progressHandler;
@@ -132,10 +132,9 @@ public class GPXImporter { @Override
public void run() {
- final Collection<cgCache> caches;
try {
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_START));
- caches = doImport();
+ final Collection<cgCache> caches = doImport();
Log.i("Imported successfully " + caches.size() + " caches.");
final SearchResult search = new SearchResult();
@@ -171,10 +170,9 @@ public class GPXImporter { protected abstract Collection<cgCache> doImport() throws IOException, ParserException;
private boolean importStaticMaps(final SearchResult importedCaches) {
- final cgeoapplication app = cgeoapplication.getInstance();
int storedCacheMaps = 0;
for (String geocode : importedCaches.getGeocodes()) {
- cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
StaticMapsProvider.downloadMaps(cache);
storedCacheMaps++;
@@ -206,7 +204,7 @@ public class GPXImporter { static abstract class ImportGpxThread extends ImportThread {
- public ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ protected ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
}
@@ -276,7 +274,7 @@ public class GPXImporter { static abstract class ImportGpxZipThread extends ImportGpxThread {
- public ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ protected ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
}
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java index b9d3f53..22a7f41 100644 --- a/main/src/cgeo/geocaching/files/GPXParser.java +++ b/main/src/cgeo/geocaching/files/GPXParser.java @@ -3,9 +3,10 @@ package cgeo.geocaching.files; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.StoredList; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgTrackable; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.cgData; +import cgeo.geocaching.Trackable; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.enumerations.CacheSize; @@ -18,6 +19,7 @@ import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.lang3.StringUtils; import org.xml.sax.Attributes; @@ -41,7 +43,6 @@ import java.util.EnumSet; import java.util.HashSet; import java.util.Locale; import java.util.Set; -import java.util.regex.Matcher; import java.util.regex.Pattern; public abstract class GPXParser extends FileParser { @@ -80,7 +81,7 @@ public abstract class GPXParser extends FileParser { final private String version; private cgCache cache; - private cgTrackable trackable = new cgTrackable(); + private Trackable trackable = new Trackable(); private LogEntry log = null; private String type = null; @@ -208,7 +209,7 @@ public abstract class GPXParser extends FileParser { return null; } // cut out baseName - final Matcher m = BASENAME_PATTERN.matcher(stringName); + final MatcherWrapper m = new MatcherWrapper(BASENAME_PATTERN, stringName); if (!m.matches()) { return null; } @@ -234,7 +235,7 @@ public abstract class GPXParser extends FileParser { static Date parseDate(String inputUntrimmed) throws ParseException { String input = inputUntrimmed.trim(); // remove milliseconds to reduce number of needed patterns - final Matcher matcher = PATTERN_MILLISECONDS.matcher(input); + final MatcherWrapper matcher = new MatcherWrapper(PATTERN_MILLISECONDS, input); input = matcher.replaceFirst(""); if (input.contains("Z")) { return formatSimpleZ.parse(input); @@ -287,7 +288,7 @@ public abstract class GPXParser extends FileParser { // take the name as code, if nothing else is available if (StringUtils.isBlank(cache.getGeocode())) { if (StringUtils.isNotBlank(name)) { - cache.setGeocode(name.trim().toUpperCase()); + cache.setGeocode(name.trim()); } } @@ -311,8 +312,8 @@ public abstract class GPXParser extends FileParser { // finally store the cache in the database result.add(geocode); - cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); - cgeoapplication.getInstance().removeAllFromCache(); + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + cgData.removeAllFromCache(); showProgressMessage(progressHandler, progressStream.getProgress()); } else if (StringUtils.isNotBlank(cache.getName()) && StringUtils.containsIgnoreCase(type, "waypoint")) { @@ -326,12 +327,11 @@ public abstract class GPXParser extends FileParser { fixCache(cache); if (cache.getName().length() > 2) { - final String cacheGeocodeForWaypoint = "GC" + cache.getName().substring(2).toUpperCase(); - + final String cacheGeocodeForWaypoint = "GC" + cache.getName().substring(2).toUpperCase(Locale.US); // lookup cache for waypoint in already parsed caches - final cgCache cacheForWaypoint = cgeoapplication.getInstance().loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB); + final cgCache cacheForWaypoint = cgData.loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB); if (cacheForWaypoint != null) { - final cgWaypoint waypoint = new cgWaypoint(cache.getShortdesc(), convertWaypointSym2Type(sym), false); + final Waypoint waypoint = new Waypoint(cache.getShortdesc(), convertWaypointSym2Type(sym), false); waypoint.setId(-1); waypoint.setGeocode(cacheGeocodeForWaypoint); waypoint.setPrefix(cache.getName().substring(0, 2)); @@ -340,14 +340,14 @@ public abstract class GPXParser extends FileParser { waypoint.setCoords(cache.getCoords()); waypoint.setNote(cache.getDescription()); - final ArrayList<cgWaypoint> mergedWayPoints = new ArrayList<cgWaypoint>(); + final ArrayList<Waypoint> mergedWayPoints = new ArrayList<Waypoint>(); mergedWayPoints.addAll(cacheForWaypoint.getWaypoints()); - final ArrayList<cgWaypoint> newPoints = new ArrayList<cgWaypoint>(); + final ArrayList<Waypoint> newPoints = new ArrayList<Waypoint>(); newPoints.add(waypoint); - cgWaypoint.mergeWayPoints(newPoints, mergedWayPoints, true); + Waypoint.mergeWayPoints(newPoints, mergedWayPoints, true); cacheForWaypoint.setWaypoints(newPoints, false); - cgeoapplication.getInstance().saveCache(cacheForWaypoint, EnumSet.of(SaveFlag.SAVE_DB)); + cgData.saveCache(cacheForWaypoint, EnumSet.of(SaveFlag.SAVE_DB)); showProgressMessage(progressHandler, progressStream.getProgress()); } } @@ -362,7 +362,7 @@ public abstract class GPXParser extends FileParser { try { cache.setHidden(parseDate(body)); } catch (Exception e) { - Log.w("Failed to parse cache date: " + e.toString()); + Log.w("Failed to parse cache date", e); } } }); @@ -410,7 +410,7 @@ public abstract class GPXParser extends FileParser { public void end(String body) { final String[] content = body.split("\\|"); if (content.length > 0) { - type = content[0].toLowerCase().trim(); + type = content[0].toLowerCase(Locale.US).trim(); } } }); @@ -420,7 +420,7 @@ public abstract class GPXParser extends FileParser { @Override public void end(final String body) { - sym = body.toLowerCase(); + sym = body.toLowerCase(Locale.US); if (sym.contains("geocache") && sym.contains("found")) { cache.setFound(true); } @@ -432,14 +432,14 @@ public abstract class GPXParser extends FileParser { @Override public void end(String url) { - final Matcher matcher = patternGuid.matcher(url); + final MatcherWrapper matcher = new MatcherWrapper(patternGuid, url); if (matcher.matches()) { final String guid = matcher.group(1); if (StringUtils.isNotBlank(guid)) { cache.setGuid(guid); } } - final Matcher matcherCode = patternUrlGeocode.matcher(url); + final MatcherWrapper matcherCode = new MatcherWrapper(patternUrlGeocode, url); if (matcherCode.matches()) { String geocode = matcherCode.group(1); cache.setGeocode(geocode); @@ -526,7 +526,7 @@ public abstract class GPXParser extends FileParser { @Override public void end(String body) { - cache.setType(CacheType.getByPattern(validate(body.toLowerCase()))); + cache.setType(CacheType.getByPattern(validate(body))); } }); @@ -535,7 +535,7 @@ public abstract class GPXParser extends FileParser { @Override public void end(String body) { - cache.setSize(CacheSize.getById(validate(body.toLowerCase()))); + cache.setSize(CacheSize.getById(validate(body))); } }); @@ -578,7 +578,7 @@ public abstract class GPXParser extends FileParser { try { cache.setDifficulty(Float.parseFloat(body)); } catch (NumberFormatException e) { - Log.w("Failed to parse difficulty: " + e.toString()); + Log.w("Failed to parse difficulty", e); } } }); @@ -591,7 +591,7 @@ public abstract class GPXParser extends FileParser { try { cache.setTerrain(Float.parseFloat(body)); } catch (NumberFormatException e) { - Log.w("Failed to parse terrain: " + e.toString()); + Log.w("Failed to parse terrain", e); } } }); @@ -661,11 +661,11 @@ public abstract class GPXParser extends FileParser { @Override public void start(Attributes attrs) { - trackable = new cgTrackable(); + trackable = new Trackable(); try { if (attrs.getIndex("ref") > -1) { - trackable.setGeocode(attrs.getValue("ref").toUpperCase()); + trackable.setGeocode(attrs.getValue("ref")); } } catch (Exception e) { // nothing @@ -679,7 +679,7 @@ public abstract class GPXParser extends FileParser { public void end() { if (StringUtils.isNotBlank(trackable.getGeocode()) && StringUtils.isNotBlank(trackable.getName())) { if (cache.getInventory() == null) { - cache.setInventory(new ArrayList<cgTrackable>()); + cache.setInventory(new ArrayList<Trackable>()); } cache.getInventory().add(trackable); } @@ -735,7 +735,7 @@ public abstract class GPXParser extends FileParser { try { log.date = parseDate(body).getTime(); } catch (Exception e) { - Log.w("Failed to parse log date: " + e.toString()); + Log.w("Failed to parse log date", e); } } }); @@ -745,7 +745,7 @@ public abstract class GPXParser extends FileParser { @Override public void end(String body) { - final String logType = validate(body).toLowerCase(); + final String logType = validate(body); log.type = LogType.getByType(logType); } }); @@ -772,9 +772,9 @@ public abstract class GPXParser extends FileParser { try { progressStream = new ProgressInputStream(stream); Xml.parse(progressStream, Xml.Encoding.UTF_8, root.getContentHandler()); - return cgeoapplication.getInstance().loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL)); + return cgData.loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL)); } catch (SAXException e) { - Log.e("Cannot parse .gpx file as GPX " + version + ": could not parse XML - " + e.toString()); + Log.w("Cannot parse .gpx file as GPX " + version + ": could not parse XML - ", e); throw new ParserException("Cannot parse .gpx file as GPX " + version + ": could not parse XML", e); } } @@ -806,17 +806,21 @@ public abstract class GPXParser extends FileParser { static WaypointType convertWaypointSym2Type(final String sym) { if ("parking area".equalsIgnoreCase(sym)) { return WaypointType.PARKING; - } else if ("stages of a multicache".equalsIgnoreCase(sym)) { + } + if ("stages of a multicache".equalsIgnoreCase(sym)) { return WaypointType.STAGE; - } else if ("question to answer".equalsIgnoreCase(sym)) { + } + if ("question to answer".equalsIgnoreCase(sym)) { return WaypointType.PUZZLE; - } else if ("trailhead".equalsIgnoreCase(sym)) { + } + if ("trailhead".equalsIgnoreCase(sym)) { return WaypointType.TRAILHEAD; - } else if ("final location".equalsIgnoreCase(sym)) { + } + if ("final location".equalsIgnoreCase(sym)) { return WaypointType.FINAL; } // this is not fully correct, but lets also look for localized waypoint types - for (WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN) { + for (WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) { final String localized = waypointType.getL10n(); if (StringUtils.isNotEmpty(localized)) { if (localized.equalsIgnoreCase(sym)) { @@ -832,7 +836,7 @@ public abstract class GPXParser extends FileParser { return; } final String trimmed = input.trim(); - final Matcher matcherGeocode = patternGeocode.matcher(trimmed); + final MatcherWrapper matcherGeocode = new MatcherWrapper(patternGeocode, trimmed); if (matcherGeocode.find()) { final String geocode = matcherGeocode.group(1); // a geocode should not be part of a word diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java index b17b203..730e224 100644 --- a/main/src/cgeo/geocaching/files/LocParser.java +++ b/main/src/cgeo/geocaching/files/LocParser.java @@ -2,13 +2,14 @@ package cgeo.geocaching.files; import cgeo.geocaching.SearchResult; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.lang3.StringUtils; @@ -22,7 +23,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.regex.Matcher; import java.util.regex.Pattern; public final class LocParser extends FileParser { @@ -65,7 +65,7 @@ public final class LocParser extends FileParser { contained.add(geocode); } } - Set<cgCache> caches = cgeoapplication.getInstance().loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB); + Set<cgCache> caches = cgData.loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB); for (cgCache cache : caches) { cgCache coord = cidCoords.get(cache.getGeocode()); copyCoordToCache(coord, cache); @@ -77,7 +77,7 @@ public final class LocParser extends FileParser { cache.setDifficulty(coord.getDifficulty()); cache.setTerrain(coord.getTerrain()); cache.setSize(coord.getSize()); - cache.setGeocode(coord.getGeocode().toUpperCase()); + cache.setGeocode(coord.getGeocode()); cache.setReliableLatLon(true); if (StringUtils.isBlank(cache.getName())) { cache.setName(coord.getName()); @@ -140,6 +140,7 @@ public final class LocParser extends FileParser { cache.setType(CacheType.UNKNOWN); // type is not given in the LOC file cache.setListId(listId); cache.setDetailed(true); + cache.store(null); } Log.i("Caches found in .loc file: " + caches.size()); return caches; @@ -147,13 +148,12 @@ public final class LocParser extends FileParser { public static cgCache parseCache(final String pointString) { final cgCache cache = new cgCache(); - final Matcher matcherGeocode = patternGeocode.matcher(pointString); + final MatcherWrapper matcherGeocode = new MatcherWrapper(patternGeocode, pointString); if (matcherGeocode.find()) { - final String geocode = matcherGeocode.group(1).trim().toUpperCase(); - cache.setGeocode(geocode.toUpperCase()); + cache.setGeocode(matcherGeocode.group(1).trim()); } - final Matcher matcherName = patternName.matcher(pointString); + final MatcherWrapper matcherName = new MatcherWrapper(patternName, pointString); if (matcherName.find()) { final String name = matcherName.group(1).trim(); cache.setName(StringUtils.substringBeforeLast(name, " by ").trim()); @@ -161,28 +161,32 @@ public final class LocParser extends FileParser { cache.setName(cache.getGeocode()); } - final Matcher matcherLat = patternLat.matcher(pointString); - final Matcher matcherLon = patternLon.matcher(pointString); + final MatcherWrapper matcherLat = new MatcherWrapper(patternLat, pointString); + final MatcherWrapper matcherLon = new MatcherWrapper(patternLon, pointString); if (matcherLat.find() && matcherLon.find()) { cache.setCoords(parsePoint(matcherLat.group(1).trim(), matcherLon.group(1).trim())); } - final Matcher matcherDifficulty = patternDifficulty.matcher(pointString); - if (matcherDifficulty.find()) { - cache.setDifficulty(Float.parseFloat(matcherDifficulty.group(1).trim())); - } + final MatcherWrapper matcherDifficulty = new MatcherWrapper(patternDifficulty, pointString); + try { + if (matcherDifficulty.find()) { + cache.setDifficulty(Float.parseFloat(matcherDifficulty.group(1).trim())); + } - final Matcher matcherTerrain = patternTerrain.matcher(pointString); - if (matcherTerrain.find()) { - cache.setTerrain(Float.parseFloat(matcherTerrain.group(1).trim())); - } + final MatcherWrapper matcherTerrain = new MatcherWrapper(patternTerrain, pointString); + if (matcherTerrain.find()) { + cache.setTerrain(Float.parseFloat(matcherTerrain.group(1).trim())); + } - final Matcher matcherContainer = patternContainer.matcher(pointString); - if (matcherContainer.find()) { - final int size = Integer.parseInt(matcherContainer.group(1).trim()); - if (size >= 1 && size <= 8) { - cache.setSize(SIZES[size - 1]); + final MatcherWrapper matcherContainer = new MatcherWrapper(patternContainer, pointString); + if (matcherContainer.find()) { + final int size = Integer.parseInt(matcherContainer.group(1).trim()); + if (size >= 1 && size <= 8) { + cache.setSize(SIZES[size - 1]); + } } + } catch (NumberFormatException e) { + Log.e("LocParser.parseCache", e); } return cache; diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java index c392564..f59f15c 100644 --- a/main/src/cgeo/geocaching/files/LocalStorage.java +++ b/main/src/cgeo/geocaching/files/LocalStorage.java @@ -305,9 +305,9 @@ public class LocalStorage { } private static boolean copy(final InputStream input, final OutputStream output) { - final byte[] buffer = new byte[4096]; - int length; try { + int length; + final byte[] buffer = new byte[4096]; while ((length = input.read(buffer)) > 0) { output.write(buffer, 0, length); } @@ -363,7 +363,7 @@ public class LocalStorage { Log.w("LocalStorage.deleteFilesPrefix: Can't delete file " + file.getName()); } } catch (Exception e) { - Log.e("LocalStorage.deleteFilesPrefix: " + e.toString()); + Log.e("LocalStorage.deleteFilesPrefix", e); } } } diff --git a/main/src/cgeo/geocaching/files/ParserException.java b/main/src/cgeo/geocaching/files/ParserException.java index 5aa152c..c0076cc 100644 --- a/main/src/cgeo/geocaching/files/ParserException.java +++ b/main/src/cgeo/geocaching/files/ParserException.java @@ -13,10 +13,6 @@ public class ParserException extends Exception { super(detailMessage); } - public ParserException(Throwable throwable) { - super(throwable); - } - public ParserException(String detailMessage, Throwable throwable) { super(detailMessage, throwable); } diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java index 404777a..c59b0cb 100644 --- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java +++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java @@ -18,7 +18,6 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.ListView; import android.widget.TextView; import java.io.File; @@ -107,11 +106,6 @@ public class SimpleDirChooser extends ListActivity { this.setListAdapter(adapter); } - @Override - protected void onListItemClick(ListView l, View v, int position, long id) { - super.onListItemClick(l, v, position, id); - } - public class FileArrayAdapter extends ArrayAdapter<Option> { private Context content; @@ -206,7 +200,7 @@ public class SimpleDirChooser extends ListActivity { } } - public class Option implements Comparable<Option> { + public static class Option implements Comparable<Option> { private final String name; private final String path; private boolean checked = false; diff --git a/main/src/cgeo/geocaching/filter/AbstractFilter.java b/main/src/cgeo/geocaching/filter/AbstractFilter.java index 44d6d3f..f78a218 100644 --- a/main/src/cgeo/geocaching/filter/AbstractFilter.java +++ b/main/src/cgeo/geocaching/filter/AbstractFilter.java @@ -8,7 +8,7 @@ import java.util.List; abstract class AbstractFilter implements IFilter { private final String name; - public AbstractFilter(String name) { + protected AbstractFilter(String name) { this.name = name; } diff --git a/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java b/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java index ff3fce5..e84174a 100644 --- a/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java +++ b/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java @@ -8,8 +8,8 @@ abstract class AbstractRangeFilter extends AbstractFilter { protected final float rangeMin; protected final float rangeMax; - public AbstractRangeFilter(int ressourceId, int range) { - super(cgeoapplication.getInstance().getResources().getString(ressourceId) + ' ' + (range == 5 ? '5' : String.valueOf(range) + " + " + String.format("%.1f", range + 0.5))); + protected AbstractRangeFilter(int ressourceId, int range) { + super(cgeoapplication.getInstance().getResources().getString(ressourceId) + ' ' + (range == 5 ? '5' : range + " + " + String.format("%.1f", range + 0.5))); this.rangeMin = range; rangeMax = rangeMin + 1f; } diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java index 2565178..837e9d1 100644 --- a/main/src/cgeo/geocaching/filter/AttributeFilter.java +++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java @@ -2,6 +2,7 @@ package cgeo.geocaching.filter; import cgeo.geocaching.R; import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; @@ -34,7 +35,7 @@ class AttributeFilter extends AbstractFilter { @Override public boolean accepts(final cgCache cache) { - cgCache fullCache = cgeoapplication.getInstance().loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES)); + cgCache fullCache = cgData.loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES)); if (fullCache == null) { fullCache = cache; } diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java index 230bc91..e2472fd 100644 --- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java +++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java @@ -73,7 +73,7 @@ public final class FilterUserInterface { public void selectFilter(final RunnableWithArgument<IFilter> runAfterwards) { final AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setTitle(R.string.caches_filter); + builder.setTitle(R.string.caches_filter_title); final ArrayAdapter<FactoryEntry> adapter = new ArrayAdapter<FactoryEntry>(activity, android.R.layout.select_dialog_item, registry); diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java index 5a00009..fa17775 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVote.java +++ b/main/src/cgeo/geocaching/gcvote/GCVote.java @@ -6,6 +6,7 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.LeastRecentlyUsedMap; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -15,7 +16,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; import java.util.regex.Pattern; public final class GCVote { @@ -98,17 +98,16 @@ public final class GCVote { return null; } - String voteData; - final Matcher matcherVoteElement = patternVoteElement.matcher(page); + final MatcherWrapper matcherVoteElement = new MatcherWrapper(patternVoteElement, page); while (matcherVoteElement.find()) { - voteData = matcherVoteElement.group(1); + String voteData = matcherVoteElement.group(1); if (voteData == null) { continue; } String guid = null; try { - final Matcher matcherGuid = patternGuid.matcher(voteData); + final MatcherWrapper matcherGuid = new MatcherWrapper(patternGuid, voteData); if (matcherGuid.find()) { if (matcherGuid.groupCount() > 0) { guid = matcherGuid.group(1); @@ -123,7 +122,7 @@ public final class GCVote { boolean loggedIn = false; try { - final Matcher matcherLoggedIn = patternLogIn.matcher(page); + final MatcherWrapper matcherLoggedIn = new MatcherWrapper(patternLogIn, page); if (matcherLoggedIn.find()) { if (matcherLoggedIn.groupCount() > 0) { if (matcherLoggedIn.group(1).equalsIgnoreCase("true")) { @@ -137,7 +136,7 @@ public final class GCVote { float rating = 0; try { - final Matcher matcherRating = patternRating.matcher(voteData); + final MatcherWrapper matcherRating = new MatcherWrapper(patternRating, voteData); if (matcherRating.find()) { rating = Float.parseFloat(matcherRating.group(1)); } @@ -150,7 +149,7 @@ public final class GCVote { int votes = -1; try { - final Matcher matcherVotes = patternVotes.matcher(voteData); + final MatcherWrapper matcherVotes = new MatcherWrapper(patternVotes, voteData); if (matcherVotes.find()) { votes = Integer.parseInt(matcherVotes.group(1)); } @@ -164,7 +163,7 @@ public final class GCVote { float myVote = 0; if (loggedIn) { try { - final Matcher matcherVote = patternVote.matcher(voteData); + final MatcherWrapper matcherVote = new MatcherWrapper(patternVote, voteData); if (matcherVote.find()) { myVote = Float.parseFloat(matcherVote.group(1)); } @@ -180,7 +179,7 @@ public final class GCVote { } } } catch (Exception e) { - Log.e("GCVote.getRating: " + e.toString()); + Log.e("GCVote.getRating", e); } return ratings; @@ -255,7 +254,7 @@ public final class GCVote { } } } catch (Exception e) { - Log.e("GCvote.loadRatings: " + e.toString()); + Log.e("GCvote.loadRatings", e); } } } diff --git a/main/src/cgeo/geocaching/geopoint/DistanceParser.java b/main/src/cgeo/geocaching/geopoint/DistanceParser.java index 5f02895..e1692f4 100644 --- a/main/src/cgeo/geocaching/geopoint/DistanceParser.java +++ b/main/src/cgeo/geocaching/geopoint/DistanceParser.java @@ -1,6 +1,10 @@ package cgeo.geocaching.geopoint; -import java.util.regex.Matcher; +import cgeo.geocaching.utils.MatcherWrapper; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Locale; import java.util.regex.Pattern; public final class DistanceParser { @@ -19,16 +23,16 @@ public final class DistanceParser { * if the given number is invalid */ public static float parseDistance(String distanceText, final boolean metricUnit) { - final Matcher matcher = pattern.matcher(distanceText); + final MatcherWrapper matcher = new MatcherWrapper(pattern, distanceText); if (!matcher.find()) { throw new NumberFormatException(distanceText); } final float value = Float.parseFloat(matcher.group(1).replace(',', '.')); - final String unit = matcher.group(2).toLowerCase(); + final String unit = matcher.group(2).toLowerCase(Locale.US); - if (unit.equals("m") || (unit.length() == 0 && metricUnit)) { + if (unit.equals("m") || (StringUtils.isEmpty(unit) && metricUnit)) { return value / 1000; } if (unit.equals("km")) { diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/geopoint/Geopoint.java index 00dec7f..a4821b9 100644 --- a/main/src/cgeo/geocaching/geopoint/Geopoint.java +++ b/main/src/cgeo/geocaching/geopoint/Geopoint.java @@ -23,6 +23,8 @@ public final class Geopoint implements ICoordinates, Parcelable { public static final double rad2deg = 180 / Math.PI; public static final float erad = 6371.0f; + public static final Geopoint ZERO = new Geopoint(0.0, 0.0); + private final double latitude; private final double longitude; @@ -140,7 +142,7 @@ public final class Geopoint implements ICoordinates, Parcelable { * @param lonSecFrac */ public Geopoint(final String latDir, final String latDeg, final String latMin, final String latSec, final String latSecFrac, - final String lonDir, final String lonDeg, final String lonMin, final String lonSec, final String lonSecFrac) { + final String lonDir, final String lonDeg, final String lonMin, final String lonSec, final String lonSecFrac) { this(latDir + " " + latDeg + " " + latMin + " " + latSec + "." + addZeros(latSecFrac, 3), lonDir + " " + lonDeg + " " + lonMin + " " + lonSec + "." + addZeros(lonSecFrac, 3)); } @@ -253,7 +255,7 @@ public final class Geopoint implements ICoordinates, Parcelable { if (this == obj) { return true; } - if (obj == null || !(obj instanceof Geopoint)) { + if (!(obj instanceof Geopoint)) { return false; } final Geopoint gp = (Geopoint) obj; @@ -274,8 +276,7 @@ public final class Geopoint implements ICoordinates, Parcelable { * tolerance in km * @return true if similar, false otherwise */ - public boolean isEqualTo(Geopoint gp, double tolerance) - { + public boolean isEqualTo(Geopoint gp, double tolerance) { return null != gp && distanceTo(gp) <= tolerance; } @@ -287,42 +288,35 @@ public final class Geopoint implements ICoordinates, Parcelable { * @see GeopointFormatter * @return formatted coordinates */ - public String format(GeopointFormatter.Format format) - { + public String format(GeopointFormatter.Format format) { return GeopointFormatter.format(format, this); } /** * Returns formatted coordinates with default format. * Default format is decimalminutes, e.g. N 52° 36.123 E 010° 03.456 - * + * * @return formatted coordinates */ @Override - public String toString() - { + public String toString() { return format(GeopointFormatter.Format.LAT_LON_DECMINUTE); } - abstract public static class GeopointException - extends RuntimeException - { + abstract public static class GeopointException extends NumberFormatException { private static final long serialVersionUID = 1L; - public GeopointException(String msg) + protected GeopointException(String msg) { super(msg); } } - public static class ParseException - extends GeopointException - { + public static class ParseException extends GeopointException { private static final long serialVersionUID = 1L; public final int resource; - public ParseException(final String msg, final GeopointParser.LatLon faulty) - { + public ParseException(final String msg, final GeopointParser.LatLon faulty) { super(msg); resource = faulty == GeopointParser.LatLon.LAT ? R.string.err_parse_lat : R.string.err_parse_lon; } @@ -350,7 +344,7 @@ public final class Geopoint implements ICoordinates, Parcelable { return result.getDouble("elevation"); } } catch (Exception e) { - Log.w("cgBase.getElevation: " + e.toString()); + Log.w("cgBase.getElevation", e); } return null; diff --git a/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java b/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java index c706e77..0e676ce 100644 --- a/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java +++ b/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java @@ -10,7 +10,7 @@ public class GeopointFormatter /** * Predefined formats. */ - public static enum Format { + public enum Format { /** Example: "10,123456 -0,123456" */ LAT_LON_DECDEGREE, @@ -61,13 +61,13 @@ public class GeopointFormatter switch (format) { case LAT_LON_DECDEGREE: - return String.format("%.6f %.6f", latSigned, lonSigned); + return String.format(Locale.getDefault(), "%.6f %.6f", latSigned, lonSigned); case LAT_LON_DECDEGREE_COMMA: return String.format((Locale) null, "%.6f,%.6f", latSigned, lonSigned); case LAT_LON_DECMINUTE: - return String.format("%c %02d° %06.3f · %c %03d° %06.3f", + return String.format(Locale.getDefault(), "%c %02d° %06.3f · %c %03d° %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw(), gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw()); case LAT_LON_DECMINUTE_RAW: @@ -75,7 +75,7 @@ public class GeopointFormatter gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw(), gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw()); case LAT_LON_DECSECOND: - return String.format("%c %02d° %02d' %06.3f\" · %c %03d° %02d' %06.3f\"", + return String.format(Locale.getDefault(), "%c %02d° %02d' %06.3f\" · %c %03d° %02d' %06.3f\"", gp.getLatDir(), gp.getLatDeg(), gp.getLatMin(), gp.getLatSecRaw(), gp.getLonDir(), gp.getLonDeg(), gp.getLonMin(), gp.getLonSecRaw()); @@ -83,23 +83,22 @@ public class GeopointFormatter return String.format((Locale) null, "%.6f", latSigned); case LAT_DECMINUTE: - return String.format("%c %02d° %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw()); + return String.format(Locale.getDefault(), "%c %02d° %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw()); case LAT_DECMINUTE_RAW: - return String.format("%c %02d %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw()); + return String.format(Locale.getDefault(), "%c %02d %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw()); case LON_DECDEGREE_RAW: return String.format((Locale) null, "%.6f", lonSigned); case LON_DECMINUTE: - return String.format("%c %03d° %06.3f", gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw()); + return String.format(Locale.getDefault(), "%c %03d° %06.3f", gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw()); case LON_DECMINUTE_RAW: - return String.format("%c %03d %06.3f", gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw()); + return String.format(Locale.getDefault(), "%c %03d %06.3f", gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw()); + default: + throw new IllegalArgumentException(); } - - // Keep the compiler happy even though it cannot happen - return null; } } diff --git a/main/src/cgeo/geocaching/geopoint/GeopointParser.java b/main/src/cgeo/geocaching/geopoint/GeopointParser.java index 7604b9d..97a9ec8 100644 --- a/main/src/cgeo/geocaching/geopoint/GeopointParser.java +++ b/main/src/cgeo/geocaching/geopoint/GeopointParser.java @@ -1,9 +1,10 @@ package cgeo.geocaching.geopoint; +import cgeo.geocaching.utils.MatcherWrapper; + import org.apache.commons.lang3.StringUtils; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -105,7 +106,7 @@ class GeopointParser { { final Pattern pattern = LatLon.LAT == latlon ? patternLat : patternLon; - final Matcher matcher = pattern.matcher(text); + final MatcherWrapper matcher = new MatcherWrapper(pattern, text); if (matcher.find()) { final double sign = matcher.group(1).equalsIgnoreCase("S") || matcher.group(1).equalsIgnoreCase("W") ? -1.0 : 1.0; diff --git a/main/src/cgeo/geocaching/geopoint/Viewport.java b/main/src/cgeo/geocaching/geopoint/Viewport.java index 97ee21d..4aca538 100644 --- a/main/src/cgeo/geocaching/geopoint/Viewport.java +++ b/main/src/cgeo/geocaching/geopoint/Viewport.java @@ -164,7 +164,10 @@ public class Viewport { @Override public boolean equals(final Object other) { - if (other == null || !(other instanceof Viewport)) { + if (this == other) { + return true; + } + if (!(other instanceof Viewport)) { return false; } final Viewport vp = (Viewport) other; diff --git a/main/src/cgeo/geocaching/loaders/UrlLoader.java b/main/src/cgeo/geocaching/loaders/UrlLoader.java new file mode 100644 index 0000000..abafd5f --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/UrlLoader.java @@ -0,0 +1,35 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.utils.Log; + +import android.content.Context; +import android.support.v4.content.AsyncTaskLoader; + +public class UrlLoader extends AsyncTaskLoader<String> { + + final private String url; + final private Parameters params; + + public UrlLoader(final Context context, final String url, final Parameters params) { + super(context); + this.url = url; + this.params = params; + } + + @Override + protected void onStartLoading() { + forceLoad(); + } + + @Override + public String loadInBackground() { + try { + return Network.getResponseData(Network.getRequest(url, params)); + } catch (final Exception e) { + Log.w("cgeovisit.UrlLoader.loadInBackground", e); + return null; + } + } +} diff --git a/main/src/cgeo/geocaching/maps/AbstractMapSource.java b/main/src/cgeo/geocaching/maps/AbstractMapSource.java index 90a61d2..1d219d3 100644 --- a/main/src/cgeo/geocaching/maps/AbstractMapSource.java +++ b/main/src/cgeo/geocaching/maps/AbstractMapSource.java @@ -9,7 +9,7 @@ public abstract class AbstractMapSource implements MapSource { private final MapProvider mapProvider; private final String id; - public AbstractMapSource(final String id, final MapProvider mapProvider, final String name) { + protected AbstractMapSource(final String id, final MapProvider mapProvider, final String name) { this.id = id; this.mapProvider = mapProvider; this.name = name; diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 6856a63..47ca240 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -8,8 +8,9 @@ import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; import cgeo.geocaching.StoredList; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.cgeocaches; import cgeo.geocaching.activity.ActivityMixin; @@ -179,7 +180,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto /** List of caches in the viewport */ private LeastRecentlyUsedSet<cgCache> caches = null; /** List of waypoints in the viewport */ - private final LeastRecentlyUsedSet<cgWaypoint> waypoints = new LeastRecentlyUsedSet<cgWaypoint>(MAX_CACHES); + private final LeastRecentlyUsedSet<Waypoint> waypoints = new LeastRecentlyUsedSet<Waypoint>(MAX_CACHES); // storing for offline private ProgressDialog waitDialog = null; private int detailTotal = 0; @@ -226,7 +227,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } countVisibleCaches(); - if (caches != null && caches.size() > 0 && !mapTitle.contains("[")) { + if (caches != null && !caches.isEmpty() && !mapTitle.contains("[")) { title.append(" [").append(cachesCnt); if (cachesCnt != caches.size()) { title.append('/').append(caches.size()); @@ -338,7 +339,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final List<cgCache> protectedCaches = caches.getAsList(); int count = 0; - if (protectedCaches.size() > 0) { + if (!protectedCaches.isEmpty()) { final Viewport viewport = mapView.getViewport(); for (final cgCache cache : protectedCaches) { @@ -368,7 +369,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto activity = this.getActivity(); app = (cgeoapplication) activity.getApplication(); - int countBubbleCnt = app.getAllStoredCachesCount(true, CacheType.ALL); + int countBubbleCnt = cgData.getAllCachesCount(); caches = new LeastRecentlyUsedSet<cgCache>(MAX_CACHES + countBubbleCnt); final MapProvider mapProvider = Settings.getMapProvider(); @@ -494,7 +495,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (!CollectionUtils.isEmpty(dirtyCaches)) { for (String geocode : dirtyCaches) { - cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); // remove to update the cache caches.remove(cache); caches.add(cache); @@ -577,9 +578,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } - MenuItem item; try { - item = menu.findItem(MENU_TRAIL_MODE); // show trail + MenuItem item = menu.findItem(MENU_TRAIL_MODE); if (Settings.isMapTrail()) { item.setTitle(res.getString(R.string.map_trail_hide)); } else { @@ -594,7 +594,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } final Set<String> geocodesInViewport = getGeocodesForCachesInViewport(); - menu.findItem(MENU_STORE_CACHES).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && app.hasUnsavedCaches(new SearchResult(geocodesInViewport))); + menu.findItem(MENU_STORE_CACHES).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches()); item = menu.findItem(MENU_CIRCLE_MODE); // show circles if (overlayCaches != null && overlayCaches.getCircles()) { @@ -610,7 +610,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto menu.findItem(SUBMENU_STRATEGY).setEnabled(isLiveEnabled); } catch (Exception e) { - Log.e("cgeomap.onPrepareOptionsMenu: " + e); + Log.e("cgeomap.onPrepareOptionsMenu", e); } return true; @@ -640,7 +640,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final List<String> geocodes = new ArrayList<String>(); for (final String geocode : geocodesInViewport) { - if (!app.isOffline(geocode, null)) { + if (!cgData.isOffline(geocode, null)) { geocodes.add(geocode); } } @@ -672,7 +672,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto geoDirUpdate.startDir(); } catch (Exception e) { - Log.e("cgeocaches.onPrepareOptionsMenu.onCancel: " + e.toString()); + Log.e("cgeocaches.onPrepareOptionsMenu.onCancel", e); } } }); @@ -750,9 +750,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto currentTheme = currentThemeFile.getName(); } - int currentItem = 0; List<String> names = new ArrayList<String>(); names.add(res.getString(R.string.map_theme_builtin)); + int currentItem = 0; for (File file : themeFiles) { if (currentTheme.equalsIgnoreCase(file.getName())) { currentItem = names.size(); @@ -766,7 +766,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto builder.setTitle(R.string.map_theme_select); - builder.setSingleChoiceItems(names.toArray(new String[] {}), selectedItem, + builder.setSingleChoiceItems(names.toArray(new String[names.size()]), selectedItem, new DialogInterface.OnClickListener() { @Override @@ -790,7 +790,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } /** - * @return a Set of geocodes corresponding to the caches that are shown on screen. + * @return a non-null Set of geocodes corresponding to the caches that are shown on screen. */ private Set<String> getGeocodesForCachesInViewport() { final Set<String> geocodes = new HashSet<String>(); @@ -1086,7 +1086,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto yield(); } catch (Exception e) { - Log.w("cgeomap.LoadTimer.run: " + e.toString()); + Log.w("cgeomap.LoadTimer.run", e); } } } @@ -1118,21 +1118,17 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto SearchResult searchResult; if (mapMode == MapMode.LIVE) { - if (isLiveEnabled) { - searchResult = new SearchResult(); - } else { - searchResult = new SearchResult(app.getStoredInViewport(viewport, Settings.getCacheType())); - } + searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(cgData.loadStoredInViewport(viewport, Settings.getCacheType())); } else { // map started from another activity - searchResult = new SearchResult(searchIntent); + searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult(); if (geocodeIntent != null) { searchResult.addGeocode(geocodeIntent); } } // live mode search result if (isLiveEnabled) { - SearchResult liveResult = new SearchResult(app.getCachedInViewport(viewport, Settings.getCacheType())); + SearchResult liveResult = new SearchResult(cgData.loadCachedInViewport(viewport, Settings.getCacheType())); searchResult.addGeocodes(liveResult.getGeocodes()); } @@ -1160,7 +1156,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (isLiveEnabled || mapMode == MapMode.COORDS) { //All visible waypoints CacheType type = Settings.getCacheType(); - Set<cgWaypoint> waypointsInViewport = app.getWaypointsInViewport(viewport, Settings.isExcludeMyCaches(), Settings.isExcludeDisabledCaches(), type); + Set<Waypoint> waypointsInViewport = cgData.loadWaypoints(viewport, Settings.isExcludeMyCaches(), Settings.isExcludeDisabledCaches(), type); waypoints.addAll(waypointsInViewport); } else @@ -1265,14 +1261,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto // display caches final List<cgCache> cachesToDisplay = caches.getAsList(); - final List<cgWaypoint> waypointsToDisplay = new ArrayList<cgWaypoint>(waypoints); + final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints); final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>(); if (!cachesToDisplay.isEmpty()) { // Only show waypoints for single view or setting // when less than showWaypointsthreshold Caches shown if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) { - for (cgWaypoint waypoint : waypointsToDisplay) { + for (Waypoint waypoint : waypointsToDisplay) { if (waypoint == null || waypoint.getCoords() == null) { continue; @@ -1320,7 +1316,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } if (coordsIntent != null) { - final cgWaypoint waypoint = new cgWaypoint("some place", waypointTypeIntent != null ? waypointTypeIntent : WaypointType.WAYPOINT, false); + final Waypoint waypoint = new Waypoint("some place", waypointTypeIntent != null ? waypointTypeIntent : WaypointType.WAYPOINT, false); waypoint.setCoords(coordsIntent); final CachesOverlayItemImpl item = getItem(waypoint, null, waypoint); @@ -1340,7 +1336,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final protected Viewport viewport; - public DoRunnable(final Viewport viewport) { + protected DoRunnable(final Viewport viewport) { this.viewport = viewport; } @@ -1394,7 +1390,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto break; } - if (!app.isOffline(geocode, null)) { + if (!cgData.isOffline(geocode, null)) { if ((System.currentTimeMillis() - last) < 1500) { try { int delay = 1000 + (int) (Math.random() * 1000.0) - (int) (System.currentTimeMillis() - last); @@ -1417,7 +1413,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto cgCache.storeCache(null, geocode, StoredList.STANDARD_LIST_ID, false, handler); } } catch (Exception e) { - Log.e("cgeocaches.LoadDetails.run: " + e.toString()); + Log.e("cgeocaches.LoadDetails.run", e); } finally { // one more cache over detailProgress++; @@ -1484,9 +1480,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto Viewport viewport = null; if (geocodeCenter != null) { - viewport = app.getBounds(geocodeCenter); + viewport = cgData.getBounds(geocodeCenter); } else if (searchCenter != null) { - viewport = app.getBounds(searchCenter.getGeocodes()); + viewport = cgData.getBounds(searchCenter.getGeocodes()); } if (viewport == null) { @@ -1630,7 +1626,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto * Waypoint. Mutally exclusive with cache * @return */ - private CachesOverlayItemImpl getItem(final IWaypoint coord, final cgCache cache, final cgWaypoint waypoint) { + private CachesOverlayItemImpl getItem(final IWaypoint coord, final cgCache cache, final Waypoint waypoint) { if (cache != null) { final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(coord, cache.getType()); @@ -1638,6 +1634,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto .append(cache.isReliableLatLon()) .append(cache.getType().id) .append(cache.isDisabled() || cache.isArchived()) + .append(cache.getCacheRealm().id) .append(cache.isOwn()) .append(cache.isFound()) .append(cache.hasUserModifiedCoords()) @@ -1657,7 +1654,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final ArrayList<int[]> insets = new ArrayList<int[]>(8); // background: disabled or not - final Drawable marker = getResources().getDrawable(cache.isDisabled() || cache.isArchived() ? R.drawable.marker_disabled : R.drawable.marker); + final Drawable marker = getResources().getDrawable(cache.isDisabled() || cache.isArchived() ? cache.getCacheRealm().markerDisabledId : cache.getCacheRealm().markerId); layers.add(marker); final int resolution = marker.getIntrinsicWidth() > 40 ? 1 : 0; // reliable or not diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java index b656900..fe1a19b 100644 --- a/main/src/cgeo/geocaching/maps/CachesOverlay.java +++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java @@ -6,7 +6,7 @@ import cgeo.geocaching.R; import cgeo.geocaching.Settings; import cgeo.geocaching.WaypointPopup; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.connector.gc.GCMap; import cgeo.geocaching.enumerations.CacheType; @@ -209,10 +209,9 @@ public class CachesOverlay extends AbstractItemizedOverlay { progress.show(context, context.getResources().getString(R.string.map_live), context.getResources().getString(R.string.cache_dialog_loading_details), true, null); - CachesOverlayItemImpl item = null; - // prevent concurrent changes getOverlayImpl().lock(); + CachesOverlayItemImpl item = null; try { if (index < items.size()) { item = items.get(index); @@ -228,7 +227,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { final IWaypoint coordinate = item.getCoord(); if (StringUtils.isNotBlank(coordinate.getCoordType()) && coordinate.getCoordType().equalsIgnoreCase("cache") && StringUtils.isNotBlank(coordinate.getGeocode())) { - cgCache cache = cgeoapplication.getInstance().loadCache(coordinate.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); + cgCache cache = cgData.loadCache(coordinate.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); RequestDetailsThread requestDetailsThread = new RequestDetailsThread(cache); if (!requestDetailsThread.requestRequired()) { // don't show popup if we have enough details @@ -248,7 +247,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { progress.dismiss(); } catch (Exception e) { - Log.e("cgMapOverlay.onTap: " + e.toString()); + Log.e("cgMapOverlay.onTap", e); if (progress != null) { progress.dismiss(); } @@ -262,7 +261,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { try { return items.get(index); } catch (Exception e) { - Log.e("cgMapOverlay.createItem: " + e.toString()); + Log.e("cgMapOverlay.createItem", e); } return null; @@ -273,7 +272,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { try { return items.size(); } catch (Exception e) { - Log.e("cgMapOverlay.size: " + e.toString()); + Log.e("cgMapOverlay.size", e); } return 0; diff --git a/main/src/cgeo/geocaching/maps/MapProviderFactory.java b/main/src/cgeo/geocaching/maps/MapProviderFactory.java index cb1f87f..483189f 100644 --- a/main/src/cgeo/geocaching/maps/MapProviderFactory.java +++ b/main/src/cgeo/geocaching/maps/MapProviderFactory.java @@ -23,7 +23,7 @@ public class MapProviderFactory { MapsforgeMapProvider.getInstance(); } - private static boolean isGoogleMapsInstalled() { + public static boolean isGoogleMapsInstalled() { boolean googleMaps = true; try { Class.forName("com.google.android.maps.MapActivity"); diff --git a/main/src/cgeo/geocaching/maps/PositionOverlay.java b/main/src/cgeo/geocaching/maps/PositionOverlay.java index 1aa2d3b..fec67ef 100644 --- a/main/src/cgeo/geocaching/maps/PositionOverlay.java +++ b/main/src/cgeo/geocaching/maps/PositionOverlay.java @@ -158,7 +158,6 @@ public class PositionOverlay implements GeneralOverlay { if (Settings.isMapTrail()) { int size = history.size(); if (size > 1) { - int alpha; int alphaCnt = size - 201; if (alphaCnt < 1) { alphaCnt = 1; @@ -172,6 +171,7 @@ public class PositionOverlay implements GeneralOverlay { projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(prev)), historyPointP); projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(now)), historyPointN); + int alpha; if ((alphaCnt - cnt) > 0) { alpha = 255 / (alphaCnt - cnt); } @@ -211,11 +211,8 @@ public class PositionOverlay implements GeneralOverlay { heightArrowHalf = arrow.getHeight() / 2; } - int marginLeft; - int marginTop; - - marginLeft = center.x - widthArrowHalf; - marginTop = center.y - heightArrowHalf; + int marginLeft = center.x - widthArrowHalf; + int marginTop = center.y - heightArrowHalf; Matrix matrix = new Matrix(); matrix.setRotate(heading, widthArrowHalf, heightArrowHalf); diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java index 0377fe9..5649d19 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.google; +import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.maps.AbstractMap; import cgeo.geocaching.maps.CGeoMap; import cgeo.geocaching.maps.interfaces.MapActivityImpl; @@ -12,7 +13,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; -public class GoogleMapActivity extends MapActivity implements MapActivityImpl { +public class GoogleMapActivity extends MapActivity implements MapActivityImpl, FilteredActivity { private AbstractMap mapBase; @@ -127,4 +128,8 @@ public class GoogleMapActivity extends MapActivity implements MapActivityImpl { mapBase.goManual(view); } + @Override + public void showFilterMenu(View view) { + // do nothing, the filter bar only shows the global filter + } } diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java b/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java index 6973338..1fa38ad 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java @@ -16,7 +16,6 @@ public final class GoogleMapProvider extends AbstractMapProvider { public static final String GOOGLE_MAP_ID = "GOOGLE_MAP"; public static final String GOOGLE_SATELLITE_ID = "GOOGLE_SATELLITE"; - private static GoogleMapProvider instance; private final MapItemFactory mapItemFactory; @@ -29,15 +28,16 @@ public final class GoogleMapProvider extends AbstractMapProvider { mapItemFactory = new GoogleMapItemFactory(); } + private static class Holder { + private static final GoogleMapProvider INSTANCE = new GoogleMapProvider(); + } + public static GoogleMapProvider getInstance() { - if (instance == null) { - instance = new GoogleMapProvider(); - } - return instance; + return Holder.INSTANCE; } public static boolean isSatelliteSource(final MapSource mapSource) { - return mapSource != null && mapSource instanceof GoogleSatelliteSource; + return mapSource instanceof GoogleSatelliteSource; } @Override @@ -67,7 +67,7 @@ public final class GoogleMapProvider extends AbstractMapProvider { private static abstract class AbstractGoogleMapSource extends AbstractMapSource { - public AbstractGoogleMapSource(final String id, final MapProvider mapProvider, final String name) { + protected AbstractGoogleMapSource(final String id, final MapProvider mapProvider, final String name) { super(id, mapProvider, name); } diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java index 9c134a4..154c3f3 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java @@ -61,7 +61,7 @@ public class GoogleMapView extends MapView implements MapViewImpl { super.draw(canvas); } catch (Exception e) { - Log.e("GoogleMapView.draw: " + e.toString()); + Log.e("GoogleMapView.draw", e); } } @@ -75,7 +75,7 @@ public class GoogleMapView extends MapView implements MapViewImpl { super.displayZoomControls(takeFocus); } catch (Exception e) { - Log.e("GoogleMapView.displayZoomControls: " + e.toString()); + Log.e("GoogleMapView.displayZoomControls", e); } } diff --git a/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java b/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java index d86eafe..773f9ff 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java @@ -27,6 +27,9 @@ public class GoogleOverlay extends Overlay implements OverlayImpl { break; case ScaleOverlay: overlayBase = new ScaleOverlay(activityIn, this); + break; + default: + throw new IllegalArgumentException(); } } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java index 6cb2539..f850402 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.mapsforge; +import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.maps.AbstractMap; import cgeo.geocaching.maps.CGeoMap; import cgeo.geocaching.maps.interfaces.MapActivityImpl; @@ -12,7 +13,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; -public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl { +public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl, FilteredActivity { private AbstractMap mapBase; @@ -121,4 +122,9 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl public void goManual(View view) { mapBase.goManual(view); } + + @Override + public void showFilterMenu(View view) { + // do nothing, the filter bar only shows the global filter + } } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java index ad64807..dc0dbf8 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java @@ -31,7 +31,6 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { public static final String MAPSFORGE_MAPNIK_ID = "MAPSFORGE_MAPNIK"; private boolean oldMap = false; private MapItemFactory mapItemFactory = new MapsforgeMapItemFactory(); - private static MapsforgeMapProvider instance; private MapsforgeMapProvider() { final Resources resources = cgeoapplication.getInstance().getResources(); @@ -42,11 +41,12 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { updateOfflineMaps(); } + private static final class Holder { + private static final MapsforgeMapProvider INSTANCE = new MapsforgeMapProvider(); + } + public static MapsforgeMapProvider getInstance() { - if (instance == null) { - instance = new MapsforgeMapProvider(); - } - return instance; + return Holder.INSTANCE; } public static List<String> getOfflineMaps() { @@ -65,6 +65,7 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { } } } + Collections.sort(mapFileList, String.CASE_INSENSITIVE_ORDER); return mapFileList; } catch (Exception e) { Log.e("Settings.getOfflineMaps: " + e); diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java index 1e4a756..083e5bb 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java @@ -59,7 +59,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { super.draw(canvas); } catch (Exception e) { - Log.e("MapsforgeMapView.draw: " + e.toString()); + Log.e("MapsforgeMapView.draw", e); } } @@ -264,7 +264,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } } catch (Exception e) { - Log.e("MapsforgeMapView.repaintRequired: " + e.toString()); + Log.e("MapsforgeMapView.repaintRequired", e); } } } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java index b6e31a2..dd7fb75 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java @@ -29,6 +29,9 @@ public class MapsforgeOverlay extends Overlay implements OverlayImpl { break; case ScaleOverlay: overlayBase = new ScaleOverlay(activityIn, this); + break; + default: + throw new IllegalArgumentException(); } } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java index d45db9a..ed8a7bc 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.mapsforge.v024; +import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.maps.AbstractMap; import cgeo.geocaching.maps.CGeoMap; import cgeo.geocaching.maps.interfaces.MapActivityImpl; @@ -12,7 +13,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; -public class MapsforgeMapActivity024 extends MapActivity implements MapActivityImpl { +public class MapsforgeMapActivity024 extends MapActivity implements MapActivityImpl, FilteredActivity { private AbstractMap mapBase; @@ -121,4 +122,9 @@ public class MapsforgeMapActivity024 extends MapActivity implements MapActivityI public void goManual(View view) { mapBase.goManual(view); } + + @Override + public void showFilterMenu(View view) { + // do nothing, the filter bar only shows the global filter + } } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java index d177a47..85d61fe 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java @@ -53,7 +53,7 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { super.draw(canvas); } catch (Exception e) { - Log.e("MapsforgeMapView.draw: " + e.toString()); + Log.e("MapsforgeMapView.draw", e); } } @@ -208,7 +208,7 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { } } catch (Exception e) { - Log.e("MapsforgeMapView.repaintRequired: " + e.toString()); + Log.e("MapsforgeMapView.repaintRequired", e); } } } diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index d47afb9..a409750 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -3,6 +3,7 @@ package cgeo.geocaching.network; import cgeo.geocaching.R; import cgeo.geocaching.StoredList; import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.utils.ImageHelper; @@ -12,15 +13,13 @@ import ch.boye.httpclientandroidlib.HttpResponse; import org.apache.commons.lang3.StringUtils; -import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Point; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.text.Html; -import android.view.Display; -import android.view.WindowManager; import java.io.File; import java.io.FileInputStream; @@ -42,7 +41,8 @@ public class HtmlImage implements Html.ImageGetter { "besucherzaehler-homepage.de", "hitwebcounter.com", "kostenloser-counter.eu", - "trendcounter.com" + "trendcounter.com", + "hit-counter-download.com" }; final private String geocode; @@ -66,9 +66,9 @@ public class HtmlImage implements Html.ImageGetter { bfOptions = new BitmapFactory.Options(); bfOptions.inTempStorage = new byte[16 * 1024]; - final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); - this.maxWidth = display.getWidth() - 25; - this.maxHeight = display.getHeight() - 25; + Point displaySize = Compatibility.getDisplaySize(); + this.maxWidth = displaySize.x - 25; + this.maxHeight = displaySize.y - 25; this.resources = cgeoapplication.getInstance().getResources(); } @@ -161,7 +161,7 @@ public class HtmlImage implements Html.ImageGetter { final File fileSec = LocalStorage.getStorageSecFile(pseudoGeocode, url, true); return loadCachedImage(fileSec, forceKeep); } catch (Exception e) { - Log.w("HtmlImage.getDrawable (reading cache): " + e.toString()); + Log.w("HtmlImage.getDrawable (reading cache)", e); } return null; } diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index 0bd845f..6ab7704 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -22,6 +22,7 @@ import ch.boye.httpclientandroidlib.client.methods.HttpGet; import ch.boye.httpclientandroidlib.client.methods.HttpPost; import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; import ch.boye.httpclientandroidlib.client.params.ClientPNames; +import ch.boye.httpclientandroidlib.entity.StringEntity; import ch.boye.httpclientandroidlib.entity.mime.MultipartEntity; import ch.boye.httpclientandroidlib.entity.mime.content.FileBody; import ch.boye.httpclientandroidlib.entity.mime.content.StringBody; @@ -34,6 +35,7 @@ import ch.boye.httpclientandroidlib.params.HttpParams; import ch.boye.httpclientandroidlib.protocol.HttpContext; import ch.boye.httpclientandroidlib.util.EntityUtils; +import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; @@ -43,11 +45,13 @@ import android.net.Uri; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.net.URLEncoder; public abstract class Network { private static final int NB_DOWNLOAD_RETRIES = 4; + /** User agent id */ private final static String PC_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"; /** Native user agent, taken from a Android 2.2 Nexus **/ @@ -58,7 +62,7 @@ public abstract class Network { private final static HttpParams clientParams = new BasicHttpParams(); static { - Network.clientParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8"); + Network.clientParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, CharEncoding.UTF_8); Network.clientParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000); Network.clientParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000); Network.clientParams.setParameter(ClientPNames.HANDLE_REDIRECTS, true); @@ -115,7 +119,6 @@ public abstract class Network { if (contentEncoding != null) { for (final HeaderElement codec : contentEncoding.getElements()) { if (codec.getName().equalsIgnoreCase("gzip")) { - Log.d("Decompressing response"); response.setEntity(new GzipDecompressingEntity(response.getEntity())); return; } @@ -153,6 +156,27 @@ public abstract class Network { } /** + * POST HTTP request with Json POST DATA + * + * @param uri the URI to request + * @param json the json object to add to the POST request + * @return the HTTP response, or null in case of an encoding error params + */ + public static HttpResponse postJsonRequest(final String uri, final JSONObject json) { + HttpPost request = new HttpPost(uri); + request.addHeader("Content-Type", "application/json; charset=utf-8"); + if (json != null) { + try { + request.setEntity(new StringEntity(json.toString())); + } catch (UnsupportedEncodingException e) { + Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException"); + return null; + } + } + return doRepeatedRequests(request); + } + + /** * Multipart POST HTTP request * * @param uri the URI to request @@ -206,7 +230,7 @@ public abstract class Network { request = new HttpPost(uri); if (params != null) { try { - ((HttpPost) request).setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + ((HttpPost) request).setEntity(new UrlEncodedFormEntity(params, CharEncoding.UTF_8)); } catch (final UnsupportedEncodingException e) { Log.e("request", e); return null; @@ -235,11 +259,8 @@ public abstract class Network { "X-Requested-With", "XMLHttpRequest")) { request.setHeader(header.getName(), header.getValue()); } - if (Settings.getUseNativeUa()) { - request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Network.NATIVE_USER_AGENT); - } else { - request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Network.PC_USER_AGENT); - } + request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, + Settings.getUseNativeUa() ? Network.NATIVE_USER_AGENT : Network.PC_USER_AGENT); } /** @@ -379,7 +400,7 @@ public abstract class Network { private static String getResponseDataNoError(final HttpResponse response, boolean replaceWhitespace) { try { - String data = EntityUtils.toString(response.getEntity(), "UTF-8"); + String data = EntityUtils.toString(response.getEntity(), CharEncoding.UTF_8); return replaceWhitespace ? BaseUtils.replaceWhitespace(data) : data; } catch (Exception e) { Log.e("getResponseData", e); @@ -399,7 +420,25 @@ public abstract class Network { } public static String rfc3986URLEncode(String text) { - return StringUtils.replace(URLEncoder.encode(text).replace("+", "%20"), "%7E", "~"); + return StringUtils.replace(Network.encode(text).replace("+", "%20"), "%7E", "~"); + } + + public static String decode(final String text) { + try { + return URLDecoder.decode(text, CharEncoding.UTF_8); + } catch (UnsupportedEncodingException e) { + Log.e("Network.decode", e); + } + return null; + } + + public static String encode(final String text) { + try { + return URLEncoder.encode(text, CharEncoding.UTF_8); + } catch (UnsupportedEncodingException e) { + Log.e("Network.encode", e); + } + return null; } } diff --git a/main/src/cgeo/geocaching/network/Parameters.java b/main/src/cgeo/geocaching/network/Parameters.java index 081a926..74f5531 100644 --- a/main/src/cgeo/geocaching/network/Parameters.java +++ b/main/src/cgeo/geocaching/network/Parameters.java @@ -4,6 +4,8 @@ import ch.boye.httpclientandroidlib.NameValuePair; import ch.boye.httpclientandroidlib.client.utils.URLEncodedUtils; import ch.boye.httpclientandroidlib.message.BasicNameValuePair; +import org.apache.commons.lang3.CharEncoding; + import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collections; @@ -24,7 +26,6 @@ public class Parameters extends ArrayList<NameValuePair> { * if the number of key/values is unbalanced */ public Parameters(final String... keyValues) { - super(); put(keyValues); } @@ -66,7 +67,7 @@ public class Parameters extends ArrayList<NameValuePair> { @Override public String toString() { - return URLEncodedUtils.format(this, "UTF-8"); + return URLEncodedUtils.format(this, CharEncoding.UTF_8); } /** diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java index 8c3b9dc..1953e1d 100644 --- a/main/src/cgeo/geocaching/network/StatusUpdater.java +++ b/main/src/cgeo/geocaching/network/StatusUpdater.java @@ -31,7 +31,7 @@ public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implement private void requestUpdate() { final JSONObject response = Network.requestJSON("http://status.cgeo.org/api/status.json", - new Parameters("version_code", "" + Version.getVersionCode(cgeoapplication.getInstance()), + new Parameters("version_code", String.valueOf(Version.getVersionCode(cgeoapplication.getInstance())), "version_name", Version.getVersionName(cgeoapplication.getInstance()), "locale", Locale.getDefault().toString())); if (response != null) { diff --git a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java index 2015375..aebecd2 100644 --- a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java +++ b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java @@ -19,7 +19,7 @@ public abstract class AbstractCacheComparator implements CacheComparator { } return compareCaches(cache1, cache2); } catch (Exception e) { - Log.e("AbstractCacheComparator.compare: " + e.toString()); + Log.e("AbstractCacheComparator.compare", e); } return 0; } diff --git a/main/src/cgeo/geocaching/sorting/DistanceComparator.java b/main/src/cgeo/geocaching/sorting/DistanceComparator.java index d601433..781359a 100644 --- a/main/src/cgeo/geocaching/sorting/DistanceComparator.java +++ b/main/src/cgeo/geocaching/sorting/DistanceComparator.java @@ -11,8 +11,22 @@ import java.util.List; */ public class DistanceComparator extends AbstractCacheComparator { + final private Geopoint coords; + final private List<cgCache> list; + private boolean cachedDistances; + public DistanceComparator(final Geopoint coords, List<cgCache> list) { - // calculate all distances to avoid duplicate calculations during sorting + this.coords = coords; + this.list = list; + } + + /** + * calculate all distances only once to avoid costly re-calculation of the same distance during sorting + */ + private void calculateAllDistances() { + if (cachedDistances) { + return; + } for (cgCache cache : list) { if (cache.getCoords() != null) { cache.setDistance(coords.distanceTo(cache.getCoords())); @@ -21,6 +35,7 @@ public class DistanceComparator extends AbstractCacheComparator { cache.setDistance(null); } } + cachedDistances = true; } @Override @@ -30,6 +45,7 @@ public class DistanceComparator extends AbstractCacheComparator { @Override protected int compareCaches(final cgCache cache1, final cgCache cache2) { + calculateAllDistances(); if (cache1.getCoords() == null && cache2.getCoords() == null) { return 0; } diff --git a/main/src/cgeo/geocaching/sorting/FindsComparator.java b/main/src/cgeo/geocaching/sorting/FindsComparator.java index 6407b11..47e3844 100644 --- a/main/src/cgeo/geocaching/sorting/FindsComparator.java +++ b/main/src/cgeo/geocaching/sorting/FindsComparator.java @@ -1,13 +1,11 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.enumerations.LogType; public class FindsComparator extends AbstractCacheComparator { - private final cgeoapplication app = cgeoapplication.getInstance(); - @Override protected boolean canCompare(cgCache cache1, cgCache cache2) { return cache1.getLogCounts() != null && cache2.getLogCounts() != null; @@ -20,9 +18,9 @@ public class FindsComparator extends AbstractCacheComparator { return finds2 - finds1; } - private int getFindsCount(cgCache cache) { + private static int getFindsCount(cgCache cache) { if (cache.getLogCounts().isEmpty()) { - cache.setLogCounts(app.loadLogCounts(cache.getGeocode())); + cache.setLogCounts(cgData.loadLogCounts(cache.getGeocode())); } Integer logged = cache.getLogCounts().get(LogType.FOUND_IT); if (logged != null) { diff --git a/main/src/cgeo/geocaching/sorting/InverseComparator.java b/main/src/cgeo/geocaching/sorting/InverseComparator.java new file mode 100644 index 0000000..d2fa085 --- /dev/null +++ b/main/src/cgeo/geocaching/sorting/InverseComparator.java @@ -0,0 +1,22 @@ +package cgeo.geocaching.sorting; + +import cgeo.geocaching.cgCache; + +/** + * comparator which inverses the sort order of the given other comparator + * + */ +public class InverseComparator implements CacheComparator { + + private final CacheComparator originalComparator; + + public InverseComparator(CacheComparator comparator) { + this.originalComparator = comparator; + } + + @Override + public int compare(cgCache lhs, cgCache rhs) { + return originalComparator.compare(rhs, lhs); + } + +} diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java index c630cec..668502f 100644 --- a/main/src/cgeo/geocaching/twitter/Twitter.java +++ b/main/src/cgeo/geocaching/twitter/Twitter.java @@ -1,8 +1,9 @@ package cgeo.geocaching.twitter; import cgeo.geocaching.Settings; +import cgeo.geocaching.Trackable; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgTrackable; +import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.geopoint.Geopoint; @@ -42,7 +43,7 @@ public final class Twitter { Log.e("Tweet could not be posted"); } } catch (Exception e) { - Log.e("cgBase.postTweet: " + e.toString()); + Log.e("cgBase.postTweet", e); } } @@ -55,7 +56,7 @@ public final class Twitter { } public static void postTweetCache(String geocode) { - final cgCache cache = cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + final cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); String status; final String url = cache.getUrl(); if (url.length() >= 100) { @@ -76,7 +77,7 @@ public final class Twitter { } public static void postTweetTrackable(String geocode) { - final cgTrackable trackable = cgeoapplication.getInstance().getTrackableByGeocode(geocode); + final Trackable trackable = cgData.loadTrackable(geocode); String name = trackable.getName(); if (name.length() > 82) { name = name.substring(0, 81) + '…'; diff --git a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java index 22ee0fb..3bd6327 100644 --- a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java @@ -7,6 +7,7 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.OAuth; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity; import ch.boye.httpclientandroidlib.util.EntityUtils; @@ -24,7 +25,6 @@ import android.view.View; import android.widget.Button; import android.widget.EditText; -import java.util.regex.Matcher; import java.util.regex.Pattern; public class TwitterAuthorizationActivity extends AbstractActivity { @@ -130,24 +130,23 @@ public class TwitterAuthorizationActivity extends AbstractActivity { } private void requestToken() { - final String host = "api.twitter.com"; - final String pathRequest = "/oauth/request_token"; - final String pathAuthorize = "/oauth/authorize"; - final String method = "GET"; int status = 0; try { final Parameters params = new Parameters(); + final String method = "GET"; + final String pathRequest = "/oauth/request_token"; + final String host = "api.twitter.com"; OAuth.signOAuth(host, pathRequest, method, true, params, null, null); final String line = Network.getResponseData(Network.getRequest("https://" + host + pathRequest, params)); if (StringUtils.isNotBlank(line)) { - final Matcher paramsMatcher1 = paramsPattern1.matcher(line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final Matcher paramsMatcher2 = paramsPattern2.matcher(line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); if (paramsMatcher2.find()) { OAtokenSecret = paramsMatcher2.group(1); } @@ -157,43 +156,44 @@ public class TwitterAuthorizationActivity extends AbstractActivity { try { final Parameters paramsBrowser = new Parameters(); paramsBrowser.put("oauth_callback", "oob"); + final String pathAuthorize = "/oauth/authorize"; OAuth.signOAuth(host, pathAuthorize, "GET", true, paramsBrowser, OAtoken, OAtokenSecret); final String encodedParams = EntityUtils.toString(new UrlEncodedFormEntity(paramsBrowser)); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://" + host + pathAuthorize + "?" + encodedParams))); status = 1; } catch (Exception e) { - Log.e("TwitterAuthorizationActivity.requestToken(2): " + e.toString()); + Log.e("TwitterAuthorizationActivity.requestToken(2)", e); } } } } catch (Exception e) { - Log.e("TwitterAuthorizationActivity.requestToken(1): " + e.toString()); + Log.e("TwitterAuthorizationActivity.requestToken(1)", e); } requestTokenHandler.sendEmptyMessage(status); } private void changeToken() { - final String host = "api.twitter.com"; - final String path = "/oauth/access_token"; - final String method = "POST"; int status = 0; try { final Parameters params = new Parameters("oauth_verifier", pinEntry.getText().toString()); + final String method = "POST"; + final String path = "/oauth/access_token"; + final String host = "api.twitter.com"; OAuth.signOAuth(host, path, method, true, params, OAtoken, OAtokenSecret); final String line = StringUtils.defaultString(Network.getResponseData(Network.postRequest("https://" + host + path, params))); OAtoken = ""; OAtokenSecret = ""; - final Matcher paramsMatcher1 = paramsPattern1.matcher(line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final Matcher paramsMatcher2 = paramsPattern2.matcher(line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); if (paramsMatcher2.find() && paramsMatcher2.groupCount() > 0) { OAtokenSecret = paramsMatcher2.group(1); } @@ -207,7 +207,7 @@ public class TwitterAuthorizationActivity extends AbstractActivity { status = 1; } } catch (Exception e) { - Log.e("TwitterAuthorizationActivity.changeToken: " + e.toString()); + Log.e("TwitterAuthorizationActivity.changeToken", e); } changeTokensHandler.sendEmptyMessage(status); @@ -242,7 +242,7 @@ public class TwitterAuthorizationActivity extends AbstractActivity { @Override public void onClick(View arg0) { - if (((EditText) findViewById(R.id.pin)).getText().toString().length() == 0) { + if (StringUtils.isEmpty(((EditText) findViewById(R.id.pin)).getText().toString())) { helpDialog(res.getString(R.string.auth_dialog_pin_title), res.getString(R.string.auth_dialog_pin_message)); return; } diff --git a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java new file mode 100644 index 0000000..333ef11 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java @@ -0,0 +1,32 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.activity.AbstractViewPagerActivity.PageViewCreator; + +import android.view.View; + +/** + * View creator which destroys the created view on every {@link #notifyDataSetChanged()}. + * + * @param <ViewClass> + */ +public abstract class AbstractCachingPageViewCreator<ViewClass extends View> implements PageViewCreator { + + public ViewClass view; + + @Override + public final void notifyDataSetChanged() { + view = null; + } + + @Override + public final View getView() { + if (view == null) { + view = getDispatchedView(); + } + + return view; + } + + @Override + public abstract ViewClass getDispatchedView(); +} diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java index 2a83ddc..9745d63 100644 --- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java +++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java @@ -35,7 +35,7 @@ public final class CacheDetailsCreator { } public TextView add(final int nameId, final CharSequence value) { - final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_item, null); + final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_layout, null); final TextView nameView = (TextView) layout.findViewById(R.id.name); nameView.setText(res.getString(nameId)); lastValueView = (TextView) layout.findViewById(R.id.value); @@ -56,16 +56,15 @@ public final class CacheDetailsCreator { nameView.setText(activity.getResources().getString(nameId)); lastValueView.setText(String.format("%.1f", value) + ' ' + activity.getResources().getString(R.string.cache_rating_of) + " 5"); - layoutStars.addView(createStarImages(value), 1); + createStarImages(layoutStars, value); + layoutStars.setVisibility(View.VISIBLE); parentView.addView(layout); return layout; } - private LinearLayout createStarImages(final float value) { + private void createStarImages(final ViewGroup starsContainer, final float value) { final LayoutInflater inflater = LayoutInflater.from(activity); - final LinearLayout starsContainer = new LinearLayout(activity); - starsContainer.setOrientation(LinearLayout.HORIZONTAL); for (int i = 0; i < 5; i++) { ImageView star = (ImageView) inflater.inflate(R.layout.star, null); @@ -78,8 +77,6 @@ public final class CacheDetailsCreator { } starsContainer.addView(star); } - - return starsContainer; } public void addCacheState(cgCache cache) { diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java index 65d3fbc..d6224a9 100644 --- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java +++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java @@ -12,6 +12,7 @@ import cgeo.geocaching.filter.IFilter; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.sorting.CacheComparator; import cgeo.geocaching.sorting.DistanceComparator; +import cgeo.geocaching.sorting.InverseComparator; import cgeo.geocaching.sorting.VisitComparator; import cgeo.geocaching.utils.AngleUtils; import cgeo.geocaching.utils.Log; @@ -43,6 +44,7 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -64,6 +66,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { final private Resources res; /** Resulting list of caches */ final private List<cgCache> list; + private boolean inverseSort = false; private static final int SWIPE_MIN_DISTANCE = 60; private static final int SWIPE_MAX_OFF_PATH = 100; @@ -149,6 +152,14 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { * @param comparator */ public void setComparator(final CacheComparator comparator) { + // selecting the same sorting twice will toggle the order + if (cacheComparator != null && comparator != null && cacheComparator.getClass().equals(comparator.getClass())) { + inverseSort = !inverseSort; + } + else { + // always reset the inversion for a new sorting criteria + inverseSort = false; + } cacheComparator = comparator; forceSort(); } @@ -257,7 +268,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { updateSortByDistance(); } else { - Collections.sort(list, cacheComparator); + Collections.sort(list, getPotentialInversion(cacheComparator)); } notifyDataSetChanged(); @@ -292,7 +303,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { return; } final ArrayList<cgCache> oldList = new ArrayList<cgCache>(list); - Collections.sort(list, new DistanceComparator(coords, list)); + Collections.sort(list, getPotentialInversion(new DistanceComparator(coords, list))); // avoid an update if the list has not changed due to location update if (list.equals(oldList)) { @@ -302,6 +313,13 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { lastSort = System.currentTimeMillis(); } + private Comparator<? super cgCache> getPotentialInversion(final CacheComparator comparator) { + if (inverseSort) { + return new InverseComparator(comparator); + } + return comparator; + } + private boolean isSortedByDistance() { return cacheComparator == null || cacheComparator instanceof DistanceComparator; } @@ -390,17 +408,24 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { holder.logStatusMark.setVisibility(View.GONE); } - if (cache.getNameSp() == null) { - cache.setNameSp((new Spannable.Factory()).newSpannable(cache.getName())); - if (cache.isDisabled() || cache.isArchived()) { // strike - cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - if (cache.isArchived()) { - cache.getNameSp().setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + Spannable spannable = null; + if (cache.isDisabled() || cache.isArchived()) { // strike + spannable = Spannable.Factory.getInstance().newSpannable(cache.getName()); + spannable.setSpan(new StrikethroughSpan(), 0, spannable.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if (cache.isArchived()) { // red color + if (spannable == null) { + spannable = Spannable.Factory.getInstance().newSpannable(cache.getName()); } + spannable.setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, spannable.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - holder.text.setText(cache.getNameSp(), TextView.BufferType.SPANNABLE); + if (spannable != null) { + holder.text.setText(spannable, TextView.BufferType.SPANNABLE); + } + else { + holder.text.setText(cache.getName()); + } holder.text.setCompoundDrawablesWithIntrinsicBounds(getCacheIcon(cache), null, null, null); if (cache.getInventoryItems() > 0) { @@ -627,7 +652,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { return true; } } catch (Exception e) { - Log.w("CacheListAdapter.FlingGesture.onFling: " + e.toString()); + Log.w("CacheListAdapter.FlingGesture.onFling", e); } return false; diff --git a/main/src/cgeo/geocaching/ui/CompassMiniView.java b/main/src/cgeo/geocaching/ui/CompassMiniView.java index 44fb8e2..da8f69e 100644 --- a/main/src/cgeo/geocaching/ui/CompassMiniView.java +++ b/main/src/cgeo/geocaching/ui/CompassMiniView.java @@ -97,17 +97,17 @@ final public class CompassMiniView extends View { targetCoords = point; } - protected void updateAzimuth(float azimuth) { + public void updateAzimuth(float azimuth) { this.azimuth = azimuth; updateDirection(); } - protected void updateHeading(float heading) { + public void updateHeading(float heading) { this.heading = heading; updateDirection(); } - protected void updateCurrentCoords(final Geopoint currentCoords) { + public void updateCurrentCoords(final Geopoint currentCoords) { if (currentCoords == null || targetCoords == null) { return; } diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java index 048e280..0ef3a43 100644 --- a/main/src/cgeo/geocaching/ui/CompassView.java +++ b/main/src/cgeo/geocaching/ui/CompassView.java @@ -185,16 +185,13 @@ public class CompassView extends View { int canvasCenterX = (compassRoseWidth / 2) + ((getWidth() - compassRoseWidth) / 2); int canvasCenterY = (compassRoseHeight / 2) + ((getHeight() - compassRoseHeight) / 2); - int marginLeftTemp; - int marginTopTemp; - super.onDraw(canvas); canvas.save(); canvas.setDrawFilter(setfil); - marginLeftTemp = (getWidth() - compassUnderlayWidth) / 2; - marginTopTemp = (getHeight() - compassUnderlayHeight) / 2; + int marginLeftTemp = (getWidth() - compassUnderlayWidth) / 2; + int marginTopTemp = (getHeight() - compassUnderlayHeight) / 2; canvas.drawBitmap(compassUnderlay, marginLeftTemp, marginTopTemp, null); diff --git a/main/src/cgeo/geocaching/ui/EditorDialog.java b/main/src/cgeo/geocaching/ui/EditorDialog.java index 50b3e27..6dcf546 100644 --- a/main/src/cgeo/geocaching/ui/EditorDialog.java +++ b/main/src/cgeo/geocaching/ui/EditorDialog.java @@ -53,7 +53,7 @@ public class EditorDialog extends Dialog { @Override public void show() { super.show(); - getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); + getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); } } diff --git a/main/src/cgeo/geocaching/ui/Formatter.java b/main/src/cgeo/geocaching/ui/Formatter.java index 53a7276..4d23952 100644 --- a/main/src/cgeo/geocaching/ui/Formatter.java +++ b/main/src/cgeo/geocaching/ui/Formatter.java @@ -2,7 +2,7 @@ package cgeo.geocaching.ui; import cgeo.geocaching.R; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheListType; import cgeo.geocaching.enumerations.CacheSize; @@ -13,6 +13,7 @@ import org.apache.commons.lang3.StringUtils; import android.content.Context; import android.text.format.DateUtils; +import java.text.DateFormat; import java.util.ArrayList; import java.util.List; @@ -70,8 +71,8 @@ public abstract class Formatter { * @return the formatted string */ public static String formatShortDate(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_NUMERIC_DATE); + DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context); + return dateFormat.format(date); } /** @@ -151,12 +152,13 @@ public abstract class Formatter { return StringUtils.join(infos, Formatter.SEPARATOR); } - public static String formatWaypointInfo(cgWaypoint waypoint) { + public static String formatWaypointInfo(Waypoint waypoint) { final List<String> infos = new ArrayList<String>(3); - if (WaypointType.ALL_TYPES_EXCEPT_OWN.contains(waypoint.getWaypointType())) { - infos.add(waypoint.getWaypointType().getL10n()); + WaypointType waypointType = waypoint.getWaypointType(); + if (waypointType != WaypointType.OWN && waypointType != null) { + infos.add(waypointType.getL10n()); } - if (cgWaypoint.PREFIX_OWN.equalsIgnoreCase(waypoint.getPrefix())) { + if (Waypoint.PREFIX_OWN.equalsIgnoreCase(waypoint.getPrefix())) { infos.add(cgeoapplication.getInstance().getString(R.string.waypoint_custom)); } else { if (StringUtils.isNotBlank(waypoint.getPrefix())) { diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java index 3d6f95c..9464114 100644 --- a/main/src/cgeo/geocaching/ui/ImagesList.java +++ b/main/src/cgeo/geocaching/ui/ImagesList.java @@ -1,14 +1,14 @@ package cgeo.geocaching.ui; +import cgeo.geocaching.Image; import cgeo.geocaching.R; import cgeo.geocaching.StoredList; -import cgeo.geocaching.cgImage; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.utils.IOUtils; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; -import org.mapsforge.core.IOUtils; import android.app.Activity; import android.app.ProgressDialog; @@ -43,7 +43,7 @@ public class ImagesList { private static final int MENU_BROWSER = 202; private BitmapDrawable currentDrawable; - private cgImage currentImage; + private Image currentImage; public enum ImageType { LogImages(R.string.cache_log_images_title, R.string.cache_log_images_loading), @@ -53,7 +53,7 @@ public class ImagesList { private final int titleResId; private final int loadingResId; - private ImageType(final int title, final int loading) { + ImageType(final int title, final int loading) { this.titleResId = title; this.loadingResId = loading; } @@ -73,7 +73,7 @@ public class ImagesList { /** * map image view id to image */ - private final SparseArray<cgImage> images = new SparseArray<cgImage>(); + private final SparseArray<Image> images = new SparseArray<Image>(); private final String geocode; private LinearLayout imagesView; @@ -83,7 +83,7 @@ public class ImagesList { inflater = activity.getLayoutInflater(); } - public void loadImages(final View parentView, final List<cgImage> images, ImageType imageType, final boolean offline) { + public void loadImages(final View parentView, final List<Image> images, ImageType imageType, final boolean offline) { imagesView = (LinearLayout) parentView.findViewById(R.id.spoiler_list); @@ -95,9 +95,8 @@ public class ImagesList { progressDialog.setMax(count); progressDialog.show(); - LinearLayout rowView; - for (final cgImage img : images) { - rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, null); + for (final Image img : images) { + LinearLayout rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, null); if (StringUtils.isNotBlank(img.getTitle())) { ((TextView) rowView.findViewById(R.id.title)).setText(Html.fromHtml(img.getTitle())); @@ -118,10 +117,10 @@ public class ImagesList { private class AsyncImgLoader extends AsyncTask<Void, Void, BitmapDrawable> { final private LinearLayout view; - final private cgImage img; + final private Image img; final boolean offline; - public AsyncImgLoader(final LinearLayout view, final cgImage img, final boolean offline) { + public AsyncImgLoader(final LinearLayout view, final Image img, final boolean offline) { this.view = view; this.img = img; this.offline = offline; @@ -179,10 +178,6 @@ public class ImagesList { bitmaps.clear(); } - public cgImage getImage(int id) { - return images.get(id); - } - public void onCreateContextMenu(ContextMenu menu, View v) { final Resources res = activity.getResources(); menu.setHeaderTitle(res.getString(R.string.cache_image)); @@ -215,7 +210,7 @@ public class ImagesList { fos = new FileOutputStream(file); image.getBitmap().compress(CompressFormat.JPEG, 100, fos); } catch (Exception e) { - Log.e("ImagesActivity.handleMessage.onClick: " + e.toString()); + Log.e("ImagesActivity.handleMessage.onClick", e); return; } finally { IOUtils.closeQuietly(fos); diff --git a/main/src/cgeo/geocaching/ui/LoggingUI.java b/main/src/cgeo/geocaching/ui/LoggingUI.java index 0e048c3..eaa25ef 100644 --- a/main/src/cgeo/geocaching/ui/LoggingUI.java +++ b/main/src/cgeo/geocaching/ui/LoggingUI.java @@ -4,7 +4,7 @@ import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.activity.IAbstractActivity; import cgeo.geocaching.enumerations.LogType; @@ -52,7 +52,7 @@ public class LoggingUI extends AbstractUIFactory { private final int stringId; - private SpecialLogType(final int stringId) { + SpecialLogType(final int stringId) { this.stringId = stringId; } @@ -94,7 +94,7 @@ public class LoggingUI extends AbstractUIFactory { } private static void showOfflineMenu(final cgCache cache, final Activity activity) { - final LogEntry currentLog = cgeoapplication.getInstance().loadLogOffline(cache.getGeocode()); + final LogEntry currentLog = cgData.loadLogOffline(cache.getGeocode()); final LogType currentLogType = currentLog == null ? null : currentLog.type; final List<LogType> logTypes = cache.getPossibleLogTypes(); @@ -123,7 +123,8 @@ public class LoggingUI extends AbstractUIFactory { break; case CLEAR_LOG: - cgeoapplication.getInstance().clearLogOffline(cache.getGeocode()); + cgData.clearLogOffline(cache.getGeocode()); + break; } } else { cache.logOffline(activity, logTypeEntry.logType); diff --git a/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java b/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java new file mode 100644 index 0000000..4724466 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java @@ -0,0 +1,27 @@ +package cgeo.geocaching.ui; + +import android.app.Activity; +import android.os.Handler; + +import java.lang.ref.WeakReference; + +/** + * Standard handler implementation which uses a weak reference to its activity. This avoids that activities stay in + * memory due to references from the handler to the activity (see Android Lint warning "HandlerLeak") + * + * Create static private subclasses of this handler class in your activity. + * + * @param <ActivityType> + */ +public abstract class WeakReferenceHandler<ActivityType extends Activity> extends Handler { + + private final WeakReference<ActivityType> activityRef; + + protected WeakReferenceHandler(final ActivityType activity) { + this.activityRef = new WeakReference<ActivityType>(activity); + } + + protected ActivityType getActivity() { + return activityRef.get(); + } +} diff --git a/main/src/cgeo/geocaching/utils/AngleUtils.java b/main/src/cgeo/geocaching/utils/AngleUtils.java index e2b4a66..6e59a91 100644 --- a/main/src/cgeo/geocaching/utils/AngleUtils.java +++ b/main/src/cgeo/geocaching/utils/AngleUtils.java @@ -8,9 +8,11 @@ public class AngleUtils { /** * Return the angle to turn of to go from an angle to the other - * - * @param from the origin angle in degrees - * @param to the target angle in degreees + * + * @param from + * the origin angle in degrees + * @param to + * the target angle in degrees * @return a value in degrees, in the [-180, 180[ range */ public static float difference(final float from, final float to) { diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java index f04327e..df2baa0 100644 --- a/main/src/cgeo/geocaching/utils/CryptUtils.java +++ b/main/src/cgeo/geocaching/utils/CryptUtils.java @@ -46,16 +46,14 @@ public final class CryptUtils { boolean plaintext = false; final int length = text.length(); - int c; - int capitalized; for (int index = 0; index < length; index++) { - c = text.charAt(index); + int c = text.charAt(index); if (c == '[') { plaintext = true; } else if (c == ']') { plaintext = false; } else if (!plaintext) { - capitalized = c & 32; + int capitalized = c & 32; c &= ~capitalized; c = ((c >= 'A') && (c <= 'Z') ? ((c - 'A' + 13) % 26 + 'A') : c) | capitalized; @@ -73,7 +71,7 @@ public final class CryptUtils { digest.update(text.getBytes(), 0, text.length()); hashed = new BigInteger(1, digest.digest()).toString(16); } catch (Exception e) { - Log.e("cgBase.md5: " + e.toString()); + Log.e("cgBase.md5", e); } return hashed; @@ -87,7 +85,7 @@ public final class CryptUtils { digest.update(text.getBytes(), 0, text.length()); hashed = new BigInteger(1, digest.digest()).toString(16); } catch (Exception e) { - Log.e("cgBase.sha1: " + e.toString()); + Log.e("cgBase.sha1", e); } return hashed; @@ -102,7 +100,7 @@ public final class CryptUtils { mac.init(secretKeySpec); macBytes = mac.doFinal(text.getBytes()); } catch (Exception e) { - Log.e("cgBase.hashHmac: " + e.toString()); + Log.e("cgBase.hashHmac", e); } return macBytes; @@ -116,16 +114,14 @@ public final class CryptUtils { boolean plaintext = false; final int length = span.length(); - int c; - int capitalized; for (int index = 0; index < length; index++) { - c = span.charAt(index); + int c = span.charAt(index); if (c == '[') { plaintext = true; } else if (c == ']') { plaintext = false; } else if (!plaintext) { - capitalized = c & 32; + int capitalized = c & 32; c &= ~capitalized; c = ((c >= 'A') && (c <= 'Z') ? ((c - 'A' + 13) % 26 + 'A') : c) | capitalized; diff --git a/main/src/cgeo/geocaching/utils/IOUtils.java b/main/src/cgeo/geocaching/utils/IOUtils.java new file mode 100644 index 0000000..73db12f --- /dev/null +++ b/main/src/cgeo/geocaching/utils/IOUtils.java @@ -0,0 +1,20 @@ +package cgeo.geocaching.utils; + +import java.io.Closeable; +import java.io.IOException; + +final public class IOUtils { + + private IOUtils() {} + + public static void closeQuietly(final Closeable closeable) { + if (closeable != null) { + try { + closeable.close(); + } catch (final IOException e) { + Log.w("closeQuietly: unable to close " + closeable, e); + } + } + } + +} diff --git a/main/src/cgeo/geocaching/utils/ImageHelper.java b/main/src/cgeo/geocaching/utils/ImageHelper.java index 4c18b06..98cad64 100644 --- a/main/src/cgeo/geocaching/utils/ImageHelper.java +++ b/main/src/cgeo/geocaching/utils/ImageHelper.java @@ -1,13 +1,12 @@ package cgeo.geocaching.utils; import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.compatibility.Compatibility; -import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; -import android.view.Display; -import android.view.WindowManager; public class ImageHelper { @@ -24,9 +23,9 @@ public class ImageHelper { */ public static BitmapDrawable scaleBitmapToFitDisplay(final Bitmap image) { final cgeoapplication app = cgeoapplication.getInstance(); - final Display display = ((WindowManager) app.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); - final int maxWidth = display.getWidth() - 25; - final int maxHeight = display.getHeight() - 25; + Point displaySize = Compatibility.getDisplaySize(); + final int maxWidth = displaySize.x - 25; + final int maxHeight = displaySize.y - 25; Bitmap result = image; int width = image.getWidth(); diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java index f0bc4f5..6122532 100644 --- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java @@ -16,7 +16,7 @@ import java.util.Map; */ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { - private static enum OperationModes { + private enum OperationModes { LRU_CACHE, BOUNDED } diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java index b654fd6..aafce4f 100644 --- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java @@ -133,7 +133,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E> */ @Override @SuppressWarnings("unchecked") - public Object clone() { + public Object clone() throws CloneNotSupportedException { try { synchronized (this) { final LeastRecentlyUsedSet<E> newSet = (LeastRecentlyUsedSet<E>) super.clone(); diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java index 7cacd9d..7171fde 100644 --- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java +++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java @@ -2,8 +2,8 @@ package cgeo.geocaching.utils; import cgeo.geocaching.R; import cgeo.geocaching.Settings; +import cgeo.geocaching.Trackable; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgTrackable; import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.network.Network; @@ -29,14 +29,14 @@ public class LogTemplateProvider { */ public static class LogContext { private cgCache cache; - private cgTrackable trackable; + private Trackable trackable; private boolean offline = false; public LogContext(final cgCache cache) { this(cache, false); } - public LogContext(final cgTrackable trackable) { + public LogContext(final Trackable trackable) { this.trackable = trackable; } @@ -53,7 +53,7 @@ public class LogTemplateProvider { return cache; } - public cgTrackable getTrackable() { + public Trackable getTrackable() { return trackable; } @@ -148,7 +148,7 @@ public class LogTemplateProvider { @Override public String getValue(final LogContext context) { - cgTrackable trackable = context.getTrackable(); + Trackable trackable = context.getTrackable(); if (trackable != null) { return trackable.getOwner(); } diff --git a/main/src/cgeo/geocaching/utils/MatcherWrapper.java b/main/src/cgeo/geocaching/utils/MatcherWrapper.java new file mode 100644 index 0000000..c3c1663 --- /dev/null +++ b/main/src/cgeo/geocaching/utils/MatcherWrapper.java @@ -0,0 +1,91 @@ +package cgeo.geocaching.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Wrapper around the regex {@link Matcher} class. This implementation optimizes the memory usage of the matched + * Strings. + * + */ +public class MatcherWrapper { + private final Matcher matcher; + + public MatcherWrapper(Pattern pattern, String input) { + this.matcher = pattern.matcher(input); + } + + /** + * see {@link Matcher#find()} + */ + public boolean find() { + return matcher.find(); + } + + /** + * see {@link Matcher#group(int)} + */ + public String group(int index) { + return newString(matcher.group(index)); + } + + /** + * This method explicitly creates a new String instance from an already existing String. This is necessary to avoid + * huge memory leaks in our parser. If we do regular expression matching on large Strings, the returned matches are + * otherwise memory mapped substrings of the huge original String, therefore blocking the garbage collector from + * removing the huge input String. + * <p> + * Do not change this method, even if Findbugs and other tools will report a violation for that line! + * + * @param input + * @return + */ + private static String newString(String input) { + if (input == null) { + return null; + } + return new String(input); // DON'T REMOVE THE "new String" HERE! + } + + /** + * see {@link Matcher#groupCount()} + */ + public int groupCount() { + return matcher.groupCount(); + } + + /** + * see {@link Matcher#group()} + */ + public String group() { + return newString(matcher.group()); + } + + /** + * see {@link Matcher#start()} + */ + public int start() { + return matcher.start(); + } + + /** + * see {@link Matcher#replaceAll(String)} + */ + public String replaceAll(String replacement) { + return newString(matcher.replaceAll(replacement)); + } + + /** + * see {@link Matcher#matches()} + */ + public boolean matches() { + return matcher.matches(); + } + + /** + * see {@link Matcher#replaceFirst(String)} + */ + public String replaceFirst(String replacement) { + return newString(matcher.replaceFirst(replacement)); + } +} diff --git a/main/src/cgeo/geocaching/utils/PeriodicHandler.java b/main/src/cgeo/geocaching/utils/PeriodicHandler.java index 3f6c345..ac6b22a 100644 --- a/main/src/cgeo/geocaching/utils/PeriodicHandler.java +++ b/main/src/cgeo/geocaching/utils/PeriodicHandler.java @@ -26,7 +26,7 @@ abstract public class PeriodicHandler extends Handler { * @param period * The period in milliseconds. */ - public PeriodicHandler(final long period) { + protected PeriodicHandler(final long period) { this.period = period; } diff --git a/main/src/cgeo/geocaching/utils/TranslationUtils.java b/main/src/cgeo/geocaching/utils/TranslationUtils.java index a29c5a7..4d318f0 100644 --- a/main/src/cgeo/geocaching/utils/TranslationUtils.java +++ b/main/src/cgeo/geocaching/utils/TranslationUtils.java @@ -1,12 +1,11 @@ package cgeo.geocaching.utils; import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.network.Network; import android.content.Intent; import android.net.Uri; -import java.net.URLEncoder; - /** * Utilities used for translating */ @@ -30,7 +29,7 @@ public final class TranslationUtils { * @return URI ready to be parsed */ private static String buildTranslationURI(final String toLang, final String text) { - String content = URLEncoder.encode(text); + String content = Network.encode(text); // the app works better without the "+", the website works better with "+", therefore assume using the app if installed if (ProcessUtils.isInstalled(TRANSLATION_APP)) { content = content.replace("+", "%20"); diff --git a/main/src/com/viewpagerindicator/TitlePageIndicator.java b/main/src/com/viewpagerindicator/TitlePageIndicator.java index a181fed..94ac962 100644 --- a/main/src/com/viewpagerindicator/TitlePageIndicator.java +++ b/main/src/com/viewpagerindicator/TitlePageIndicator.java @@ -65,7 +65,7 @@ public class TitlePageIndicator extends View implements PageIndicator { public final int value; - private IndicatorStyle(int value) { + IndicatorStyle(int value) { this.value = value; } @@ -686,15 +686,13 @@ public class TitlePageIndicator extends View implements PageIndicator { * @return The width of the view, honoring constraints from measureSpec */ private int measureWidth(int measureSpec) { - int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode != MeasureSpec.EXACTLY) { throw new IllegalStateException(getClass().getSimpleName() + " can only be used in EXACTLY mode."); } - result = specSize; - return result; + return specSize; } /** diff --git a/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java b/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java index 28950b9..af4c03e 100644 --- a/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java +++ b/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java @@ -233,9 +233,8 @@ public class AppManualReaderClient { // manuals this doesn't matter, as the user then can choose which // one to use on a single or permanent basis. // - String logTag = "appmanualclient"; - for ( ;; ) { - Uri uri = Uri.parse(URI_SCHEME_APPMANUAL + "://" + manualIdentifier + while (true) { + Uri uri = Uri.parse(URI_SCHEME_APPMANUAL + "://" + manualIdentifier + localePath + "#topic='" + topic + "'"); // Note: we do not use a MIME type for this. intent.setData(uri); @@ -300,7 +299,8 @@ public class AppManualReaderClient { | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); } try { - if ( Log.isLoggable(logTag, Log.INFO) ) { + String logTag = "appmanualclient"; + if ( Log.isLoggable(logTag, Log.INFO) ) { Log.i(logTag, "Trying to activate manual: uri=" + uri.toString()); } diff --git a/main/src/org/openintents/intents/FileManagerIntents.java b/main/src/org/openintents/intents/FileManagerIntents.java new file mode 100644 index 0000000..8ff10c8 --- /dev/null +++ b/main/src/org/openintents/intents/FileManagerIntents.java @@ -0,0 +1,127 @@ +/*
+ * Copyright (C) 2008 OpenIntents.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openintents.intents;
+
+/**
+ * Provides OpenIntents actions, extras, and categories used by providers.
+ * <p>These specifiers extend the standard Android specifiers.</p>
+ */
+public final class FileManagerIntents {
+
+ /**
+ * Activity Action: Pick a file through the file manager, or let user
+ * specify a custom file name.
+ * Data is the current file name or file name suggestion.
+ * Returns a new file name as file URI in data.
+ *
+ * <p>Constant Value: "org.openintents.action.PICK_FILE"</p>
+ */
+ public static final String ACTION_PICK_FILE = "org.openintents.action.PICK_FILE";
+
+ /**
+ * Activity Action: Pick a directory through the file manager, or let user
+ * specify a custom file name.
+ * Data is the current directory name or directory name suggestion.
+ * Returns a new directory name as file URI in data.
+ *
+ * <p>Constant Value: "org.openintents.action.PICK_DIRECTORY"</p>
+ */
+ public static final String ACTION_PICK_DIRECTORY = "org.openintents.action.PICK_DIRECTORY";
+
+ /**
+ * Activity Action: Move, copy or delete after select entries.
+ * Data is the current directory name or directory name suggestion.
+ *
+ * <p>Constant Value: "org.openintents.action.MULTI_SELECT"</p>
+ */
+ public static final String ACTION_MULTI_SELECT = "org.openintents.action.MULTI_SELECT";
+
+ public static final String ACTION_SEARCH_STARTED = "org.openintents.action.SEARCH_STARTED";
+
+ public static final String ACTION_SEARCH_FINISHED = "org.openintens.action.SEARCH_FINISHED";
+
+ /**
+ * The title to display.
+ *
+ * <p>This is shown in the title bar of the file manager.</p>
+ *
+ * <p>Constant Value: "org.openintents.extra.TITLE"</p>
+ */
+ public static final String EXTRA_TITLE = "org.openintents.extra.TITLE";
+
+ /**
+ * The text on the button to display.
+ *
+ * <p>Depending on the use, it makes sense to set this to "Open" or "Save".</p>
+ *
+ * <p>Constant Value: "org.openintents.extra.BUTTON_TEXT"</p>
+ */
+ public static final String EXTRA_BUTTON_TEXT = "org.openintents.extra.BUTTON_TEXT";
+
+ /**
+ * Flag indicating to show only writeable files and folders.
+ *
+ * <p>Constant Value: "org.openintents.extra.WRITEABLE_ONLY"</p>
+ */
+ public static final String EXTRA_WRITEABLE_ONLY = "org.openintents.extra.WRITEABLE_ONLY";
+
+ /**
+ * The path to prioritize in search. Usually denotes the path the user was on when the search was initiated.
+ *
+ * <p>Constant Value: "org.openintents.extra.SEARCH_INIT_PATH"</p>
+ */
+ public static final String EXTRA_SEARCH_INIT_PATH = "org.openintents.extra.SEARCH_INIT_PATH";
+
+ /**
+ * The search query as sent to SearchService.
+ *
+ * <p>Constant Value: "org.openintents.extra.SEARCH_QUERY"</p>
+ */
+ public static final String EXTRA_SEARCH_QUERY = "org.openintents.extra.SEARCH_QUERY";
+
+ /**
+ * <p>Constant Value: "org.openintents.extra.DIR_PATH"</p>
+ */
+ public static final String EXTRA_DIR_PATH = "org.openintents.extra.DIR_PATH";
+
+ /**
+ * Extension by which to filter.
+ *
+ * <p>Constant Value: "org.openintents.extra.FILTER_FILETYPE"</p>
+ */
+ public static final String EXTRA_FILTER_FILETYPE = "org.openintents.extra.FILTER_FILETYPE";
+
+ /**
+ * Mimetype by which to filter.
+ *
+ * <p>Constant Value: "org.openintents.extra.FILTER_MIMETYPE"</p>
+ */
+ public static final String EXTRA_FILTER_MIMETYPE = "org.openintents.extra.FILTER_MIMETYPE";
+
+ /**
+ * Only show directories.
+ *
+ * <p>Constant Value: "org.openintents.extra.DIRECTORIES_ONLY"</p>
+ */
+ public static final String EXTRA_DIRECTORIES_ONLY = "org.openintents.extra.DIRECTORIES_ONLY";
+
+ public static final String EXTRA_DIALOG_FILE_HOLDER = "org.openintents.extra.DIALOG_FILE";
+
+ public static final String EXTRA_IS_GET_CONTENT_INITIATED = "org.openintents.extra.ENABLE_ACTIONS";
+
+ public static final String EXTRA_FILENAME = "org.openintents.extra.FILENAME";
+}
diff --git a/main/templates/mapsapikey.xml b/main/templates/mapsapikey.xml index 5514121..3655b5e 100644 --- a/main/templates/mapsapikey.xml +++ b/main/templates/mapsapikey.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> <resources> - <string name="maps_api_key">@maps.api.key@</string> + <string name="maps_api_key" translatable="false">@maps.api.key@</string> </resources> diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 62813a2..64d30cd 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="cgeo.geocaching.test" - android:versionCode="1" - android:versionName="1.0" - name="c:geo Tests"> - <uses-sdk android:minSdkVersion="4" /> + package="cgeo.geocaching.test" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="13"/> <instrumentation android:targetPackage="cgeo.geocaching" android:name="android.test.InstrumentationTestRunner" /> - <application android:icon="@drawable/icon" android:label="@string/app_name"> + <application android:icon="@drawable/icon" android:label="@string/app_name" android:allowBackup="false"> <uses-library android:name="android.test.runner" /> </application> diff --git a/tests/build.xml b/tests/build.xml index b5596c3..2afa27b 100644 --- a/tests/build.xml +++ b/tests/build.xml @@ -45,6 +45,26 @@ unless="sdk.dir"
/>
+ <target name="run-acceptance-tests" depends="clean, debug, install" >
+
+ <property name="log.file" value="acceptance_tests_standard_out.txt" />
+ <!-- because we don't have control over the 'test' target (to check for passes an fails) this prints to standard out
+ we capture standard out into a file and query this to see if we have any test failures, using this to pass/fail our task -->
+ <record name="${log.file}" action="start" />
+ <antcall target="test" />
+ <record name="${log.file}" action="stop" />
+
+ <loadfile property="tests.output" srcFile="${log.file}" />
+
+ <echo>Checking for failures</echo>
+ <fail message="Acceptance tests FAILED!!!" >
+ <condition>
+ <contains string="${tests.output}" substring="FAILURES" />
+ </condition>
+ </fail>
+
+ <echo>Acceptance tests passed!</echo>
+ </target>
<!-- extension targets. Uncomment the ones where you want to do custom work
in between standard targets -->
@@ -79,7 +99,7 @@ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
- <!-- version-tag: 1 -->
+ <!-- version-tag: custom -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>
diff --git a/tests/libs/docs/robotium-solo-3.6-javadoc.jar b/tests/libs/docs/robotium-solo-3.6-javadoc.jar Binary files differnew file mode 100644 index 0000000..db4e75b --- /dev/null +++ b/tests/libs/docs/robotium-solo-3.6-javadoc.jar diff --git a/tests/libs/robotium-solo-3.6.jar b/tests/libs/robotium-solo-3.6.jar Binary files differnew file mode 100644 index 0000000..4280906 --- /dev/null +++ b/tests/libs/robotium-solo-3.6.jar diff --git a/tests/libs/robotium-solo-3.6.jar.properties b/tests/libs/robotium-solo-3.6.jar.properties new file mode 100644 index 0000000..10e60fa --- /dev/null +++ b/tests/libs/robotium-solo-3.6.jar.properties @@ -0,0 +1 @@ +doc=./docs/robotium-solo-3.6-javadoc.jar
\ No newline at end of file diff --git a/tests/res/raw/gc430fm_published.html b/tests/res/raw/gc430fm_published.html new file mode 100644 index 0000000..6d7d728 --- /dev/null +++ b/tests/res/raw/gc430fm_published.html @@ -0,0 +1,2245 @@ +
+<!DOCTYPE html>
+<html lang="en" class="no-js">
+<head id="ctl00_Head1"><meta charset="utf-8" />
+ <!--[if IE]><![endif]-->
+ <title>
+ GC430FM Cache is Unpublished (Unknown Cache) in California, United States created by The North Star
+</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta name="author" content="Groundspeak, Inc." /><meta name="DC.creator" content="Groundspeak, Inc." /><meta name="Copyright" content="Copyright (c) 2000-2012 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2012 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><meta http-equiv="X-UA-Compatible" content="IE=8" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/reset.css" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/typography.css" /><link rel="stylesheet" type="text/css" media="screen,projection" href="../css/blueprint/src/grid.css" />
+ <!--[if lt IE 8]>
+ <link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/ie.css" />
+ <![endif]-->
+ <link id="uxCssMaster" rel="stylesheet" type="text/css" media="screen,projection" href="../css/tlnMasterScreen.css?r=1" /><link id="uxCssMain" rel="stylesheet" type="text/css" media="all" href="../css/tlnMain.css?r=1" /><link rel="Stylesheet" type="text/css" media="all" href="../css/jqueryui1810/jquery-ui-1.8.10.custom.css" /><link rel="stylesheet" type="text/css" media="all" href="/js/jquery_plugins/jquery.jgrowl.css" /><link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" />
+ <script type="text/javascript" src="/js/modernizr-1.7.min.js"></script>
+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.min.js"></script>
+ <script type="text/javascript" src="/js/jquery.truncate.min.js"></script>
+
+
+
+ <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" />
+ <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" />
+ <link href="/js/jquery_plugins/tipTip/tipTip.css" rel="stylesheet" type="text/css" />
+ <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" />
+ <!--[if lte IE 8]>
+ <style type="text/css" media="all">
+ legend{
+ position: absolute;
+ top: -.6em;
+ left: 1em;
+ line-height: 1.3;
+ }
+ fieldset p{
+ margin-top:1em;
+ }
+ img.CacheNoteHelpImg{
+ top:-.2em;
+ }
+ </style>
+ <![endif]-->
+ <style type="text/css" media="screen,projection">
+ #otherSearchOptions li
+ {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ }
+ .ff
+ {
+ font-family: "Andale Mono" , "Courier New" ,Courier,monospace;
+ }
+ .fr
+ {
+ margin-top: 1.5em;
+ float: right;
+ }
+ .fl
+ {
+ float: left;
+ }
+ .clsCell
+ {
+ border: 1px solid #c0cee3;
+ font-size: 80%;
+ background-color: #fff;
+ }
+ .clsResultTitle, .clsResultTitleNoBold
+ {
+ color: #0000de;
+ }
+ .clsResultDescription
+ {
+ color: #333;
+ }
+ .clsURL
+ {
+ color: #999;
+ }
+ a.title:link, a.title:visited, a.title:hover, a.title:active
+ {
+ color: #000;
+ text-decoration: underline;
+ }
+ a.title
+ {
+ text-align: right;
+ font-size: 10px;
+ font-family: arial,sans-serif;
+ padding: 0 1px 0 0;
+ }
+ #mapSizePager a:hover
+ {
+ font-weight: bold;
+ }
+ #mapSizePager ul
+ {
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+ #mapSizePager li
+ {
+ float: left;
+ list-style: none;
+ }
+ #mapSizePager li a
+ {
+ font-family: verdana,sans-serif;
+ font-size: x-small;
+ display: block;
+ margin: 0 2px 0 0;
+ padding: 4px;
+ text-decoration: none;
+ border: solid 1px #c0c0c0;
+ height: 10px;
+ min-width: 10px;
+ cursor: pointer;
+ }
+ #mapPrintingNotes
+ {
+ width: 280px;
+ text-align: left;
+ overflow: auto;
+ }
+ .inplace_field {
+ width:100%;
+ resize: none;
+ }
+ legend.note{
+ background:url('../images/icons/16/user_note.png') no-repeat 0 0;
+ padding-left:18px;
+ }
+ legend.warning{
+ background:url('../images/icons/16/take_note.png') no-repeat 0 0;
+ padding-left:18px;
+ }
+ fieldset.CacheNote{
+ border-color: #e9a24c !important;
+ background-color:#ffffde;
+ position:relative;
+ }
+ .CacheNoteHelpImg{
+ position:relative;
+ cursor:pointer;
+ top:-1em;
+ right:-.75em;
+ float:right;
+ }
+ .InformationWidget h3{
+ margin-bottom:.5em;
+ }
+ .InformationWidget .AlignRight{
+ font-size:.8em;
+ }
+ #tiptip_content{
+ *background-color:#000;
+ box-shadow:none;
+ }
+ .maxed{
+ color:#992a2a;
+ }
+
+
+ span.ccu-parseverify-distance img{
+ text-align:center !important;
+ vertical-align:text-bottom !important;
+ }
+ .edit-cache-coordinates{
+ text-decoration: none;
+ color: #000 !important;
+ background: url(/images/icons/16/edit.png) no-repeat right 0;
+ padding:2px 20px 2px 0px;
+ margin-right:4px;
+ }
+ .ccc-coord{
+ cursor: text;
+ font-family: Courier New, Sans-Serif;
+ }
+ .ccu-update dl {
+ margin-bottom:.25em;
+ }
+ .ccu-update dt{
+ float:left;
+ min-width:90px;
+ }
+ .ccu-update .ui-button-text-only .ui-button-text{
+ padding:.3em .75em;
+ }
+ .ccu-parseverify-coords{
+ font-style:italic;
+ margin-right:.25em;
+ }
+ .ccu-parseverify-accept, .ccu-parseverify-cancel{
+ margin-top:-5px;
+ }
+ .ui-tooltip-widget .ui-tooltip-content{
+ border-width:1px;
+ background-color:#fff;
+ border-color:#c0cee3;
+ color:#594a42;
+ padding:1em;
+ width:420px;
+ }
+ .myLatLon {
+ border-bottom:2px solid #c0cee3;
+ font-style:italic;
+ }
+ .leaflet-control-attribution{
+ padding:3px !important;
+ }
+ .leaflet-control-attribution img{
+ vertical-align:middle;
+ }
+ </style>
+ <link rel="Stylesheet" type="text/css" media="screen" href="/hide/css/CSPScreen.css" />
+ <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/v5/leaflet.css" />
+ <!--[if IE]>
+ <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/v5/leaflet.ie.css" />
+ <![endif]-->
+ <script type="text/javascript" language="javascript" src="/js/leaflet/v5/leaflet.js"></script>
+ <script type="text/javascript" src="/js/jquery.pagemethods.js"></script>
+ <script type="text/javascript" src="/js/geometa.js"></script>
+ <script type="text/javascript">
+ var userToken = null,
+ urlParams = {},
+ mapLatLng = null,
+ cmapAdditionalWaypoints = [],
+ initalLogs = null, totalLogs = 0, includeAvatars = false;
+
+ (function () {
+ var e,
+ d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); },
+ q = window.location.search.substring(1),
+ r = /([^&=]+)=?([^&]*)/g;
+
+ while (e = r.exec(q)) {
+ urlParams[d(e[1])] = d(e[2]);
+ }
+ })();
+ </script>
+<meta name="og:site_name" content="Geocaching.com" property="og:site_name" /><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?guid=af38aaf9-5386-40bb-92f0-025ebc7700a7" property="og:url" /><meta name="og:description" content="Solve the mystery and then use a smartphone or GPS device to navigate to the solution coordinates. Look for a micro hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 1.5 and difficulty is 4 (out of 5)." property="og:description" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/8.png" property="og:image" /><meta name="og:title" content="Cache is Unpublished" property="og:title" /><meta name="description" content="Cache is Unpublished (GC430FM) was created by The North Star on 12/19/2012. It's a Micro size geocache, with difficulty of 4, terrain of 1.5. It's located in California, United States. The cache is not at the posted coordinates but is less than 2 miles awayI obtained a Geocache waypoint (GC#) on 02/12/12 for a cache that was not published." /></head>
+<body >
+ <form name="aspnetForm" method="post" action="cache_details.aspx?guid=af38aaf9-5386-40bb-92f0-025ebc7700a7" onsubmit="javascript:return WebForm_OnSubmit();" onkeypress="javascript:return WebForm_FireDefaultButton(event, 'ctl00_btnSignIn')" id="aspnetForm">
+<div>
+<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
+<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
+<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="2" />
+<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTc1MjcwNzgxNg8WAh4EQy5JRCgpWVN5c3RlbS5JbnQ2NCwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BzMzNzI4MjIWAmYPZBYGZg9kFgoCBg8WAh4EVGV4dAViPG1ldGEgbmFtZT0iQ29weXJpZ2h0IiBjb250ZW50PSJDb3B5cmlnaHQgKGMpIDIwMDAtMjAxMiBHcm91bmRzcGVhaywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLiIgLz5kAgcPFgIfAQVHPCEtLSBDb3B5cmlnaHQgKGMpIDIwMDAtMjAxMiBHcm91bmRzcGVhaywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAtLT5kAhoPFgIeBGhyZWYFHX4vY3NzL3Rsbk1hc3RlclNjcmVlbi5jc3M/cj0xZAIbDxYCHwIFFX4vY3NzL3Rsbk1haW4uY3NzP3I9MWQCIA8WAh4HVmlzaWJsZWhkAgEPZBYSAgUPFgIfAWRkAgcPFgIfA2cWAgIdDw8WAh4LUG9zdEJhY2tVcmwFfmh0dHBzOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2xvZ2luL2RlZmF1bHQuYXNweD9yZWRpcj0lMmZzZWVrJTJmY2FjaGVfZGV0YWlscy5hc3B4JTNmZ3VpZCUzZGFmMzhhYWY5LTUzODYtNDBiYi05MmYwLTAyNWViYzc3MDBhN2RkAggPZBYCAgUPDxYCHgtOYXZpZ2F0ZVVybAWlAWh0dHBzOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2xvZ2luL2RlZmF1bHQuYXNweD9SRVNFVD1ZJnJlZGlyPWh0dHAlM2ElMmYlMmZ3d3cuZ2VvY2FjaGluZy5jb20lMmZzZWVrJTJmY2FjaGVfZGV0YWlscy5hc3B4JTNmZ3VpZCUzZGFmMzhhYWY5LTUzODYtNDBiYi05MmYwLTAyNWViYzc3MDBhN2RkAgwPFgIfA2dkAiwPZBYEAgMPFgIfAQUHRW5nbGlzaGQCBQ8WAh4LXyFJdGVtQ291bnQCEBYgZg9kFgICAQ8PFggeD0NvbW1hbmRBcmd1bWVudAUFZW4tVVMeC0NvbW1hbmROYW1lBQ1TZXRUZW1wTG9jYWxlHwEFB0VuZ2xpc2geEENhdXNlc1ZhbGlkYXRpb25oZGQCAQ9kFgICAQ8PFggfBwUFZGUtREUfCAUNU2V0VGVtcExvY2FsZR8BBQdEZXV0c2NoHwloZGQCAg9kFgICAQ8PFggfBwUFZnItRlIfCAUNU2V0VGVtcExvY2FsZR8BBQlGcmFuw6dhaXMfCWhkZAIDD2QWAgIBDw8WCB8HBQVwdC1QVB8IBQ1TZXRUZW1wTG9jYWxlHwEFClBvcnR1Z3XDqnMfCWhkZAIED2QWAgIBDw8WCB8HBQVjcy1DWh8IBQ1TZXRUZW1wTG9jYWxlHwEFCcSMZcWhdGluYR8JaGRkAgUPZBYCAgEPDxYIHwcFBXN2LVNFHwgFDVNldFRlbXBMb2NhbGUfAQUHU3ZlbnNrYR8JaGRkAgYPZBYCAgEPDxYIHwcFBWVzLUVTHwgFDVNldFRlbXBMb2NhbGUfAQUIRXNwYcOxb2wfCWhkZAIHD2QWAgIBDw8WCB8HBQVpdC1JVB8IBQ1TZXRUZW1wTG9jYWxlHwEFCEl0YWxpYW5vHwloZGQCCA9kFgICAQ8PFggfBwUFbmwtTkwfCAUNU2V0VGVtcExvY2FsZR8BBQpOZWRlcmxhbmRzHwloZGQCCQ9kFgICAQ8PFggfBwUFY2EtRVMfCAUNU2V0VGVtcExvY2FsZR8BBQdDYXRhbMOgHwloZGQCCg9kFgICAQ8PFggfBwUFcGwtUEwfCAUNU2V0VGVtcExvY2FsZR8BBQZQb2xza2kfCWhkZAILD2QWAgIBDw8WCB8HBQVldC1FRR8IBQ1TZXRUZW1wTG9jYWxlHwEFBUVlc3RpHwloZGQCDA9kFgICAQ8PFggfBwUFbmItTk8fCAUNU2V0VGVtcExvY2FsZR8BBQ5Ob3JzaywgQm9rbcOlbB8JaGRkAg0PZBYCAgEPDxYIHwcFBWtvLUtSHwgFDVNldFRlbXBMb2NhbGUfAQUJ7ZWc6rWt7Ja0HwloZGQCDg9kFgICAQ8PFggfBwUFaHUtSFUfCAUNU2V0VGVtcExvY2FsZR8BBQZNYWd5YXIfCWhkZAIPD2QWAgIBDw8WCB8HBQVyby1STx8IBQ1TZXRUZW1wTG9jYWxlHwEFCFJvbcOibsSDHwloZGQCLg9kFgICAw8WAh8DaGQCLw8WAh4FY2xhc3MFDHNwYW4tMjQgbGFzdBYCAgEPZBYuAgEPZBYCZg9kFgICAQ8PFgIfAQUHR0M0MzBGTWRkAgIPFgIfAQWeATxhIGhyZWY9Ii9hYm91dC9jYWNoZV90eXBlcy5hc3B4IiB0YXJnZXQ9Il9ibGFuayIgdGl0bGU9IkFib3V0IENhY2hlIFR5cGVzIj48aW1nIHNyYz0iL2ltYWdlcy9XcHRUeXBlcy84LmdpZiIgYWx0PSJVbmtub3duIENhY2hlIiB0aXRsZT0iVW5rbm93biBDYWNoZSIgLz48L2E+ZAIGD2QWBAIBDxYCHwNnZAIGDxYCHwNoZAIHDxYCHwEFHEluIENhbGlmb3JuaWEsIFVuaXRlZCBTdGF0ZXNkAgsPFgIfA2hkAgwPFgIfA2dkAg0PDxYCHwNoZGQCEA8WAh8DaBYCAgEPFgIfAQWXAllvdSBtdXN0IGJlIDxhIGhyZWY9Imh0dHBzOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2xvZ2luLz9SRVNFVD1ZJnJlZGlyPWh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vc2Vlay9jYWNoZV9kZXRhaWxzLmFzcHg/Z3VpZD1hZjM4YWFmOS01Mzg2LTQwYmItOTJmMC0wMjVlYmM3NzAwYTciIHRpdGxlPSJMb2cgSW4iPmxvZ2dlZCBpbjwvYT4gd2l0aCBhIEdlb2NhY2hpbmcuY29tIGFjY291bnQgdG8gdmlldyB0aGUgc3BlY2lmaWMgbG9jYXRpb24gb2YgdGhpcyBnZW9jYWNoZS4gSXQncyBmcmVlIWQCEQ8WAh8DaGQCEg8WAh8DaBYOAgMPFgIeBXN0eWxlBQ1kaXNwbGF5Om5vbmU7FgICAQ8WAh8BZWQCDQ8PFgQfBQUzY2RwZi5hc3B4P2d1aWQ9YWYzOGFhZjktNTM4Ni00MGJiLTkyZjAtMDI1ZWJjNzcwMGE3HwNoZGQCDw8PFgIfBQU4Y2RwZi5hc3B4P2d1aWQ9YWYzOGFhZjktNTM4Ni00MGJiLTkyZjAtMDI1ZWJjNzcwMGE3JmxjPTVkZAIRDw8WAh8FBTljZHBmLmFzcHg/Z3VpZD1hZjM4YWFmOS01Mzg2LTQwYmItOTJmMC0wMjVlYmM3NzAwYTcmbGM9MTBkZAITDw8WBh8FBV5odHRwOi8vbWFwcy5nb29nbGUuY29tL21hcHM/Zj1kJmhsPWVuJnNhZGRyPSZkYWRkcj0zNy4zOTgzMzMsLTEyMS45MTY2NjcoQ2FjaGUraXMrVW5wdWJsaXNoZWQpHgZUYXJnZXQFBl9ibGFuax8DaGRkAhUPFgIfA2hkAhsPFgIfA2gWBAIBDw8WBh4JRm9yZUNvbG9yCk4eB0VuYWJsZWRoHgRfIVNCAgRkZAIDDw8WBh8NCk4fDmgfDwIEZGQCFw9kFghmDxYCHwNoZAIBDw8WAh8DaGRkAgIPDxYCHwNoZGQCAw8WAh8DaGQCGA9kFgICAw8PFgIfAQUHRGVjcnlwdGRkAhkPFgIfAQWiAVF2cSBsYmggeGFiaiBndW5nIGxiaCBwbmEgc3ZhcSBuIHl2ZmcgYnMgPGI+RXJwcmFneWwgSXZyanJxIFBucHVyZjwvYj4gaGFxcmUgPGI+TGJoZSBDZWJzdnlyPC9iPj8g4oCcSXZyaiBOeXnigJ0gZ2IgZnJyIGd1ciB5bmZnIDUwIHBucHVyZiBndW5nIGxiaCB1bmlyIGl2cmpyceKApmQCHA8WAh8DaGQCHQ8PFgIfA2hkZAIfDxYCHwNoZAIiD2QWAgIBD2QWBAIBDw8WAh8BBf8DPGlmcmFtZSB0eXBlPSJpZnJhbWUiIHNyYz0iaHR0cDovL2Fkcy5ncm91bmRzcGVhay5jb20vYS5hc3B4P1pvbmVJRD05JlRhc2s9R2V0JlNpdGVJRD0xJlg9JzE2NTQ0OTU2NDhjOTRjNGI5ZDE1YzUxNTUyYzU3MTBhJyIgd2lkdGg9IjEyMCIgaGVpZ2h0PSIyNDAiIE1hcmdpbndpZHRoPSIwIiBNYXJnaW5oZWlnaHQ9IjAiIEhzcGFjZT0iMCIgVnNwYWNlPSIwIiBGcmFtZWJvcmRlcj0iMCIgU2Nyb2xsaW5nPSJubyIgc3R5bGU9IndpZHRoOjEyMHB4O0hlaWdodDoyNDBweDsiPjxhIGhyZWY9Imh0dHA6Ly9hZHMuZ3JvdW5kc3BlYWsuY29tL2EuYXNweD9ab25lSUQ9OSZUYXNrPUNsaWNrJjtNb2RlPUhUTUwmU2l0ZUlEPTEiIHRhcmdldD0iX2JsYW5rIj48aW1nIHNyYz0iaHR0cDovL2Fkcy5ncm91bmRzcGVhay5jb20vYS5hc3B4P1pvbmVJRD05JlRhc2s9R2V0Jk1vZGU9SFRNTCZTaXRlSUQ9MSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSIyNDAiIGJvcmRlcj0iMCIgYWx0PSIiIC8+PC9hPjwvaWZyYW1lPmRkAgMPFgIeCWlubmVyaHRtbAUTQWR2ZXJ0aXNpbmcgd2l0aCBVc2QCJg9kFgQCBQ8PFgIfA2dkZAIJDw8WAh8FBTx+L3RyYWNrL3NlYXJjaC5hc3B4P3dpZD1hZjM4YWFmOS01Mzg2LTQwYmItOTJmMC0wMjVlYmM3NzAwYTdkZAInDw8WAh8DZ2QWAmYPFgIfBgIBFgICAQ9kFgRmDxUDAFdodHRw" />
+<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="Oi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD05ZmQzOWZiOC05NTAyLTQ3YjQtYWUwOC04NmNlMjM2ZmM2NjEbZm1vcmFlcyYjMzk7IHNvbHZlZCBidXQgZmFyZAICDxUCTGh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD00NDBjZjYxYi1kY2YzLTQyMjAtYTg3Ny1jZTMxMmYxMDM5MjEHZm1vcmFlc2QCKQ9kFhQCAQ8PFgIfA2hkZAIHDw8WAh8DaGRkAhEPDxYCHwUFIy9zZWVrL25lYXJlc3QuYXNweD91PVRoZStOb3J0aCtTdGFyZGQCFQ8PFgIfBQUkL3NlZWsvbmVhcmVzdC5hc3B4P3VsPVRoZStOb3J0aCtTdGFyZGQCGQ8WAh8DaBYKAgMPDxYCHwUFWC9zZWVrL25lYXJlc3QuYXNweD90eD00MDg2MTgyMS0xODM1LTRlMTEtYjY2Ni04ZDQxMDY0ZDAzZmUmbGF0PTM3LjM5ODMzMyZsbmc9LTEyMS45MTY2NjdkZAIFDw8WAh8FBVwvc2Vlay9uZWFyZXN0LmFzcHg/dHg9NDA4NjE4MjEtMTgzNS00ZTExLWI2NjYtOGQ0MTA2NGQwM2ZlJmxhdD0zNy4zOTgzMzMmbG5nPS0xMjEuOTE2NjY3JmY9MWRkAgkPDxYCHwUFMC9zZWVrL25lYXJlc3QuYXNweD9sYXQ9MzcuMzk4MzMzJmxuZz0tMTIxLjkxNjY2N2RkAgsPDxYCHwUFNC9zZWVrL25lYXJlc3QuYXNweD9sYXQ9MzcuMzk4MzMzJmxuZz0tMTIxLjkxNjY2NyZmPTFkZAIPDw8WAh8FBUpodHRwOi8vd3d3LndheW1hcmtpbmcuY29tL2RpcmVjdG9yeS5hc3B4P2Y9MSZsYXQ9MzcuMzk4MzMzJmxvbj0tMTIxLjkxNjY2N2RkAhsPFgIfA2hkAh8PDxYCHwUFIS9yZXZpZXdzL2hvdGVscy1pbi1NaWxwaXRhcyxDQSxVU2RkAiEPDxYCHwNoZGQCIw8PFgIfA2hkZAInD2QWCAIBDxYCHwEFDzcgTG9nZ2VkIFZpc2l0c2QCBw8PFgIfBQVDfi9zZWVrL2NhY2hlX2xvZ2Jvb2suYXNweD9ndWlkPWFmMzhhYWY5LTUzODYtNDBiYi05MmYwLTAyNWViYzc3MDBhN2RkAggPFgIfA2hkAgkPDxYCHwNoZGQCKg8WAh8BBQVmYWxzZWQCKw8WAh8BBR5sYXQ9bnVsbDtsbmc9bnVsbDtndWlkPW51bGw7DQpkAiwPFgIfAQV1dHJ5IHsgX2dhcS5wdXNoKFsnX3RyYWNrRXZlbnQnLCAnR2VvY2FjaGluZycsICdDYWNoZURldGFpbHNNZW1iZXJUeXBlJywgJ05vdFNpZ25lZEluJywgbnVsbCwgdHJ1ZV0pOyB9IGNhdGNoKGVycikgeyB9ZAIwDxYCHwNoZAIxD2QWBAIDDxYCHwEFB0VuZ2xpc2hkAgUPFgIfBgIQFiBmD2QWAgIBDw8WCB8HBQVlbi1VUx8IBQ1TZXRUZW1wTG9jYWxlHwEFB0VuZ2xpc2gfCWhkZAIBD2QWAgIBDw8WCB8HBQVkZS1ERR8IBQ1TZXRUZW1wTG9jYWxlHwEFB0RldXRzY2gfCWhkZAICD2QWAgIBDw8WCB8HBQVmci1GUh8IBQ1TZXRUZW1wTG9jYWxlHwEFCUZyYW7Dp2Fpcx8JaGRkAgMPZBYCAgEPDxYIHwcFBXB0LVBUHwgFDVNldFRlbXBMb2NhbGUfAQUKUG9ydHVndcOqcx8JaGRkAgQPZBYCAgEPDxYIHwcFBWNzLUNaHwgFDVNldFRlbXBMb2NhbGUfAQUJxIxlxaF0aW5hHwloZGQCBQ9kFgICAQ8PFggfBwUFc3YtU0UfCAUNU2V0VGVtcExvY2FsZR8BBQdTdmVuc2thHwloZGQCBg9kFgICAQ8PFggfBwUFZXMtRVMfCAUNU2V0VGVtcExvY2FsZR8BBQhFc3Bhw7FvbB8JaGRkAgcPZBYCAgEPDxYIHwcFBWl0LUlUHwgFDVNldFRlbXBMb2NhbGUfAQUISXRhbGlhbm8fCWhkZAIID2QWAgIBDw8WCB8HBQVubC1OTB8IBQ1TZXRUZW1wTG9jYWxlHwEFCk5lZGVybGFuZHMfCWhkZAIJD2QWAgIBDw8WCB8HBQVjYS1FUx8IBQ1TZXRUZW1wTG9jYWxlHwEFB0NhdGFsw6AfCWhkZAIKD2QWAgIBDw8WCB8HBQVwbC1QTB8IBQ1TZXRUZW1wTG9jYWxlHwEFBlBvbHNraR8JaGRkAgsPZBYCAgEPDxYIHwcFBWV0LUVFHwgFDVNldFRlbXBMb2NhbGUfAQUFRWVzdGkfCWhkZAIMD2QWAgIBDw8WCB8HBQVuYi1OTx8IBQ1TZXRUZW1wTG9jYWxlHwEFDk5vcnNrLCBCb2ttw6VsHwloZGQCDQ9kFgICAQ8PFggfBwUFa28tS1IfCAUNU2V0VGVtcExvY2FsZR8BBQntlZzqta3slrQfCWhkZAIOD2QWAgIBDw8WCB8HBQVodS1IVR8IBQ1TZXRUZW1wTG9jYWxlHwEFBk1hZ3lhch8JaGRkAg8PZBYCAgEPDxYIHwcFBXJvLVJPHwgFDVNldFRlbXBMb2NhbGUfAQUIUm9tw6JuxIMfCWhkZAIDDxYCHwEFK1NlcnZlcjogV0VCMDM7IEJ1aWxkOiBXZWIuSG90Rml4XzIwMTIxMjExLjFkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBRJjdGwwMCRjYlJlbWVtYmVyTWUTsUNZ99o/ZMkVlQ0TmeDu4Dizww==" />
+</div>
+
+<script type="text/javascript">
+//<![CDATA[
+var theForm = document.forms['aspnetForm'];
+if (!theForm) {
+ theForm = document.aspnetForm;
+}
+function __doPostBack(eventTarget, eventArgument) {
+ if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
+ theForm.__EVENTTARGET.value = eventTarget;
+ theForm.__EVENTARGUMENT.value = eventArgument;
+ theForm.submit();
+ }
+}
+//]]>
+</script>
+
+
+<script src="/WebResource.axd?d=Dh2VENdI9XyWNN0f7DnYfR8WWRCRIzdVqal2y0yjiQ5nC_eHhLchYgnQDHIk0d3RCcSUMVZ36ciRD0qmhXKmeu3S_RE1&t=634449413070371108" type="text/javascript"></script>
+
+
+<script src="/ScriptResource.axd?d=8q09cuy9-PZDS8eZx6HLVXd3YZywgUmuoy8VVtGr3vaISS8ybaBLyQLFlq93nr2dlYP0QJWcJvooQKkloTdALTrS571k1UcPpD2pbXbpthIOf2Mn8gCnpyvfv-ZudWTMi0y39YZC0-Q0yjjxQ82yTlKdhBw1&t=6df0ad7a" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=I9_m2Hb1Tv_B0qTMDG8bMbnkNSHUkv5oUaG9-V5NZ8qQ2VFlu60I8y8gfr3vPmZjbiPnu43MOQdFVDeYF-nDAEKBLmyxD3DCTGmes9NNbbvaDEHyEuuRWgccIkK3ik5TI48YGDxjHjqdn-gTK4Fkgd17LGw1&t=2610f696" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=8vNbe34dAujgZMPnfnacfjeoweX1vHgyns8KlAV4vpGpsZC9Cf3pro__lv8ekBa0NiCgXGMMolzOUNH__lrnEI_qjlNBIAuuLeemtAXV_i6E0QIMZa8nGSYmWGF5nQOJK3rmZzvTxsr2Mh4Ebdba_1ywGLUSH_U_XIe-jzecfRQwwvjZ0&t=2610f696" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=l5IqBBbOFPRmpVAJwxQpHQyZ16ITBnk7fYRIeFc1JaDh64igpOv-k92v3DpzWBikWWvRdoxgNXda9cdmIFt2Ryy2gD2Tv71tVdwVNB4i-d1_vwLdJifCsG55PNiibmPX-x1Vspbf6jGBVWDKxT4kuLr2vWh-XRcY7PiryWks0UgjSCXEHO05VytTmCI6A-IhnCg2kD_i3YytsXr36qf0k6q0vQ41" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=mw8CUwVrYP9IGhC7WIGT8qdlVInGzqviii3RV8GrEEiOV2Nqjk57cAorEy9ACR1-rU7I3CZphWXcx81x-LDKIItu7BGPceT7Q61MOAXhSyJyW2DF3crLIX0Xef7vI1s2RLsp2bf8Aazkh-w4559ltQCi1H8uzBcnORltR9bo05Oe5VlRs1WnFqxyOK9aLEH4pBXNx8Bhb2-oIOLExj6kkCQgF06_A6ksiNnQXuGaKfXh1LjjCyujVv1xsxL_muSivN4bS4R4JR4M2Z3WmsBSnQXzJkIKkQB7kOS3JYimpNQ7sw1_qOYPZVB0xYbSCGD-xptYnX3Q4DLGiBNW4mP5R1Xv0QiVlwA9uiMAy_mQKBalvK4YjYdSbW9T9WZdtn39cD799HNy--sDKm1hhlBWb8Dz1jgxR2B9glqCYkqQmk3DSoPhPx9eWxB5q9VFjw1Q4u3d0Rgu8lF3NszOnHmJ19E6XZOdbRPyOjljcqTy1MWgNSwFAV-E3kWUGiJ0QNel49k3VkdjBUTKhIqIdQ9wve0zAcvWgxHEaFuvXv92aYmJwFYFDbNPvkYfBRLakBbpHIzGs9e0xu5sbTAVijArOHlzTSMNx2jK2mdt8VSjThXQAkMSV5W0jY2I6tuqFunlegJeA9zrFE9HdfbBtj9gOSe3LQQNMG7NaUShNTYUbJ5eZbQ8g7O5gjKFbDylaSZqv0aXQu0Lgrn7EdKV3B0BMhNeG3pR32zEBX1T3hEAnDKiYVOX0" type="text/javascript"></script>
+<script src="js/cachedetails.js" type="text/javascript"></script>
+<script src="../js/latlng.js" type="text/javascript"></script>
+<script src="/WebResource.axd?d=Np8DmZmh2tcIkgE9SU7mE6n1BWbJ0opng-rHikqBjFQo0nbLYSeBBVhJhCHcmx1ihKnAnQv_ZhnItUUjENzIzc1uoXk1&t=634449413070371108" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+function WebForm_OnSubmit() {
+if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;
+return true;
+}
+//]]>
+</script>
+
+<div>
+
+ <input type="hidden" name="__PREVIOUSPAGE" id="__PREVIOUSPAGE" value="Q3QLAIGc3fycf1xcmR0oeYDSmxzti-0045OC6NZQvsE42Tm2u2QIX8zoZDBQxLovJ-hK6GtvJtlghgEFizixxK5opmWjeHAxzOpw_rZ8ZR8kHZBX0" />
+</div>
+ <script type="text/javascript">
+//<![CDATA[
+Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00');
+//]]>
+</script>
+
+ <div id="Top" class="SkipLinks">
+
+ <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
+ <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
+
+ </div>
+
+ <!--[if lte IE 6]>
+ <div class="WarningMessage PhaseOut">
+
+ <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
+
+ </div>
+ <![endif]-->
+
+
+
+ <div class="PrintOnly">
+
+ <p>
+ <img src="/images/logo_print_bw.png" alt="Geocaching.com" /></p>
+ <hr />
+
+ </div>
+
+ <header>
+
+ <div class="container">
+
+ <h1 class="Logo span-16">
+ <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">Geocaching</a></h1>
+ <div class="ProfileWidget span-8 last">
+
+ <div id="ctl00_divNotSignedIn" class="FloatContainer">
+
+ <p class="NotSignedInText"><strong>Welcome, Visitor!</strong><br /></p>
+ <p class="LoginWithFacebook">
+ <a id="ctl00_uxSignIn" title="Login with Facebook" class="btnFacebookLogin NoWrap" href="javascript:__doPostBack('ctl00$uxSignIn','')"><span>Login with Facebook</span></a></p>
+ <p class="NotSignedInLinks clear">
+ <a id="hlSignIn" accesskey="s" title="Sign In" class="SignInLink" href="/login/">Sign In</a> | <a id="ctl00_hlRegister" accesskey="r" title="Sign Up" href="../membership/register.aspx?type=basic">Sign Up</a></p>
+ <div id="SignInWidget">
+
+ <h3>Sign In with Geocaching</h3>
+ <div id="ctl00_vsSignInWidgetForm" class="FormSummaryWidget FormErrorWidget InputWidth" style="color:Red;display:none;">
+
+</div>
+ <p>
+ <label for="ctl00_tbUsername" id="ctl00_lblUsername" title="Geocaching Username">Geocaching Username:</label><br />
+ <input name="ctl00$tbUsername" type="text" id="ctl00_tbUsername" class="text" autocomplete="off" />
+ <span id="ctl00_rfvUsername" title="Username is a required field; please enter a valid username." style="color:Red;display:none;"><span class="FormIcon FormValidationIcon">*</span></span>
+ </p>
+ <p>
+ <label for="ctl00_tbPassword" id="ctl00_lblPassword" title="Geocaching Password">Geocaching Password:</label><br />
+ <input name="ctl00$tbPassword" type="password" id="ctl00_tbPassword" class="text" autocomplete="off" />
+ <span id="ctl00_rfvPassword" title="Password is a required field; please enter a valid password." style="color:Red;display:none;"><span class="FormIcon FormValidationIcon">*</span></span>
+ </p>
+ <p>
+ <span class="Checkbox" title="Keep Me Signed In" autocomplete="off"><input id="ctl00_cbRememberMe" type="checkbox" name="ctl00$cbRememberMe" /><label for="ctl00_cbRememberMe">Keep Me Signed In</label></span><br />
+ <small>
+ Uncheck if on a shared computer.</small>
+ </p>
+ <p>
+ <input type="submit" name="ctl00$btnSignIn" value="Sign In" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$btnSignIn", "", true, "SignInForm", "https://www.geocaching.com/login/default.aspx?redir=%2fseek%2fcache_details.aspx%3fguid%3daf38aaf9-5386-40bb-92f0-025ebc7700a7", false, false))" id="ctl00_btnSignIn" title="Sign In" />
+ or
+ <a id="ctl00_hlSignInClose" title="Close this Window" class="SignInCloseLink" href="javascript:void(0);">Close</a></p>
+ <p>
+ <small>
+ <a id="ctl00_hlForgot" title="Forgot your username or password?" href="../login/password.aspx">Forgot your username or password?</a></small></p>
+
+ </div>
+
+
+ </div>
+
+
+
+
+ </div>
+
+ <div class="NavContainer span-24 last">
+ <nav id="Navigation">
+
+ <ul class="Menu">
+ <li>
+ <a id="ctl00_hlNavLearn" accesskey="1" title="Learn" href="../guide/">Learn ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavGeocaching101" accesskey="i" title="Geocaching 101" href="../guide/">Geocaching 101</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeocaching2Minutes" title="Geocaching in 2 Minutes" href="../videos/#cat=cat:newbies&vid=-4VFeYZTTYs">Geocaching in 2 Minutes</a></li>
+ </ul>
+ </li>
+ <li id="ctl00_liNavJoin">
+ <a id="ctl00_hlNavJoin" accesskey="2" title="Join" href="../membership/register.aspx?type=basic">Join</a></li>
+
+ <li>
+ <a id="ctl00_hlNavPlay" accesskey="3" title="Play" href="./">Play ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavHide" accesskey="d" title="Hide & Seek a Cache" href="./">Hide & Seek a Cache</a></li>
+ <li>
+ </li>
+ <li><a id="ctl00_hlSubNavMap" accesskey="/" title="View Geocache Map" href="../map/">View Geocache Map</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTrackables" accesskey="e" title="Find Trackables" href="../track/">Find Trackables</a></li>
+ <li>
+ <a id="ctl00_hlSubNavHelpCenter" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavCommunity" accesskey="6" title="Community" href="../forums/">Community ▼</a>
+ <ul class="SubMenu">
+
+ <li>
+ <a id="ctl00_hlSubNavTellaFriend" accesskey="-" title="Tell a Friend" href="../account/SendReferral.aspx">Tell a Friend</a></li>
+
+ <li><a id="ctl00_hlSubNavVolunteers" accesskey="+" title="Volunteers" href="../volunteers/">Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavLocal" accesskey="z" title="Local Organizations" href="../organizations/">Local Organizations</a></li>
+ <li>
+ <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBlog" accesskey="b" title="Blog" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEvents" accesskey="v" title="Events" href="../calendar/">Events</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavShop" accesskey="4" title="Shop" href="http://shop.geocaching.com/">Shop ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavShop" accesskey="j" title="Shop Geocaching" rel="external" href="http://shop.geocaching.com/">Shop Geocaching</a></li>
+ <li>
+ <a id="ctl00_hlSubNavIntlRetailers" title="International Retailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGPSReviews" accesskey="w" title="GPS Reviews" href="/reviews/gps">GPS Reviews</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGPSGuide" accesskey="k" title="Guide to Buying a GPS Device" href="../about/buying.aspx">Guide to Buying a GPS Device</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavPartnering" accesskey="5" title="Partnering" href="../travel/">Partnering ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavTravel" title="Travel and GeoTourism" href="../travel/">Travel and GeoTourism</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBrandedPromotions" title="Branded Promotions" href="../brandedpromotions/">Branded Promotions</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEducation" title="Geocaching and Education" href="../education/">Geocaching and Education</a></li>
+ <li>
+ <a id="ctl00_hlSubNavAdvertisingWithUs" title="Advertising with Us" href="../about/advertising.aspx">Advertising with Us</a></li>
+ <li>
+ <a id="ctl00_hlSubNavAPIProgram" title="API Program" href="../live/apidevelopers/">API Program</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavVideos" accesskey="7" title="Videos" href="../videos/">Videos</a></li>
+ <li>
+ <a id="ctl00_hlNavFollowUs" title="Follow Us" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts">Follow Us ▼</a>
+ <ul class="SubMenu NavSocialMedia">
+ <li>
+ <a id="ctl00_hlSubNavFacebook" title="Facebook" class="SubNavFacebook" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts">Facebook</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTwitter" title="Twitter" class="SubNavTwitter" href="http://twitter.com/GoGeocaching">Twitter</a></li>
+ <li>
+ <a id="ctl00_hlSubNavFlickr" title="Flickr" class="SubNavFlickr" href="http://www.flickr.com/photos/geocaching_com/">Flickr</a></li>
+ <li>
+ <a id="ctl00_hlSubNavYouTube" title="YouTube" class="SubNavYouTube" href="http://www.youtube.com/user/GoGeocaching">YouTube</a></li>
+ </ul>
+ </li>
+ </ul>
+
+ </nav>
+ <div class="LanguageSelector">
+
+
+<div class="LocaleText">
+
+ <strong>Choose Your Language:</strong>
+
+</div>
+<div class="LocaleList">
+
+ <div class="selected-language">
+
+ <a href="#">English▼</a>
+
+ </div>
+ <ul class="language-list">
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl05$uxLocaleItem','')">Svenska</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl06$uxLocaleItem','')">Español</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl07$uxLocaleItem','')">Italiano</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl08$uxLocaleItem','')">Nederlands</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl09$uxLocaleItem','')">Català</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl10$uxLocaleItem','')">Polski</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl11$uxLocaleItem','')">Eesti</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl12$uxLocaleItem','')">Norsk, Bokmål</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl13$uxLocaleItem','')">한국어</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl14$uxLocaleItem','')">Magyar</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl15$uxLocaleItem','')">Română</a></li>
+
+ </ul>
+
+</div>
+<script type="text/javascript">
+
+ jQuery(document).ready(function () {
+ jQuery(".selected-language a").click(function (e) {
+ e.preventDefault();
+ var $loc = jQuery(this).parent().next();
+ jQuery($loc).show().position({
+ of: $loc.parent(),
+ my: "left top",
+ at: "left bottom",
+ offset: "0 0",
+ collision: "fit fit"
+ });
+ jQuery(this).addClass("Expanded");
+ jQuery(document).click(function () {
+ jQuery(".language-list").fadeOut("fast");
+ jQuery(".selected-language a").removeClass("Expanded");
+ });
+ return false;
+ });
+ });
+</script>
+ </div>
+ </div>
+
+
+ </div>
+
+
+ </header>
+ <section id="Content">
+
+
+ <div class="container">
+
+ <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
+
+ <p>
+ <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
+ </p>
+
+
+ </div>
+
+ <div id="ctl00_divContentMain" class="span-24 last">
+
+
+
+
+ <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
+
+ <p>
+ <a href="#" class="CoordInfoLink">
+ <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC430FM</span>
+ <span class="arrow">▼</span> </a>
+ </p>
+
+</div>
+<div id="dlgClipboard">
+ <input type="text" class="TextFormat" />
+ <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close">
+ x</a>
+</div>
+<script type="text/javascript">
+ $("a.CoordInfoLink").click(function (e) {
+ e.preventDefault();
+
+ $("#dlgClipboard")
+ .show()
+ .position({
+ of: $("a.CoordInfoLink"),
+ my: "right top",
+ at: "right bottom",
+ offset: "0 5"
+ })
+ .find("input")
+ .val('http://coord.info/' + $('.CoordInfoCode').text())
+ .focus()
+ .select();
+
+ $(document).mouseup(function (e) {
+ if ($(e.target).parent("div#dlgClipboard").length == 0) {
+ $(this).unbind(e);
+ $("div#dlgClipboard").hide();
+ }
+ });
+
+ return false;
+ });
+
+
+</script>
+
+ <div class="span-17">
+
+ <div class="span-17 last BottomSpacing" id="cacheDetails">
+ <p class="cacheImage">
+ <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/8.gif" alt="Unknown Cache" title="Unknown Cache" /></a>
+ </p>
+
+ <h2 class="NoBottomSpacing">
+ <span id="ctl00_ContentBody_CacheName">Cache is Unpublished</span></h2>
+ <div class="minorCacheDetails Clear">
+ <div id="ctl00_ContentBody_mcd1">
+ A cache by <a href="http://www.geocaching.com/profile/?guid=f3d7b7c8-8698-4e21-a6ad-24e148f5c6a5&wid=af38aaf9-5386-40bb-92f0-025ebc7700a7&ds=2">The North Star</a></div>
+ <div id="ctl00_ContentBody_mcd2">
+ Hidden:
+ 12/19/2012
+
+ </div>
+ <div>In California, United States</div>
+ </div>
+ </div>
+ <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-3 BottomSpacing">
+
+ Difficulty:
+ <br />
+ Terrain:
+
+ </div>
+
+ <div id="ctl00_ContentBody_diffTerrStars" class="CacheStarImgs span-2">
+
+ <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars4.gif" alt="4 out of 5" /></span>
+ <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars1_5.gif" alt="1.5 out of 5" /></span>
+
+ </div>
+
+ <div id="ctl00_ContentBody_size" class="CacheSize span-9">
+
+ <p style="text-align: center;">
+ Size: <span class="minorCacheDetails"><img src="/images/icons/container/micro.gif" alt="Size: micro" title="Size: micro" /> <small>(micro)</small></span></p>
+
+ </div>
+
+
+
+ <div class="span-3 right last">
+
+
+
+ </div>
+
+
+ <div id="lus_container" class="lus-container Clear">
+ <div class="lus-header">
+ <span>
+ Join now to view geocache location details. It's free!
+ </span>
+ <span class="lus-signup">
+ <a id="ctl00_ContentBody_locdSignUpLink" title="Sign up" href="/membership/register.aspx?type=basic">Sign up</a><a id="hlFBLogin" title="Log in with Facebook" class="btnFacebookLogin" href="/api/beginfacebook"><span id="ctl00_ContentBody_locFBLogin">Login</span></a>
+ </span>
+ </div>
+ <div style="position: relative;height:257px;">
+ <div class="lus-video">
+ <div class="lus-textblock">
+ <div class="play-control AlignCenter"><a id="ctl00_ContentBody_hlPlayArrow" title="Play Video">▶</a></div>
+ <h4>
+ Watch
+ </h4>
+ How Geocaching Works
+ </div>
+ </div>
+ <div class="lus-image">
+ <img src="/images/seek/locdp_cityscape.jpg" width="380" height="257" />
+ </div>
+ </div>
+ <div class="lus-footer">
+ <span class="AlignRight">
+ <span>Looking for a different adventure?</span>
+ </span>
+ <span class="lus-findacache NoWrap">
+ <input type="submit" name="ctl00$ContentBody$findacache" value="Find a Cache Near Me" id="findacache" title="Find a Cache Near Me" />
+ </span>
+ </div>
+ </div>
+ <script type="text/javascript">
+
+ $("#lus_container")
+ .on("click", "div.lus-video", function () {
+ var $this = $(this),
+ h = $this.height(),
+ w = $this.width();
+
+ $("div.lus-image").hide('slide', { direction: 'right' }, 500, function () {
+ var vhtml = ["<iframe width=\"" + w + "\" height=\"" + h + "\" src=\"http://www.youtube.com/embed/-4VFeYZTTYs?rel=0&autoplay=1\" frameborder=\"0\" allowfullscreen></iframe>"].join('');
+ $this.replaceWith(vhtml);
+ });
+ return false;
+ });
+
+ $("#findacache").click(function (e) {
+ e.preventDefault();
+ $("#txtFindCache").text("Searching...");
+
+ navigator.geolocation.getCurrentPosition(
+ function (position) { // Browser success
+ $(window.location).attr('href', '/seek/nearest.aspx?origin_lat=' + position.coords.latitude + '&origin_long=' + position.coords.longitude + '&dist=100');
+ }, function (error) { // Browser failure, fallback to geocode.
+ $.ajax({
+ url: '/api/geocode?cmd=whoami',
+ dataType: 'json',
+ async: false,
+ success: function (response) {
+ if (response.status == 'success') { // Geocode success
+ $(window.location).attr('href', '/seek/nearest.aspx?origin_lat=' + response.data.lat + '&origin_long=' + response.data.lng + '&dist=100');
+ } else { // Total failure, just go to the search page.
+ $(window.location).attr('href', '/seek/nearest.aspx');
+ }
+ }
+ });
+ },
+ {
+ timeout: 3000 // Wait on the browser for a max of 3 seconds.
+ });
+ return false;
+ });
+
+ // Geolocation emulator
+ (function (geolocation) {
+
+ if (geolocation) return;
+
+ var cache;
+
+ geolocation = window.navigator.geolocation = {};
+ geolocation.getCurrentPosition = function (callback) {
+
+ if (cache) callback(cache);
+
+ $.getScript('//www.google.com/jsapi', function () {
+
+ cache = {
+ coords: {
+ "latitude": google.loader.ClientLocation.latitude,
+ "longitude": google.loader.ClientLocation.longitude
+ }
+ };
+
+ callback(cache);
+ });
+
+ };
+
+ geolocation.watchPosition = geolocation.getCurrentPosition;
+ })(navigator.geolocation);
+
+
+ </script>
+
+ <p class="Clear">
+ </p>
+
+
+
+
+
+
+ <fieldset class="DisclaimerWidget">
+ <legend class="warning">
+ Please note
+ </legend>
+ <p class="NoBottomSpacing">
+ Use of geocaching.com services is subject to the terms and conditions <a href="/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>.
+ </p>
+ </fieldset>
+
+
+ <div class="UserSuppliedContent">
+
+ <span id="ctl00_ContentBody_ShortDescription">
+</span>
+
+ </div>
+
+ <br />
+ <div class="UserSuppliedContent">
+
+ <span id="ctl00_ContentBody_LongDescription"><div class="Section1">
+<p><span style="font-size:10.0pt;font-family:Verdana;mso-bidi-font-family:Arial;color:red;">The cache is not at the posted coordinates but is less than 2 miles away</span></p>
+<p><span style="font-size:10.0pt;font-family:Verdana;mso-bidi-font-family:Arial;color:#333333;">I obtained a Geocache waypoint (GC#) on 02/12/12 for a cache that was not published. Find the name of the unpublished cache and you will find the coordinates for this cache.<br />
+<br />
+The waypoint starts with GC3C and contains 2 additional letters and 1 additional number. Per GC.com Base 31 implementation, the letters ILOSU (US OIL or LOUIS) are not used.<br />
+<br />
+I’m not sure if this is a bug or a feature of <b>Recently Viewed Caches</b>, so it’s entirely possible that this puzzle will be unsolvable or not as easily solved in the future. So solve it and grab it while you can!<br />
+<br />
+Thanks to <a href="http://www.geocaching.com/profile/?u=Chrysalides" target="_blank" rel="nofollow">Chrysalides</a> for planting the seed ;)<br />
+<br />
+There is room for very small trade and signature items. Don't forget to bring your pen.<br />
+<br />
+Enjoy!<br />
+<br />
+You can validate your puzzle solution with <a href="http://certitude.comxa.com/certitude.php?wp=GC430FM">certitude</a> or see <a href="http://certitude.comxa.com/certified.php?wp=GC430FM">who solved</a> this puzzle.<br />
+<br />
+Congratulations to <a href="http://www.geocaching.com/profile/?u=TeamOttlet" target="_blank" rel="nofollow">TeamOttlet</a> on FTS and FTF.</span></p>
+</div></span>
+
+ </div>
+
+ <p>
+
+
+ </p>
+ <p id="ctl00_ContentBody_hints">
+ <strong>
+ Additional Hints</strong>
+ (<a id="ctl00_ContentBody_lnkDH" onclick="dht(this);return false;" title="Decrypt" href="#">Decrypt</a>)</p>
+ <div id="div_hint" class="span-8 WrapFix">
+ Qvq lbh xabj gung lbh pna svaq n yvfg bs <b>Erpragyl Ivrjrq Pnpurf</b> haqre <b>Lbhe Cebsvyr</b>? “Ivrj Nyy” gb frr gur ynfg 50 pnpurf gung lbh unir ivrjrq…</div>
+ <div id='dk' style="display: block;" class="span-9 last">
+ <span id="ctl00_ContentBody_EncryptionKey" class="right"><div class="DecryptionKeyWidget"> <p class="WidgetHeader">Decryption Key</p> <p class="WidgetBody">A|B|C|D|E|F|G|H|I|J|K|L|M<br /> -------------------------<br /> N|O|P|Q|R|S|T|U|V|W|X|Y|Z</p> <p class="WidgetFooter">(letter above equals below, and vice versa)</p></div></span>
+ </div>
+ <div class="Clear">
+ </div>
+
+ </div>
+
+
+ <div class="span-6 prepend-1 last">
+
+
+<div class="CacheDetailNavigationWidget NoPrint">
+
+ <h3 class="WidgetHeader">
+ Navigation
+ </h3>
+ <div class="WidgetBody">
+
+ <ul class="CacheDetailsNavLinks">
+ <li><a href="https://www.geocaching.com/login/?RESET=Y&redir=%2fseek%2flog.aspx%3fID%3d3372822" class="lnk"><img src="/images/icons/16/write_log_locked.png" /> <span>Log in to log your visit</span></a></li>
+<li><a href="https://www.geocaching.com/login/?RESET=Y&redir=%2fmy%2fwatchlist.aspx%3fw%3d3372822" class="lnk"><img src="/images/icons/16/watch_locked.png" /> <span>Log in to watch this listing</span></a></li>
+
+ </ul>
+
+ </div>
+
+
+</div>
+
+
+
+
+
+
+
+ <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing">
+
+ <h3 class="WidgetHeader">
+ Attributes</h3>
+ <div class="WidgetBody">
+ <img src="/images/attributes/available-yes.gif" alt="available 24-7" title="available 24-7" width="30" height="30" /> <img src="/images/attributes/stealth-yes.gif" alt="stealth required" title="stealth required" width="30" height="30" /> <img src="/images/attributes/bicycles-yes.gif" alt="bikes allowed" title="bikes allowed" width="30" height="30" /> <img src="/images/attributes/parkngrab-yes.gif" alt="park and grab" title="park and grab" width="30" height="30" /> <img src="/images/attributes/onehour-yes.gif" alt="takes less than 1 hour" title="takes less than 1 hour" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p>
+ </div>
+
+ </div>
+
+
+ <div id="ctl00_ContentBody_uxBanManWidget" class="CacheDetailPageAds clear">
+
+ <div id="ctl00_ContentBody_divContentSide">
+
+ <p class="NoBottomSpacing">
+ <span id="ctl00_ContentBody_ADModules_09"><iframe type="iframe" src="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Get&SiteID=1&X='1654495648c94c4b9d15c51552c5710a'" width="120" height="240" Marginwidth="0" Marginheight="0" Hspace="0" Vspace="0" Frameborder="0" Scrolling="no" style="width:120px;Height:240px;"><a href="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Click&;Mode=HTML&SiteID=1" target="_blank"><img src="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Get&Mode=HTML&SiteID=1" width="120" height="240" border="0" alt="" /></a></iframe></span>
+ </p>
+ <p class="AlignCenter">
+ <small><a href="../about/advertising.aspx" id="ctl00_ContentBody_advertisingWithUs" title="Advertising with Us">Advertising with Us</a></small></p>
+
+ </div>
+
+</div>
+
+
+
+ <div class="GoogleAds AlignCenter BottomSpacing">
+ </div>
+ <div class="clear">
+ </div>
+
+ <span id="ctl00_ContentBody_lnkTravelBugs"></span>
+
+
+<div class="CacheDetailNavigationWidget">
+
+ <h3 class="WidgetHeader">
+ <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span>
+ </h3>
+ <div class="WidgetBody">
+
+
+ <div id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItems">
+
+ <p class="NoBottomSpacing"><span id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItemsLabel">There are no Trackables in this cache.</span></p>
+
+</div>
+ <div class="TopSpacing">
+
+ <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory" href="../track/search.aspx?wid=af38aaf9-5386-40bb-92f0-025ebc7700a7">View past Trackables</a></p>
+ <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="../track/default.aspx">What are Trackable Items?</a></p>
+ </div>
+
+
+ </div>
+
+
+</div>
+
+
+<div class="CacheDetailNavigationWidget">
+
+ <h3 class="WidgetHeader">Bookmark Lists</h3>
+ <div class="WidgetBody">
+
+
+ <ul>
+
+ <li style='padding: .5em;' class=''>
+ <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=9fd39fb8-9502-47b4-ae08-86ce236fc661">
+ fmoraes' solved but far</a><br />
+ <small><em>
+ by
+ <a href="http://www.geocaching.com/profile/?guid=440cf61b-dcf3-4220-a877-ce312f103921">
+ fmoraes</a> </em></small>
+ </li>
+
+ </ul>
+
+ <p class="NoBottomSpacing">
+ <a href="/bookmarks/default.aspx?guid=af38aaf9-5386-40bb-92f0-025ebc7700a7&WptTypeID=8" title="View all bookmark lists...">View all bookmark lists...</a>
+ </p>
+
+ </div>
+
+
+</div>
+
+
+
+
+
+ </div>
+
+
+ <div id="ctl00_ContentBody_bottomSection" class="span-24 last">
+
+ <p>
+
+ <br />
+
+
+ </p>
+
+
+
+ <p class="NoPrint">
+ <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span>
+ <br />
+ <span id="ctl00_ContentBody_FindText"></span>
+ </p>
+ <ul class="NoPrint">
+ <li>
+ ...other caches
+ <a id="ctl00_ContentBody_uxFindLinksHiddenByThisUser" href="/seek/nearest.aspx?u=The+North+Star">hidden</a>
+ or
+ <a id="ctl00_ContentBody_uxFindLinksFoundByThisUser" href="/seek/nearest.aspx?ul=The+North+Star">found</a>
+ by this user
+ </li>
+
+
+ <li>
+ ...nearby <a id="ctl00_ContentBody_uxFindLinksHotels" href="/reviews/hotels-in-Milpitas,CA,US">Hotels</a>
+ </li>
+ </ul>
+ <p class="NoPrint">
+
+ </p>
+ <span class="NoPrint">
+
+ </span>
+ <p class="NoPrint">
+
+ </p>
+
+ <div class="InformationWidget Clear">
+ <h3>
+ 7 Logged Visits</h3>
+ <div class="EncryptDecrypt">
+ <a href="#" class="decrypt-link">
+ Decrypt
+ </a>
+ </div>
+ <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 4 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 2 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 1 </p></span>
+ <p class="HalfLeft">
+ <a id="ctl00_ContentBody_uxLogbookLink" href="cache_logbook.aspx?guid=af38aaf9-5386-40bb-92f0-025ebc7700a7">View Logbook</a>
+ </p>
+ <p class="NoBottomSpacing AlignRight">
+ <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links.
+ </p>
+ </div>
+
+ <div id="cache_logs_container">
+ <table id="cache_logs_table" class="LogsTable NoBottomSpacing">
+ <tbody>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="AlignCenter">
+ <div id="pnlLazyLoad" style="display: none;">
+ <img src="/images/loading2.gif" class="StatusIcon" alt="Loading" />
+ Loading Cache Logs...
+ </div>
+ <div id="pnlButtonLoad" style="display: none;">
+ <a class="MobileButton">
+ Load More Logs...</a>
+ </div>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+ <p>
+ <small>
+ Current Time: <time datetime="2012-12-21T10:49:48Z">12/21/2012 10:49:48 AM (UTC-08:00) Pacific Time (US & Canada) (6:49 PM GMT)</time><br/>Last Updated: <time class="timeago" datetime="2012-12-21T11:06:00Z">2012-12-21T11:06:00Z</time> on 12/21/2012 3:06:00 AM (UTC-08:00) Pacific Time (US & Canada) (11:06 AM GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum
+ </small>
+ </p>
+
+
+ </div>
+ <script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl">
+ <tr class="log-row" data-encoded="${IsEncoded}" >
+ <td>
+ <div class="FloatLeft LogDisplayLeft" >
+ <p class="logOwnerProfileName">
+ <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong></p>
+ <p class="logOwnerBadge">
+ <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle}
+ </p>
+ <p class="logOwnerAvatar">
+ <a href="/profile/?guid=${AccountGuid}">
+ {{if includeAvatars && AvatarImage}}
+ <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}">
+ {{else includeAvatars }}
+ <img width="48" height="48" src="/images/default_avatar.jpg">
+ {{/if}}
+ </a></p>
+ <p class="logOwnerStats">
+
+ {{if GeocacheFindCount > 0 }}
+ <img title="Caches Found" src="/images/icons/icon_smile.png"> ${GeocacheFindCount}
+ {{/if}}
+
+ </p>
+ </div>
+ <div class="FloatLeft LogDisplayRight">
+ <div class="HalfLeft LogType">
+ <strong>
+ <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong></div>
+ <div class="HalfRight AlignRight">
+ <span class="minorDetails LogDate">${Visited}</span></div>
+ <div class="Clear LogContent">
+ {{if LatLonString.length > 0}}
+ <strong>${LatLonString}</strong>
+ {{/if}}
+ <p class="LogText">{{html LogText}}</p>
+ {{if Images.length > 0}}
+ <table cellspacing="0" cellpadding="3" class="LogImagesTable">
+ {{tmpl(Images) "tmplCacheLogImages"}}
+ </table>
+ {{/if}}
+
+ <div class="AlignRight">
+ <small><a title="View Log" href="log.aspx?LUID=${LogGuid}" target="_blank">
+ {{if (userInfo.ID==AccountID)}}
+ View / Edit Log / Images
+ {{else}}
+ View Log
+ {{/if}}
+ </a></small>
+ {{if (userInfo.ID==AccountID)}}
+ <small><a title="Upload Image" href="upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small>
+ {{/if}}
+ </div>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </script>
+ <script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl">
+ <tr>
+ <td>
+ <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}">
+ <img title="Photo" alt="Photo" src="/images/icons/16/photo.png">
+ <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span>
+ </a>
+ </td>
+ </tr>
+ </script>
+ <script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl">
+ <span class="LogImgTitle"> ${ $('<div />').text($('<div />').text($('<div />').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink">
+
+ <a target="_blank" href="log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a>
+
+ <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span>
+
+ {{if (Descr && Descr.length > 0) }}
+ <br /><p class="LogImgDescription">${ $('<div />').text($('<div />').text($('<div />').html($item.data.Descr).text()).html()).html() }</p>
+ {{/if}}
+ </script>
+ <script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl">
+ <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}">
+ <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4>
+ <dl>
+ <dt>Original:</dt>
+ <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd>
+ </dl>
+ <dl class="ccu-parse">
+ <dt>Change To:</dt>
+ <dd>
+ <input type="text" max="40" size="35" class="cc-parse-text">
+ <button class="ccu-button ccu-parse">Submit</button>
+ </dd>
+ </dl>
+ <dl class="ccu-parseverify" style="display:none;">
+ <dt>Change To:</dt>
+ <dd>
+ <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span>
+
+ <button class="ccu-button ccu-parseverify-accept">Accept</button> <button class="ccu-button ccu-parseverify-cancel">Cancel</button>
+ </dd>
+ </dl>
+ </div>
+ <div class="Clear"></div>
+
+ </script>
+
+ <script type="text/javascript">
+ <!--
+ var dh, lat, lng, guid;
+
+ dh = 'false';
+
+ lat=null;lng=null;guid=null;
+
+
+ function s2gps(guid) {
+ var w = window.open('sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no');
+ w.focus();
+ }
+
+ function s2phone(wpid) {
+ window.location.href='sendtophone.aspx?gc=' + wpid;
+ }
+
+ function pl(lc) {
+ document.location.href='cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n');
+ }
+ function setNotification(id) {
+ //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'});
+ //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'});
+ }
+ function cmo(id) {
+ //new Effect.Fade(id);
+ Cookie.set('sn', true);
+ }
+ function pp(img) {
+ var w = window.open(img);
+ w.focus();
+ }
+
+ //-->
+ </script>
+ <script language="javascript" type="text/javascript">
+ var map, bounds;
+ var canUpdateFavoriteStatus = true;
+ var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false;
+ var logInitialLoaded = false;
+ var $tfoot = $("#cache_logs_table").find("tfoot");
+ var currentPageIdx = 1, totalPages = 1, pageSize = 10;
+ var isBusy = false;
+
+ var locString = {
+ decrypt: 'Decrypt',
+ encrypt: 'Encrypt'
+ };
+
+ $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle");
+ $("#tmpl_CacheLogImages").template("tmplCacheLogImages");
+ $("#tmpl_CacheLogRow").template("tmplCacheLogRow");
+
+ $(".EncryptDecrypt")
+ .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} })
+ .click(function (e) {
+ e.preventDefault();
+ $("tr.log-row").each(function (i, obj) {
+ var $obj = $(obj);
+ if ($obj.data("encoded") == true) {
+ var lt = $obj.find("p.LogText");
+ //var ltDecoded = $('<div />').html(lt.html()).text();
+ lt.html(convertROTStringWithBrackets(lt.html()));
+ }
+ });
+
+ decryptLogs = !decryptLogs;
+
+ $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
+
+ return false;
+ });
+
+ function appendNewLogs(obj) {
+
+ totalPages = obj.pageInfo.totalPages;
+
+ var $newBody = $(document.createElement("TBODY"));
+
+ $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody);
+
+ $newBody.find("a.tb_images").each(function()
+ {
+ var $this = $(this);
+ $this.fancybox({
+ 'type': 'image',
+ 'titlePosition': 'inside',
+ 'padding': 10,
+ titleFormat: function() { return $this.data('title'); }
+ });
+ });
+
+ $("#cache_logs_table")
+ .append($newBody.children());
+
+ currentPageIdx = obj.pageInfo.idx + 1;
+ pageSize = obj.pageInfo.size;
+ }
+
+ function callLogLoad(hideFooter) {
+ $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs },
+ function (response) {
+ if (response.status == "success") {
+ appendNewLogs(response);
+ if( hideFooter || (totalPages < currentPageIdx) ) {
+ $tfoot.hide();
+ }
+ } else if (response.status == "error" && response.value == "1") {
+ // reload the page since the data had expired.
+ window.location.reload();
+ }
+ isBusy = false;
+ });
+ }
+
+ $("#add_to_favorites").click(function () {
+
+ if (canUpdateFavoriteStatus) {
+ canUpdateFavoriteStatus = false;
+
+ var fv = parseInt($(".favorite-value").text());
+ fv++;
+ $(".favorite-value").text(fv);
+
+ var fr = parseInt($(".favorite-rank").text());
+ fr--;
+ $(".favorite-rank").text(fr);
+
+ $("#pnlNonfavoriteCache").fadeOut("fast", function () {
+ $("#pnlFavoriteCache").fadeIn("fast");
+ });
+
+ $.ajax({
+ type: "POST",
+ cache: false,
+ url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true',
+ success: function () {
+ canUpdateFavoriteStatus = true;
+ gotScore = false;
+ showFavoriteScore();
+ }
+ });
+
+ return false;
+ }
+ });
+
+ $("#remove_from_favorites").click(function () {
+
+ if (canUpdateFavoriteStatus) {
+ canUpdateFavoriteStatus = false;
+
+ var fv = parseInt($(".favorite-value").text());
+ fv--;
+ $(".favorite-value").text(fv);
+
+ var fr = parseInt($(".favorite-rank").text());
+ fr++;
+ $(".favorite-rank").text(fr);
+
+ $("#pnlFavoriteCache").fadeOut("fast", function () {
+ $("#pnlNonfavoriteCache").fadeIn("fast");
+ });
+
+ $.ajax({
+ type: "POST",
+ cache: false,
+ url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false',
+ success: function () {
+ canUpdateFavoriteStatus = true;
+ gotScore = false;
+ showFavoriteScore();
+ }
+ });
+
+ return false;
+ }
+ });
+
+ $(function () {
+
+ // CSP Section
+ if ($("#cspMessage").length) {
+
+ var editLink = $('a[href*="report.aspx"]').attr('href');
+
+ $("#cspMessage").prepend('<P>Please take a moment to check the listing and ensure it is ready to enable. Clicking "Submit for Review" will enable your cache page.</P>');
+ $("#cspMessage").prepend('<P>Once it is enabled, you will receive a confirmation email that it was successfully submitted. It is peak season for cache placement. Your volunteer reviewer will strive to begin the review process within the next 7 days.</P>');
+ $("#cspMessage").prepend('<P>Your cache page has not been reviewed yet. It will not appear in the review queue until you enable it.</P>');
+
+ $("#cspGoBack").click(function (e) {
+ e.preventDefault();
+ window.location = editLink;
+ return false;
+ });
+
+ $("#cspSubmit").click(function (e) {
+ e.preventDefault();
+ $.pageMethod("EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) {
+ var r = JSON.parse(r.d);
+ if (r.success == true) {
+ window.location = '/seek/cache_details.aspx?guid=' + r.guid;
+ } else {
+ alert("There was an error enabling your cache.");
+ }
+ });
+ return false;
+ });
+
+ $("#cspConfirm").change(function() {
+ if ($("#cspConfirm").is(":checked")) {
+ $("#cspSubmit").removeAttr('disabled');
+ $("#cspGoBack").attr('disabled', true);
+ } else {
+ $("#cspSubmit").attr('disabled', true);
+ $("#cspGoBack").removeAttr('disabled');
+ }
+ });
+ }
+
+
+ //override coords
+ if (typeof(userDefinedCoords) != "undefined") {
+ if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) {
+ mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
+ $("#uxLatLon")
+ .data("isOverridden", true)
+ .addClass("myLatLon");
+ } else if (userDefinedCoords.status == "success") {
+ mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
+ } else {
+ $("#uxLatLonLink").contents().unwrap();
+ }
+ } else {
+ $("#uxLatLonLink").contents().unwrap();
+ }
+
+
+ var cacheNoteText = {
+ DefaultText: 'Click to enter a note',
+ ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.',
+ SavingText: 'Please wait, saving your note...'
+ };
+
+
+
+ $("time.timeago").timeago();
+
+ $(".button").button();
+
+ var sn = Cookie.get('sn');
+
+ if ($('#trNotPM').length > 0) {
+ $('#trNotPM').toggle(!sn);
+ }
+
+ $("#cache_note").editInPlace({
+ callback: function (unused, enteredText) {
+ var me = $(this);
+
+ var et = $.trim(enteredText);
+ if (et.length > 500)
+ et = et.substr(0, 500);
+
+ $.pageMethod("SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) {
+ var r = JSON.parse(r.d);
+ if (r.success == true) {
+ if ($.trim(r.note) == "") {
+ $("#cache_note").text(cacheNoteText.DefaultText);
+ } else {
+ $("#cache_note").text(r.note);
+ }
+
+ me.effect('highlight', { color: '#ffb84c' }, 'slow');
+ } else {
+ alert(cacheNoteText.ErrorInSaving);
+ $("#cache_note").text(cacheNoteText.DefaultText);
+ }
+
+ });
+
+ return cacheNoteText.SavingText;
+ }
+ , default_text: cacheNoteText.DefaultText
+ , field_type: "textarea"
+ , textarea_rows: "7"
+ , textarea_cols: "65"
+ , show_buttons: true
+ , bg_over: "#FDEBBB"
+ //, callback_skip_dom_reset: true
+
+ });
+
+ $("#lnk_slippyMap").click(function(e) {
+ e.preventDefault();
+ loadDynamicMap();
+ return false;
+ });
+
+ $(".inplace_field").live("focus", function () {
+ if ($(this).data("created") == null) {
+ $(this).data("created", true)
+ $(this).countable({
+ maxLength: 500
+ });
+ }
+ });
+
+ $("#pcn_help").tipTip({ activation: 'hover', content: 'Enter your own notes here. No other user will be able to access them.' });
+
+ $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
+
+ if ($("#cache_logs_container").length > 0) {
+
+ appendNewLogs(initalLogs);
+
+ if (DetectMobileQuick()) {
+ $("#pnlButtonLoad")
+ .show()
+ .find("a.MobileButton")
+ .click(function (e) {
+ e.preventDefault();
+ callLogLoad(false);
+ return false;
+ })
+ .button();
+ if(!DetectTierTablet()){
+ $("a.MobileButton").addClass("Phone");
+ }
+ } else {
+ $("#pnlLazyLoad").show();
+
+ $(window).endlessScroll({
+ fireOnce: true,
+ fireDelay: 500,
+ bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50,
+ ceaseFire: function(){
+ // stop the scrolling if the last page is reached.
+ return (isLoggedIn == false) || (totalPages < currentPageIdx);
+ },
+ callback: function() {
+ if (!isBusy) {
+
+ isBusy = true;
+ $tfoot.show();
+ callLogLoad(true);
+ }
+ }
+ });
+ }
+ }
+
+ if (!isLoggedIn) {
+ $("#cache_logs_table").find("tfoot").hide();
+ }
+
+ if (mapLatLng != null) {
+
+ $("#uxLatLonLink").qtip({
+ suppress:false,
+ content: buildCacheCoordMenu(),
+ position: {
+ my: 'left top',
+ at: 'right top',
+ adjust: {
+ x: 10, y: -10
+ }
+ },
+ show: {
+ ready: false,
+ event: "click",
+ solo: true
+ }, hide: {
+ event: 'unfocus'
+ },
+ style: {
+ tip: {
+ corner: false
+ },
+ classes: 'ui-tooltip-widget'
+ },
+ events: {
+ show: function () {
+ if ($("#uxLatLon").data("isOverridden")) {
+ $("a.ccu-restore").show();
+ } else {
+ $("a.ccu-restore").hide();
+ }
+
+ if (userDefinedCoords.status != "success") {
+ $("div.ccu-update").hide();
+ } else {
+ $("div.ccu-update").show();
+ }
+ }
+ }
+ }).click(function (e) {
+ e.preventDefault();
+ return false;
+ });
+
+ setStaticMaps();
+ //$("#staticMap").lazyload();
+ }
+ });
+
+ function setStaticMaps() {
+
+ var map = new L.Map('map_preview_canvas', {
+ center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
+ zoom: 10,
+ doubleClickZoom: false,
+ dragging: false,
+ touchZoom: false,
+ scrollWheelZoom: false,
+ attributionControl: false
+ })
+ .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }));
+
+
+ var mapLarge = new L.Map('map_canvas', {
+ center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
+ zoom: 14,
+ doubleClickZoom: true,
+ dragging: true,
+ touchZoom: false,
+ scrollWheelZoom: false,
+ zoomControl: true,
+ attributionControl: false
+ })
+ .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }))
+ .addControl(new L.Control.Scale());
+
+ var tileOptions = {
+ tileUrl: "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg",
+ name: "mpqosm",
+ alt: "MapQuest",
+ //attribution: "Tiles Courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='http://developer.mapquest.com/content/osm/mq_logo.png'>, Map and map data © 2012 <a href=\"http://www.openstreetmap.org\" target='_blank'>OpenStreetMap</a> and contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>. ",
+ subdomains: "1234",
+ tileSize: 256,
+ minZoom: 0,
+ maxZoom: 18
+ };
+
+ map.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
+ mapLarge.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
+
+ var pinIcon = L.Icon.extend({
+ iconSize: new L.Point(20, 23),
+ iconAnchor: new L.Point(10,23),
+ shadowUrl: null
+ });
+
+ var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng),
+ {
+ icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
+ title: mapLatLng.name
+ })
+ .on("click", function () {
+ document.getElementById("uxlrgMap").scrollIntoView(true);
+ return false;
+ });
+
+ var mkA2 = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), {
+ icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
+ clickable: false, zIndexOffset:99, title: mapLatLng.name
+ });
+
+ map.addLayer(mkA);
+ mapLarge.addLayer(mkA2);
+
+ $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({
+ overlayShow: false
+ });
+
+
+ if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) {
+ var llBounds = new L.LatLngBounds();
+
+ for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) {
+ var item = cmapAdditionalWaypoints[x],
+ ll = new L.LatLng(item.lat, item.lng),
+ marker = new L.Marker(ll, {
+ icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + item.type + '.png', iconAnchor: new L.Point(10,23)}),
+ title: item.name,
+ clickable:false
+ });
+
+ llBounds.extend(ll);
+ mapLarge.addLayer(marker);
+ }
+ var bz = mapLarge.getBoundsZoom(llBounds);
+
+ mapLarge.setView(new L.LatLng(mapLatLng.lat, mapLatLng.lng), bz);
+ }
+ }
+
+
+
+ function dht() {
+ try {
+ $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html()));
+ var linkText = (($('#ctl00_ContentBody_lnkDH').attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt');
+ $('#ctl00_ContentBody_lnkDH').text(linkText);
+ $('#ctl00_ContentBody_lnkDH').attr('title', linkText);
+ } catch (e) {
+ alert(e);
+ return false;
+ }
+ return false;
+ }
+
+ function buildCacheCoordMenu() {
+ var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng)
+ $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" );
+
+ var $menu = $("<div></div>");
+
+ $( "#tmpl_CacheCoordinateUpdate" ).tmpl( {
+ ll: [mapLatLng.lat, mapLatLng.lng],
+ ll_formatted: mapLatLng.oldLatLngDisplay
+ } ).appendTo( $menu );
+
+ $menu.find("button.ccu-button").button();
+
+ $menu.delegate("button.ccu-parse", "click", function (e) {
+ e.preventDefault();
+ var $this = $(e.target),
+ $parse =$this.closest('dd').find(".cc-parse-text"),
+ parseCoords = $.trim($parse.val());
+
+ if (parseCoords.length == 0) {
+ alert('Please provide valid coordinates.');
+ } else {
+ $.getJSON("/api/geocode", { parse: parseCoords}, function (response) {
+ if (response.status == "success") {
+ var newLatLng = new LatLon(response.data.lat, response.data.lng);
+
+ // update the displayed coords
+ var dist = curLatLng.rhumbDistanceTo(newLatLng);
+ var bearingTo = curLatLng.rhumbBearingTo(newLatLng);
+ var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N";
+
+ var formats = response.data.formats;
+ // all these finds, make me feel dirty
+ $menu
+ .find("span.ccu-parseverify-coords").text(formats.DM).end()
+ .find("dl.ccu-parse").hide().end()
+ .find("dl.ccu-parseverify").show().end()
+ .find("button.ccu-parseverify-accept")
+ .data("utm", '')
+ .data("dm", formats.DM)
+ .data("lat", response.data.lat)
+ .data("lng", response.data.lng)
+ .end();
+ } else {
+ alert("Sorry unable to parse the coordinates you entered.");
+ }
+ });
+ }
+
+ return false;
+ });
+
+ $menu.delegate("button.ccu-parseverify-accept", "click", function (e) {
+ e.preventDefault();
+ var $this = $(this);
+ // update to webmethod
+ $.pageMethod("SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) {
+ var r = JSON.parse(r.d);
+ if (r.status == "success") {
+ window.location.reload();
+ } else {
+ $("#uxLatLonLink").qtip('hide');
+ }
+
+ });
+
+ return false;
+ });
+
+ $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) {
+ e.preventDefault();
+ $menu
+ .find("input.cc-parse-text").val('').end()
+ .find("dl.ccu-parse").show().end()
+ .find("dl.ccu-parseverify").hide().end();
+ return false;
+ });
+
+ $menu.delegate("a.ccu-restore", "click", function (e) {
+ e.preventDefault();
+
+ $.pageMethod("ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) {
+ var r = JSON.parse(r.d);
+ if (r.status == "success") {
+ window.location.reload();
+ }
+ });
+
+ return false;
+ });
+
+ return $menu;
+ }
+
+ GSPK = window.GSPK || {};
+ GSPK.Selector = {};
+ GSPK.Selector.getSelected = function(){
+ var t = null;
+ if ( window.getSelection ){
+ t = window.getSelection();
+ }else if(document.getSelection){
+ t = document.getSelection();
+ }else if(document.selection){
+ t = document.selection.createRange().text;
+ }
+ return t;
+ }
+
+ try { _gaq.push(['_trackEvent', 'Geocaching', 'CacheDetailsMemberType', 'NotSignedIn', null, true]); } catch(err) { }
+ </script>
+
+
+
+ </div>
+
+
+
+
+ </div>
+
+
+ </section>
+
+ <footer>
+
+ <div class="container">
+
+ <div class="span-24 last FooterTop">
+
+
+
+<div class="LocaleText">
+
+ <strong>Choose Your Language:</strong>
+
+</div>
+<div class="LocaleList">
+
+ <div class="selected-language">
+
+ <a href="#">English▼</a>
+
+ </div>
+ <ul class="language-list">
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Svenska</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Español</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Italiano</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Nederlands</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Català</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">Polski</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">Eesti</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">Norsk, Bokmål</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">한국어</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Magyar</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Română</a></li>
+
+ </ul>
+
+</div>
+<script type="text/javascript">
+
+ jQuery(document).ready(function () {
+ jQuery(".selected-language a").click(function (e) {
+ e.preventDefault();
+ var $loc = jQuery(this).parent().next();
+ jQuery($loc).show().position({
+ of: $loc.parent(),
+ my: "left top",
+ at: "left bottom",
+ offset: "0 0",
+ collision: "fit fit"
+ });
+ jQuery(this).addClass("Expanded");
+ jQuery(document).click(function () {
+ jQuery(".language-list").fadeOut("fast");
+ jQuery(".selected-language a").removeClass("Expanded");
+ });
+ return false;
+ });
+ });
+</script>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ About</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterGlossary" title="Glossary of Terms" href="../about/glossary.aspx">Glossary of Terms</a></li>
+ <li>
+ <a id="ctl00_hlFooterBrochures" title="Brochures" href="../tools/#Guide">Brochures</a></li>
+ <li>
+ <a id="ctl00_hlFooterAbout" title="About Groundspeak" href="../about/groundspeak.aspx">About Groundspeak</a></li>
+ <li>
+ <a id="ctl00_hlFooterVolunteers" title="About Our Volunteers" href="../volunteers/">About Our Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlFooterHistory" title="History" href="../about/history.aspx">History</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ Press</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterNews" title="News Articles" href="../press/">News Articles</a></li>
+ <li>
+ <a id="ctl00_hlFooterMediaFAQs" title="Media FAQs" rel="document" href="../articles/Brochures/footer/FAQ_Media.pdf">Media FAQs</a></li>
+ <li>
+ <a id="ctl00_hlFooterMediaInquiries" title="Media Inquiries" rel="external" href="http://support.groundspeak.com/index.php?pg=request&xCategory=11">Media Inquiries</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-5">
+
+ <p class="FooterHeader">
+ <strong>
+ Questions & Suggestions</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterHelpCenterLink" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
+ <li>
+ <a id="ctl00_hlFooterDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlFooterParksPoliceLink" title="Land Management and Law Enforcement" href="../parksandpolice/">Land Management and Law Enforcement</a></li>
+ <li>
+ <a id="ctl00_hlFooterContactUs" title="Contact Us" href="../contact/">Contact Us</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ Resources</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterTools" accesskey="o" title="Tools and Downloads" href="../tools/">Tools and Downloads</a></li>
+ <li>
+ <a id="ctl00_hlFooterAPIProgram" title="API Program" href="../live/">API Program</a></li>
+ <li>
+ <a id="ctl00_hlFooterBenchmarks" title="Find a Benchmark" href="../mark/">Find a Benchmark</a></li>
+ </ul>
+
+ </div>
+ <div class="span-4 append-3 last">
+
+ <p class="FooterHeader">
+ <strong>
+ Follow Us</strong></p>
+ <ul class="FooterLinks FollowUsLinks">
+ <li><a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts"><img id="ctl00_imgFacebook" title="Facebook" src="../images/home/icon_facebook.png" alt="Facebook" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"><img id="ctl00_imgTwitter" title="Twitter" src="../images/twitter/twitter_icon_white_22.png" alt="Twitter" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlFlickr" title=" Flickr" href="http://www.flickr.com/photos/geocaching_com/"><img id="ctl00_imgFlickr" title="Flickr" src="../images/home/icon_flickr.png" alt="Flickr" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"><img id="ctl00_imgYouTube" title="YouTube" src="../images/home/icon_youtube.png" alt="YouTube" style="border-width:0px;" /></a></li>
+ </ul>
+
+ </div>
+
+ <p class="span-24 last FooterBottom">
+ Copyright
+ © 2000-2012
+ <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
+ All Rights Reserved.<br />
+ <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
+ |
+ <a id="ctl00_hlFooterPrivacy" accesskey="x" title="Privacy Policy" href="../about/privacypolicy.aspx">Privacy Policy</a>
+ |
+ <a id="ctl00_hlFooterLogo" accesskey="l" title="Geocaching Logo Usage Guidelines" href="../about/logousage.aspx">Geocaching Logo Usage Guidelines</a>
+ |
+ <a id="ctl00_hlFooterAPI" accesskey="`" title="API License Agreement" href="../live/api_license_agreement.aspx">API License Agreement</a>
+ |
+ <a id="ctl00_HlFooterStatus" accesskey="`" title="Current Service Status" href="http://status.geocaching.com">Service Status</a></p>
+
+ </div>
+
+
+ </footer>
+ <div class="SkipLinks">
+
+ <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
+
+ </div>
+
+
+
+<script type="text/javascript">
+//<![CDATA[
+var Page_ValidationSummaries = new Array(document.getElementById("ctl00_vsSignInWidgetForm"));
+var Page_Validators = new Array(document.getElementById("ctl00_rfvUsername"), document.getElementById("ctl00_rfvPassword"));
+//]]>
+</script>
+
+<script type="text/javascript">
+//<![CDATA[
+var ctl00_vsSignInWidgetForm = document.all ? document.all["ctl00_vsSignInWidgetForm"] : document.getElementById("ctl00_vsSignInWidgetForm");
+ctl00_vsSignInWidgetForm.headertext = "<h4>Please correct the following issues:</h4>";
+ctl00_vsSignInWidgetForm.validationGroup = "SignInForm";
+var ctl00_rfvUsername = document.all ? document.all["ctl00_rfvUsername"] : document.getElementById("ctl00_rfvUsername");
+ctl00_rfvUsername.controltovalidate = "ctl00_tbUsername";
+ctl00_rfvUsername.errormessage = "Username is a required field; please enter a valid username.";
+ctl00_rfvUsername.display = "Dynamic";
+ctl00_rfvUsername.validationGroup = "SignInForm";
+ctl00_rfvUsername.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
+ctl00_rfvUsername.initialvalue = "";
+var ctl00_rfvPassword = document.all ? document.all["ctl00_rfvPassword"] : document.getElementById("ctl00_rfvPassword");
+ctl00_rfvPassword.controltovalidate = "ctl00_tbPassword";
+ctl00_rfvPassword.errormessage = "Password is a required field; please enter a valid password.";
+ctl00_rfvPassword.display = "Dynamic";
+ctl00_rfvPassword.validationGroup = "SignInForm";
+ctl00_rfvPassword.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
+ctl00_rfvPassword.initialvalue = "";
+//]]>
+</script>
+
+
+<script type="text/javascript">
+//<![CDATA[
+var isLoggedIn = false;
+var userDefinedCoords = {"status":"fail","data":{"isUserDefined":false,"oldLatLngDisplay":"N 37° 23.900' W 121° 55.000'"}};
+userInfo = {ID: 0};
+userToken = 'WQZID4ZFAYC6SULYQF74LYDA3S3BDCRFF42MHAMCQ2FV344K2FX57T5PR5HMIIEYY3CGMUR4ZCJLPZTNFNAGW2TB53PY5QWTMDL4AU4IKCSURNTR555XW5UR6GPGTI3L77XLHQYQRCXS6J3O3FRH3WHZ23TV7YTF2XZ3PYA';
+//]]>
+</script>
+<script type="text/javascript">setNotification('ctl00_ContentBody_trNotLoggedIn');</script>
+<script type="text/javascript">
+//<![CDATA[
+initalLogs = {"status":"success", "data": [{"LogID":284766538,"CacheID":3372822,"LogGuid":"73790d15-edbd-4e22-8906-fd78557699b4","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"No idea eventually became one idea that became another idea...which became a lot of work! <img src=\"/images/icons/icon_smile_shock.gif\" border=\"0\" align=\"middle\" /> In fact, I might still be busy-bee-ing my way through the puzzle if I hadn't received a timely offer that was too good to refuse. Turned out I had figured out enough to be getting close but had a loooooong way to go, so I was very grateful for the boost up from skillz I lack. From there, the solution was quickly within reach, and after digging around in my mind for another bit of inspiration, the cache was soon in reach as well. TNLNSL, TFTC!","Created":"12/21/2012","Visited":"12/20/2012","UserName":"thelins","MembershipLevel":3,"AccountID":2999428,"AccountGuid":"01cb03f6-290f-4720-8786-0c5ac17a6cc0","Email":"","AvatarImage":"0ee825d9-bc33-41f4-bf0e-a62bde392303.jpg","GeocacheFindCount":1424,"GeocacheHideCount":14,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":284677706,"CacheID":3372822,"LogGuid":"7c7a396a-337e-4b48-b76b-db5c1c351126","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"21:56. Consecutive Day 3445.<br />Knew what I needed to do right away with this puzzle, as I had been considering how to incorporate this \"feature\" into one of my own puzzles, but I misread the date as 12/12/12, and so my attempt to solve this morning failed. Saw the new info this evening and worked out a trick to make it easier to find the needed info. The cache hint confused me, and it took me a long time to find the cache.<br />{3/1.5m-puz,n,h}<br /><br />This entry was edited by kablooey on Thursday, December 20, 2012 at 2:25:22 PM UTC.","Created":"12/19/2012","Visited":"12/19/2012","UserName":"kablooey","MembershipLevel":1,"AccountID":18898,"AccountGuid":"a3dd3925-32ae-4ab2-9063-b62919d412b7","Email":"","AvatarImage":"906a0d82-5f39-4925-830f-a505f38d15fb.jpg","GeocacheFindCount":14367,"GeocacheHideCount":135,"ChallengesCompleted":13,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":284677102,"CacheID":3372822,"LogGuid":"7bc5e006-4d3a-4b40-9c3d-50dcf348ef56","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"I saw this one this morning as I got ready to go out for my run. I was a little disappointed to see so much description of what was needed, since I knew what to do for once on a puzzle around here. The only clever part of what I did to solve this one was to narrow down the possibilities to essentially what the new extra information says. I underestimated how much time it was going to take to finish up once I got in to work, but it still went by relatively quickly. I don't think there's any way I could have made to be FTF, even though I did solve 8 minutes before TeamOttlet found it. Anyways, I stopped by on my way home, and despite the darkness, it was in the first place I checked, thanks to the certitude hint. Thanks for the puzzle.","Created":"12/19/2012","Visited":"12/19/2012","UserName":"payakoi","MembershipLevel":3,"AccountID":94859,"AccountGuid":"b20a5189-6852-49ba-951f-b3471d3198bf","Email":"","AvatarImage":"","GeocacheFindCount":5344,"GeocacheHideCount":7,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":284659125,"CacheID":3372822,"LogGuid":"819ecce1-91db-48bc-899a-063e12512595","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Write note","LogTypeImage":"4.png","LogText":"Updated the description to include some details about the waypoint.<br /><br />Thank Chrysalides for the US OIL tip <img src=\"/images/icons/icon_smile_approve.gif\" border=\"0\" align=\"middle\" />. kanchan suggested LOUIS <img src=\"/images/icons/icon_smile_big.gif\" border=\"0\" align=\"middle\" />.<font color=\"white\"><br /><br />This entry was edited by The North Star on Thursday, 20 December 2012 at 02:38:37 UTC.</font>","Created":"12/19/2012","Visited":"12/19/2012","UserName":"The North Star","MembershipLevel":3,"AccountID":669462,"AccountGuid":"f3d7b7c8-8698-4e21-a6ad-24e148f5c6a5","Email":"","AvatarImage":"1561481d-e045-481f-9c19-eccb025fcfea.jpg","GeocacheFindCount":1308,"GeocacheHideCount":40,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":284645348,"CacheID":3372822,"LogGuid":"05e00972-1576-4c93-b595-93c095632984","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"FTF at 11:40am<br />I made this one a lot more tedious than it had to be, I ought to have read the description more carefully. I did find a slightly more efficient search method, but still pretty manual. TFTP<font color=\"white\"></font>","Created":"12/19/2012","Visited":"12/19/2012","UserName":"TeamOttlet","MembershipLevel":3,"AccountID":623076,"AccountGuid":"b9f2639c-5ed0-4625-82ed-f7723aad6a24","Email":"","AvatarImage":"b4d5c924-f0b3-4668-866d-0c7eafe6a6ad.jpg","GeocacheFindCount":7971,"GeocacheHideCount":11,"ChallengesCompleted":2,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 5, "totalRows": 7, "rows": 7 } };
+
+document.getElementById('ctl00_vsSignInWidgetForm').dispose = function() {
+ Array.remove(Page_ValidationSummaries, document.getElementById('ctl00_vsSignInWidgetForm'));
+}
+
+var Page_ValidationActive = false;
+if (typeof(ValidatorOnLoad) == "function") {
+ ValidatorOnLoad();
+}
+
+function ValidatorOnSubmit() {
+ if (Page_ValidationActive) {
+ return ValidatorCommonOnSubmit();
+ }
+ else {
+ return true;
+ }
+}
+ WebForm_AutoFocus('btnSignIn');
+document.getElementById('ctl00_rfvUsername').dispose = function() {
+ Array.remove(Page_Validators, document.getElementById('ctl00_rfvUsername'));
+}
+
+document.getElementById('ctl00_rfvPassword').dispose = function() {
+ Array.remove(Page_Validators, document.getElementById('ctl00_rfvPassword'));
+}
+//]]>
+</script>
+</form>
+ <script type="text/javascript">
+ var browserType = {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ };
+
+ $(function () {
+ // Make the menu system play nice with all browsers:
+ $('ul.Menu li').hover(function () {
+ $(this).addClass('hover');
+ $('ul:first', this).css('visibility', 'visible');
+ }, function () {
+ $(this).removeClass('hover');
+ $('ul:first', this).css('visibility', 'hidden');
+ });
+ if (!isiOS()) {
+ // Constructing a Twitter-esque Login:
+ $(".SignInLink").click(function (e) {
+ e.preventDefault();
+ $("#SignInWidget").toggle();
+ $(".ProfileWidget").toggleClass("WidgetOpen");
+ $(this).blur();
+ $("#ctl00_tbUsername").focus();
+ });
+ $(".SignInCloseLink").click(function () {
+ $("#SignInWidget").toggle();
+ $(".ProfileWidget").toggleClass("WidgetOpen");
+ });
+ }
+ $('.SignedInProfileLink').truncate({
+ width: 120,
+ after: '&hellip;',
+ center: false,
+ addclass: false,
+ addtitle: false
+ });
+
+ // Hide the warning message if the user closed it already
+ if ($.cookie('hide_warning') != null) {
+ $(".WarningMessage").hide();
+ } else {
+ $("#warningCloseButton").click(function () {
+ $('.WarningMessage').hide('blind');
+ $.cookie('hide_warning', 'true', { expires: 1 });
+ });
+ }
+
+ function isiOS() {
+ return (
+ (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
+ );
+ }
+ });
+ </script>
+
+
+ <script id="loc_favPointsScoreDesc" type="text/html">
+ Favorites/Premium Logs
+ </script>
+ <script type="text/javascript" language="javascript">
+ <!--
+
+
+
+ var gotScore = false;
+ var favDropDown = $('.favorite-dropdown');
+ var favContainer = $('.favorite-container');
+
+ function showFavoriteScore() {
+ $('#imgFavoriteScore').attr('src', '/images/loading3.gif');
+
+ $('#uxFavoriteScore').parent().fadeTo(200, .001, function () {
+ $.ajax({
+ type: "POST",
+ cache: false,
+ url: '/datastore/favorites.svc/score?u=' + userToken,
+ success: function (scoreResult) {
+ gotScore = true;
+
+ var score = 0;
+
+ if(scoreResult)
+ score = scoreResult;
+
+ if(score > 100)
+ score = 100;
+
+ $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png');
+ var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim();
+ $('#imgFavoriteScore').attr('alt', pieDesc);
+ $('#imgFavoriteScore').attr('title', pieDesc);
+
+ $('#uxFavoriteScore').parent().fadeTo(1000, 1);
+ $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html());
+ }
+ });
+ });
+ }
+
+
+
+ $(document).bind('mouseup', function (e) {
+ var $clicked = $(e.target);
+
+
+ if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) {
+ favDropDown.hide(1, function () {
+ favContainer.addClass('favorite-container');
+ favContainer.removeClass('favorite-container-open');
+ $('#imgFavoriteArrow').attr('src', '/images/arrow-down.png');
+ });
+ }
+ });
+
+ $('#uxFavContainerLink').click(function () {
+ if ($(favDropDown).is(':visible')) {
+ favDropDown.hide(1, function(){
+ favContainer.addClass('favorite-container');
+ favContainer.removeClass('favorite-container-open');
+ $('#imgFavoriteArrow').attr('src', '/images/arrow-down.png');
+ });
+ }
+ else {
+ if (!gotScore) {
+ showFavoriteScore();
+ }
+
+ favContainer.addClass('favorite-container-open');
+ favContainer.removeClass('favorite-container');
+ $('#imgFavoriteArrow').attr('src', '/images/arrow-up.png');
+ favDropDown.show(1);
+ }
+ });
+ // End -->
+ </script>
+
+
+ <script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-2020240-1']);
+ _gaq.push(['_trackPageview']);
+ (function () {
+ var ga = document.createElement('script');
+ ga.src = ('https:' == document.location.protocol ?
+ 'https://ssl' : 'http://www') +
+ '.google-analytics.com/ga.js';
+ ga.setAttribute('async', 'true');
+ document.documentElement.firstChild.appendChild(ga);
+ })();
+ $(function () {
+ $("a.language").click(function (e) {
+ e.preventDefault();
+ window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang"));
+ });
+ });
+ </script>
+
+
+ <!-- Quantcast Tag -->
+ <div id="Quantcast">
+ <script type="text/javascript">
+ var _qevents = _qevents || [];
+
+ (function () {
+ var elem = document.createElement('script');
+
+ elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
+ elem.async = true;
+ elem.type = "text/javascript";
+ var scpt = document.getElementsByTagName('script')[0];
+ scpt.parentNode.insertBefore(elem, scpt);
+ })();
+ </script>
+ <script type="text/javascript">
+ _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
+ </script>
+ <noscript>
+ <div style="display: none;">
+ <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
+ alt="Quantcast" /></div>
+ </noscript>
+ </div>
+ <!-- End Quantcast tag -->
+
+ <!-- Server: WEB03; Build: Web.HotFix_20121211.1 -->
+</body>
+</html>
diff --git a/tests/res/raw/gc431f2_published.html b/tests/res/raw/gc431f2_published.html new file mode 100644 index 0000000..869c0f8 --- /dev/null +++ b/tests/res/raw/gc431f2_published.html @@ -0,0 +1,2248 @@ +
+<!DOCTYPE html>
+<html lang="en" class="no-js">
+<head id="ctl00_Head1"><meta charset="utf-8" />
+ <!--[if IE]><![endif]-->
+ <title>
+ GC431F2 Needle in a Haystack (Unknown Cache) in California, United States created by The North Star
+</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta name="author" content="Groundspeak, Inc." /><meta name="DC.creator" content="Groundspeak, Inc." /><meta name="Copyright" content="Copyright (c) 2000-2012 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2012 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><meta http-equiv="X-UA-Compatible" content="IE=8" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/reset.css" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/typography.css" /><link rel="stylesheet" type="text/css" media="screen,projection" href="../css/blueprint/src/grid.css" />
+ <!--[if lt IE 8]>
+ <link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/ie.css" />
+ <![endif]-->
+ <link id="uxCssMaster" rel="stylesheet" type="text/css" media="screen,projection" href="../css/tlnMasterScreen.css?r=1" /><link id="uxCssMain" rel="stylesheet" type="text/css" media="all" href="../css/tlnMain.css?r=1" /><link rel="Stylesheet" type="text/css" media="all" href="../css/jqueryui1810/jquery-ui-1.8.10.custom.css" /><link rel="stylesheet" type="text/css" media="all" href="/js/jquery_plugins/jquery.jgrowl.css" /><link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" />
+ <script type="text/javascript" src="/js/modernizr-1.7.min.js"></script>
+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.min.js"></script>
+ <script type="text/javascript" src="/js/jquery.truncate.min.js"></script>
+
+
+
+ <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" />
+ <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" />
+ <link href="/js/jquery_plugins/tipTip/tipTip.css" rel="stylesheet" type="text/css" />
+ <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" />
+ <!--[if lte IE 8]>
+ <style type="text/css" media="all">
+ legend{
+ position: absolute;
+ top: -.6em;
+ left: 1em;
+ line-height: 1.3;
+ }
+ fieldset p{
+ margin-top:1em;
+ }
+ img.CacheNoteHelpImg{
+ top:-.2em;
+ }
+ </style>
+ <![endif]-->
+ <style type="text/css" media="screen,projection">
+ #otherSearchOptions li
+ {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ }
+ .ff
+ {
+ font-family: "Andale Mono" , "Courier New" ,Courier,monospace;
+ }
+ .fr
+ {
+ margin-top: 1.5em;
+ float: right;
+ }
+ .fl
+ {
+ float: left;
+ }
+ .clsCell
+ {
+ border: 1px solid #c0cee3;
+ font-size: 80%;
+ background-color: #fff;
+ }
+ .clsResultTitle, .clsResultTitleNoBold
+ {
+ color: #0000de;
+ }
+ .clsResultDescription
+ {
+ color: #333;
+ }
+ .clsURL
+ {
+ color: #999;
+ }
+ a.title:link, a.title:visited, a.title:hover, a.title:active
+ {
+ color: #000;
+ text-decoration: underline;
+ }
+ a.title
+ {
+ text-align: right;
+ font-size: 10px;
+ font-family: arial,sans-serif;
+ padding: 0 1px 0 0;
+ }
+ #mapSizePager a:hover
+ {
+ font-weight: bold;
+ }
+ #mapSizePager ul
+ {
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+ #mapSizePager li
+ {
+ float: left;
+ list-style: none;
+ }
+ #mapSizePager li a
+ {
+ font-family: verdana,sans-serif;
+ font-size: x-small;
+ display: block;
+ margin: 0 2px 0 0;
+ padding: 4px;
+ text-decoration: none;
+ border: solid 1px #c0c0c0;
+ height: 10px;
+ min-width: 10px;
+ cursor: pointer;
+ }
+ #mapPrintingNotes
+ {
+ width: 280px;
+ text-align: left;
+ overflow: auto;
+ }
+ .inplace_field {
+ width:100%;
+ resize: none;
+ }
+ legend.note{
+ background:url('../images/icons/16/user_note.png') no-repeat 0 0;
+ padding-left:18px;
+ }
+ legend.warning{
+ background:url('../images/icons/16/take_note.png') no-repeat 0 0;
+ padding-left:18px;
+ }
+ fieldset.CacheNote{
+ border-color: #e9a24c !important;
+ background-color:#ffffde;
+ position:relative;
+ }
+ .CacheNoteHelpImg{
+ position:relative;
+ cursor:pointer;
+ top:-1em;
+ right:-.75em;
+ float:right;
+ }
+ .InformationWidget h3{
+ margin-bottom:.5em;
+ }
+ .InformationWidget .AlignRight{
+ font-size:.8em;
+ }
+ #tiptip_content{
+ *background-color:#000;
+ box-shadow:none;
+ }
+ .maxed{
+ color:#992a2a;
+ }
+
+
+ span.ccu-parseverify-distance img{
+ text-align:center !important;
+ vertical-align:text-bottom !important;
+ }
+ .edit-cache-coordinates{
+ text-decoration: none;
+ color: #000 !important;
+ background: url(/images/icons/16/edit.png) no-repeat right 0;
+ padding:2px 20px 2px 0px;
+ margin-right:4px;
+ }
+ .ccc-coord{
+ cursor: text;
+ font-family: Courier New, Sans-Serif;
+ }
+ .ccu-update dl {
+ margin-bottom:.25em;
+ }
+ .ccu-update dt{
+ float:left;
+ min-width:90px;
+ }
+ .ccu-update .ui-button-text-only .ui-button-text{
+ padding:.3em .75em;
+ }
+ .ccu-parseverify-coords{
+ font-style:italic;
+ margin-right:.25em;
+ }
+ .ccu-parseverify-accept, .ccu-parseverify-cancel{
+ margin-top:-5px;
+ }
+ .ui-tooltip-widget .ui-tooltip-content{
+ border-width:1px;
+ background-color:#fff;
+ border-color:#c0cee3;
+ color:#594a42;
+ padding:1em;
+ width:420px;
+ }
+ .myLatLon {
+ border-bottom:2px solid #c0cee3;
+ font-style:italic;
+ }
+ .leaflet-control-attribution{
+ padding:3px !important;
+ }
+ .leaflet-control-attribution img{
+ vertical-align:middle;
+ }
+ </style>
+ <link rel="Stylesheet" type="text/css" media="screen" href="/hide/css/CSPScreen.css" />
+ <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/v5/leaflet.css" />
+ <!--[if IE]>
+ <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/v5/leaflet.ie.css" />
+ <![endif]-->
+ <script type="text/javascript" language="javascript" src="/js/leaflet/v5/leaflet.js"></script>
+ <script type="text/javascript" src="/js/jquery.pagemethods.js"></script>
+ <script type="text/javascript" src="/js/geometa.js"></script>
+ <script type="text/javascript">
+ var userToken = null,
+ urlParams = {},
+ mapLatLng = null,
+ cmapAdditionalWaypoints = [],
+ initalLogs = null, totalLogs = 0, includeAvatars = false;
+
+ (function () {
+ var e,
+ d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); },
+ q = window.location.search.substring(1),
+ r = /([^&=]+)=?([^&]*)/g;
+
+ while (e = r.exec(q)) {
+ urlParams[d(e[1])] = d(e[2]);
+ }
+ })();
+ </script>
+<meta name="og:site_name" content="Geocaching.com" property="og:site_name" /><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC431F2&Submit6=Go" property="og:url" /><meta name="og:description" content="Solve the mystery and then use a smartphone or GPS device to navigate to the solution coordinates. Look for a other hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 1.5 and difficulty is 3 (out of 5)." property="og:description" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/8.png" property="og:image" /><meta name="og:title" content="Needle in a Haystack" property="og:title" /><meta name="description" content="Needle in a Haystack (GC431F2) was created by The North Star on 12/21/2012. It's a Other size geocache, with difficulty of 3, terrain of 1.5. It's located in California, United States. The cache is not at the posted coordinates but is less than 2 miles awayCache is Unpublished is a little like looking for a Needle in a Haystack. The “Needle” should be easier to find in this Haystack.Cache is "sign" only." /></head>
+<body background="http://outplacing.com/files/2010/05/needle-in-a-haystack.jpg" class="CacheDetailsPage">
+ <form name="aspnetForm" method="post" action="cache_details.aspx?wp=GC431F2&Submit6=Go" onsubmit="javascript:return WebForm_OnSubmit();" onkeypress="javascript:return WebForm_FireDefaultButton(event, 'ctl00_btnSignIn')" id="aspnetForm">
+<div>
+<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
+<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
+<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="2" />
+<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTc1MjcwNzgxNg8WAh4EQy5JRCgpWVN5c3RlbS5JbnQ2NCwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BzMzNzM3NjUWAmYPZBYGZg9kFgoCBg8WAh4EVGV4dAViPG1ldGEgbmFtZT0iQ29weXJpZ2h0IiBjb250ZW50PSJDb3B5cmlnaHQgKGMpIDIwMDAtMjAxMiBHcm91bmRzcGVhaywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLiIgLz5kAgcPFgIfAQVHPCEtLSBDb3B5cmlnaHQgKGMpIDIwMDAtMjAxMiBHcm91bmRzcGVhaywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAtLT5kAhoPFgIeBGhyZWYFHX4vY3NzL3Rsbk1hc3RlclNjcmVlbi5jc3M/cj0xZAIbDxYCHwIFFX4vY3NzL3Rsbk1haW4uY3NzP3I9MWQCIA8WAh4HVmlzaWJsZWhkAgEPZBYSAgUPFgIfAWRkAgcPFgIfA2cWAgIdDw8WAh4LUG9zdEJhY2tVcmwFbmh0dHBzOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2xvZ2luL2RlZmF1bHQuYXNweD9yZWRpcj0lMmZzZWVrJTJmY2FjaGVfZGV0YWlscy5hc3B4JTNmd3AlM2RHQzQzMUYyJTI2U3VibWl0NiUzZEdvZGQCCA9kFgICBQ8PFgIeC05hdmlnYXRlVXJsBZUBaHR0cHM6Ly93d3cuZ2VvY2FjaGluZy5jb20vbG9naW4vZGVmYXVsdC5hc3B4P1JFU0VUPVkmcmVkaXI9aHR0cCUzYSUyZiUyZnd3dy5nZW9jYWNoaW5nLmNvbSUyZnNlZWslMmZjYWNoZV9kZXRhaWxzLmFzcHglM2Z3cCUzZEdDNDMxRjIlMjZTdWJtaXQ2JTNkR29kZAIMDxYCHwNnZAIsD2QWBAIDDxYCHwEFB0VuZ2xpc2hkAgUPFgIeC18hSXRlbUNvdW50AhAWIGYPZBYCAgEPDxYIHg9Db21tYW5kQXJndW1lbnQFBWVuLVVTHgtDb21tYW5kTmFtZQUNU2V0VGVtcExvY2FsZR8BBQdFbmdsaXNoHhBDYXVzZXNWYWxpZGF0aW9uaGRkAgEPZBYCAgEPDxYIHwcFBWRlLURFHwgFDVNldFRlbXBMb2NhbGUfAQUHRGV1dHNjaB8JaGRkAgIPZBYCAgEPDxYIHwcFBWZyLUZSHwgFDVNldFRlbXBMb2NhbGUfAQUJRnJhbsOnYWlzHwloZGQCAw9kFgICAQ8PFggfBwUFcHQtUFQfCAUNU2V0VGVtcExvY2FsZR8BBQpQb3J0dWd1w6pzHwloZGQCBA9kFgICAQ8PFggfBwUFY3MtQ1ofCAUNU2V0VGVtcExvY2FsZR8BBQnEjGXFoXRpbmEfCWhkZAIFD2QWAgIBDw8WCB8HBQVzdi1TRR8IBQ1TZXRUZW1wTG9jYWxlHwEFB1N2ZW5za2EfCWhkZAIGD2QWAgIBDw8WCB8HBQVlcy1FUx8IBQ1TZXRUZW1wTG9jYWxlHwEFCEVzcGHDsW9sHwloZGQCBw9kFgICAQ8PFggfBwUFaXQtSVQfCAUNU2V0VGVtcExvY2FsZR8BBQhJdGFsaWFubx8JaGRkAggPZBYCAgEPDxYIHwcFBW5sLU5MHwgFDVNldFRlbXBMb2NhbGUfAQUKTmVkZXJsYW5kcx8JaGRkAgkPZBYCAgEPDxYIHwcFBWNhLUVTHwgFDVNldFRlbXBMb2NhbGUfAQUHQ2F0YWzDoB8JaGRkAgoPZBYCAgEPDxYIHwcFBXBsLVBMHwgFDVNldFRlbXBMb2NhbGUfAQUGUG9sc2tpHwloZGQCCw9kFgICAQ8PFggfBwUFZXQtRUUfCAUNU2V0VGVtcExvY2FsZR8BBQVFZXN0aR8JaGRkAgwPZBYCAgEPDxYIHwcFBW5iLU5PHwgFDVNldFRlbXBMb2NhbGUfAQUOTm9yc2ssIEJva23DpWwfCWhkZAIND2QWAgIBDw8WCB8HBQVrby1LUh8IBQ1TZXRUZW1wTG9jYWxlHwEFCe2VnOq1reyWtB8JaGRkAg4PZBYCAgEPDxYIHwcFBWh1LUhVHwgFDVNldFRlbXBMb2NhbGUfAQUGTWFneWFyHwloZGQCDw9kFgICAQ8PFggfBwUFcm8tUk8fCAUNU2V0VGVtcExvY2FsZR8BBQhSb23Dom7Egx8JaGRkAi4PZBYCAgMPFgIfA2hkAi8PFgIeBWNsYXNzBQxzcGFuLTI0IGxhc3QWAgIBD2QWLgIBD2QWAmYPZBYCAgEPDxYCHwEFB0dDNDMxRjJkZAICDxYCHwEFngE8YSBocmVmPSIvYWJvdXQvY2FjaGVfdHlwZXMuYXNweCIgdGFyZ2V0PSJfYmxhbmsiIHRpdGxlPSJBYm91dCBDYWNoZSBUeXBlcyI+PGltZyBzcmM9Ii9pbWFnZXMvV3B0VHlwZXMvOC5naWYiIGFsdD0iVW5rbm93biBDYWNoZSIgdGl0bGU9IlVua25vd24gQ2FjaGUiIC8+PC9hPmQCBg9kFgQCAQ8WAh8DZ2QCBg8WAh8DaGQCBw8WAh8BBRxJbiBDYWxpZm9ybmlhLCBVbml0ZWQgU3RhdGVzZAILDxYCHwNoZAIMDxYCHwNnZAINDw8WAh8DaGRkAhAPFgIfA2gWAgIBDxYCHwEFgwJZb3UgbXVzdCBiZSA8YSBocmVmPSJodHRwczovL3d3dy5nZW9jYWNoaW5nLmNvbS9sb2dpbi8/UkVTRVQ9WSZyZWRpcj1odHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3NlZWsvY2FjaGVfZGV0YWlscy5hc3B4P3dwPUdDNDMxRjImU3VibWl0Nj1HbyIgdGl0bGU9IkxvZyBJbiI+bG9nZ2VkIGluPC9hPiB3aXRoIGEgR2VvY2FjaGluZy5jb20gYWNjb3VudCB0byB2aWV3IHRoZSBzcGVjaWZpYyBsb2NhdGlvbiBvZiB0aGlzIGdlb2NhY2hlLiBJdCdzIGZyZWUhZAIRDxYCHwNoZAISDxYCHwNoFg4CAw8WAh4Fc3R5bGUFDWRpc3BsYXk6bm9uZTsWAgIBDxYCHwFlZAINDw8WBB8FBTNjZHBmLmFzcHg/Z3VpZD05OGU2ZjVhOS1jZjJkLTQyZjgtOWNkZi1hM2Y1MzQzNmYzODQfA2hkZAIPDw8WAh8FBThjZHBmLmFzcHg/Z3VpZD05OGU2ZjVhOS1jZjJkLTQyZjgtOWNkZi1hM2Y1MzQzNmYzODQmbGM9NWRkAhEPDxYCHwUFOWNkcGYuYXNweD9ndWlkPTk4ZTZmNWE5LWNmMmQtNDJmOC05Y2RmLWEzZjUzNDM2ZjM4NCZsYz0xMGRkAhMPDxYGHwUFW2h0dHA6Ly9tYXBzLmdvb2dsZS5jb20vbWFwcz9mPWQmaGw9ZW4mc2FkZHI9JmRhZGRyPTM3LjM1OSwtMTIyLjAzMjI4MyhOZWVkbGUraW4rYStIYXlzdGFjaykeBlRhcmdldAUGX2JsYW5rHwNoZGQCFQ8WAh8DaGQCGw8WAh8DaBYEAgEPDxYGHglGb3JlQ29sb3IKTh4HRW5hYmxlZGgeBF8hU0ICBGRkAgMPDxYGHw0KTh8OaB8PAgRkZAIXD2QWCGYPFgIfA2hkAgEPDxYCHwNoZGQCAg8PFgIfA2hkZAIDDxYCHwNoZAIYD2QWAgIDDw8WAh8BBRNObyBoaW50cyBhdmFpbGFibGUuFgIeB29uY2xpY2sFDXJldHVybiBmYWxzZTtkAhkPFgIfA2hkAhwPFgIfA2hkAh0PDxYCHwNoZGQCHw8WAh8DaGQCIg9kFgICAQ9kFgQCAQ8PFgIfAQX/AzxpZnJhbWUgdHlwZT0iaWZyYW1lIiBzcmM9Imh0dHA6Ly9hZHMuZ3JvdW5kc3BlYWsuY29tL2EuYXNweD9ab25lSUQ9OSZUYXNrPUdldCZTaXRlSUQ9MSZYPScwZDFlZTAyY2RiZjM0OTgyODRiMGI0NGVmN2Q3YWVlZiciIHdpZHRoPSIxMjAiIGhlaWdodD0iMjQwIiBNYXJnaW53aWR0aD0iMCIgTWFyZ2luaGVpZ2h0PSIwIiBIc3BhY2U9IjAiIFZzcGFjZT0iMCIgRnJhbWVib3JkZXI9IjAiIFNjcm9sbGluZz0ibm8iIHN0eWxlPSJ3aWR0aDoxMjBweDtIZWlnaHQ6MjQwcHg7Ij48YSBocmVmPSJodHRwOi8vYWRzLmdyb3VuZHNwZWFrLmNvbS9hLmFzcHg/Wm9uZUlEPTkmVGFzaz1DbGljayY7TW9kZT1IVE1MJlNpdGVJRD0xIiB0YXJnZXQ9Il9ibGFuayI+PGltZyBzcmM9Imh0dHA6Ly9hZHMuZ3JvdW5kc3BlYWsuY29tL2EuYXNweD9ab25lSUQ9OSZUYXNrPUdldCZNb2RlPUhUTUwmU2l0ZUlEPTEiIHdpZHRoPSIxMjAiIGhlaWdodD0iMjQwIiBib3JkZXI9IjAiIGFsdD0iIiAvPjwvYT48L2lmcmFtZT5kZAIDDxYCHglpbm5lcmh0bWwFE0FkdmVydGlzaW5nIHdpdGggVXNkAiYPZBYEAgUPDxYCHwNnZGQCCQ8PFgIfBQU8fi90cmFjay9zZWFyY2guYXNweD93aWQ9OThlNmY1YTktY2YyZC00MmY4LTljZGYtYTNmNTM0MzZmMzg0ZGQCJw8PFgIfA2dkFgJmDxYCHwYCAhYEAgEPZBYEZg8VAwBXaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9ib29rbWFya3Mvdmlldy5hc3B4P2d1aWQ9OWZkMzlmYjgtOTUwMi00N2I0LWFlMDgtODZjZTIzNmZjNjYxG2Ztb3JhZXMmIzM5OyBzb2x2ZWQgYnV0IGZhcmQCAg8VAkxodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3Byb2ZpbGUvP2d1aWQ9NDQwY2Y2MWItZGNmMy00MjIwLWE4Nzct" />
+<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="Y2UzMTJmMTAzOTIxB2Ztb3JhZXNkAgIPZBYEZg8VAw5BbHRlcm5hdGluZ1Jvd1dodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD1kYTE5ZjUwMy04ZGYyLTRhMzYtYWE5OC01ZDQxNzlmNTg1NTAOU29sdmVkIFB1enpsZXNkAgIPFQJMaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9wcm9maWxlLz9ndWlkPTM3MWQzMTJlLWU4MjgtNGRhOC04MDIxLTY1MTQyMmE0NDYyMQZ3MDBmZWxkAikPZBYUAgEPDxYCHwNoZGQCBw8PFgIfA2hkZAIRDw8WAh8FBSMvc2Vlay9uZWFyZXN0LmFzcHg/dT1UaGUrTm9ydGgrU3RhcmRkAhUPDxYCHwUFJC9zZWVrL25lYXJlc3QuYXNweD91bD1UaGUrTm9ydGgrU3RhcmRkAhkPFgIfA2gWCgIDDw8WAh8FBVgvc2Vlay9uZWFyZXN0LmFzcHg/dHg9NDA4NjE4MjEtMTgzNS00ZTExLWI2NjYtOGQ0MTA2NGQwM2ZlJmxhdD0zNy4zNTkwMDAmbG5nPS0xMjIuMDMyMjgzZGQCBQ8PFgIfBQVcL3NlZWsvbmVhcmVzdC5hc3B4P3R4PTQwODYxODIxLTE4MzUtNGUxMS1iNjY2LThkNDEwNjRkMDNmZSZsYXQ9MzcuMzU5MDAwJmxuZz0tMTIyLjAzMjI4MyZmPTFkZAIJDw8WAh8FBTAvc2Vlay9uZWFyZXN0LmFzcHg/bGF0PTM3LjM1OTAwMCZsbmc9LTEyMi4wMzIyODNkZAILDw8WAh8FBTQvc2Vlay9uZWFyZXN0LmFzcHg/bGF0PTM3LjM1OTAwMCZsbmc9LTEyMi4wMzIyODMmZj0xZGQCDw8PFgIfBQVKaHR0cDovL3d3dy53YXltYXJraW5nLmNvbS9kaXJlY3RvcnkuYXNweD9mPTEmbGF0PTM3LjM1OTAwMCZsb249LTEyMi4wMzIyODNkZAIbDxYCHwNoZAIfDw8WAh8FBSIvcmV2aWV3cy9ob3RlbHMtaW4tU3Vubnl2YWxlLENBLFVTZGQCIQ8PFgIfA2hkZAIjDw8WAh8DaGRkAicPZBYIAgEPFgIfAQUPMiBMb2dnZWQgVmlzaXRzZAIHDw8WAh8FBUN+L3NlZWsvY2FjaGVfbG9nYm9vay5hc3B4P2d1aWQ9OThlNmY1YTktY2YyZC00MmY4LTljZGYtYTNmNTM0MzZmMzg0ZGQCCA8WAh8DaGQCCQ8PFgIfA2hkZAIqDxYCHwEFBHRydWVkAisPFgIfAQUebGF0PW51bGw7bG5nPW51bGw7Z3VpZD1udWxsOw0KZAIsDxYCHwEFdXRyeSB7IF9nYXEucHVzaChbJ190cmFja0V2ZW50JywgJ0dlb2NhY2hpbmcnLCAnQ2FjaGVEZXRhaWxzTWVtYmVyVHlwZScsICdOb3RTaWduZWRJbicsIG51bGwsIHRydWVdKTsgfSBjYXRjaChlcnIpIHsgfWQCMA8WAh8DaGQCMQ9kFgQCAw8WAh8BBQdFbmdsaXNoZAIFDxYCHwYCEBYgZg9kFgICAQ8PFggfBwUFZW4tVVMfCAUNU2V0VGVtcExvY2FsZR8BBQdFbmdsaXNoHwloZGQCAQ9kFgICAQ8PFggfBwUFZGUtREUfCAUNU2V0VGVtcExvY2FsZR8BBQdEZXV0c2NoHwloZGQCAg9kFgICAQ8PFggfBwUFZnItRlIfCAUNU2V0VGVtcExvY2FsZR8BBQlGcmFuw6dhaXMfCWhkZAIDD2QWAgIBDw8WCB8HBQVwdC1QVB8IBQ1TZXRUZW1wTG9jYWxlHwEFClBvcnR1Z3XDqnMfCWhkZAIED2QWAgIBDw8WCB8HBQVjcy1DWh8IBQ1TZXRUZW1wTG9jYWxlHwEFCcSMZcWhdGluYR8JaGRkAgUPZBYCAgEPDxYIHwcFBXN2LVNFHwgFDVNldFRlbXBMb2NhbGUfAQUHU3ZlbnNrYR8JaGRkAgYPZBYCAgEPDxYIHwcFBWVzLUVTHwgFDVNldFRlbXBMb2NhbGUfAQUIRXNwYcOxb2wfCWhkZAIHD2QWAgIBDw8WCB8HBQVpdC1JVB8IBQ1TZXRUZW1wTG9jYWxlHwEFCEl0YWxpYW5vHwloZGQCCA9kFgICAQ8PFggfBwUFbmwtTkwfCAUNU2V0VGVtcExvY2FsZR8BBQpOZWRlcmxhbmRzHwloZGQCCQ9kFgICAQ8PFggfBwUFY2EtRVMfCAUNU2V0VGVtcExvY2FsZR8BBQdDYXRhbMOgHwloZGQCCg9kFgICAQ8PFggfBwUFcGwtUEwfCAUNU2V0VGVtcExvY2FsZR8BBQZQb2xza2kfCWhkZAILD2QWAgIBDw8WCB8HBQVldC1FRR8IBQ1TZXRUZW1wTG9jYWxlHwEFBUVlc3RpHwloZGQCDA9kFgICAQ8PFggfBwUFbmItTk8fCAUNU2V0VGVtcExvY2FsZR8BBQ5Ob3JzaywgQm9rbcOlbB8JaGRkAg0PZBYCAgEPDxYIHwcFBWtvLUtSHwgFDVNldFRlbXBMb2NhbGUfAQUJ7ZWc6rWt7Ja0HwloZGQCDg9kFgICAQ8PFggfBwUFaHUtSFUfCAUNU2V0VGVtcExvY2FsZR8BBQZNYWd5YXIfCWhkZAIPD2QWAgIBDw8WCB8HBQVyby1STx8IBQ1TZXRUZW1wTG9jYWxlHwEFCFJvbcOibsSDHwloZGQCAw8WAh8BBStTZXJ2ZXI6IFdFQjAzOyBCdWlsZDogV2ViLkhvdEZpeF8yMDEyMTIxMS4xZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAQUSY3RsMDAkY2JSZW1lbWJlck1l4bXr81thZG2PoWxIqVZjMOUf7tU=" />
+</div>
+
+<script type="text/javascript">
+//<![CDATA[
+var theForm = document.forms['aspnetForm'];
+if (!theForm) {
+ theForm = document.aspnetForm;
+}
+function __doPostBack(eventTarget, eventArgument) {
+ if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
+ theForm.__EVENTTARGET.value = eventTarget;
+ theForm.__EVENTARGUMENT.value = eventArgument;
+ theForm.submit();
+ }
+}
+//]]>
+</script>
+
+
+<script src="/WebResource.axd?d=Dh2VENdI9XyWNN0f7DnYfR8WWRCRIzdVqal2y0yjiQ5nC_eHhLchYgnQDHIk0d3RCcSUMVZ36ciRD0qmhXKmeu3S_RE1&t=634449413070371108" type="text/javascript"></script>
+
+
+<script src="/ScriptResource.axd?d=8q09cuy9-PZDS8eZx6HLVXd3YZywgUmuoy8VVtGr3vaISS8ybaBLyQLFlq93nr2dlYP0QJWcJvooQKkloTdALTrS571k1UcPpD2pbXbpthIOf2Mn8gCnpyvfv-ZudWTMi0y39YZC0-Q0yjjxQ82yTlKdhBw1&t=6df0ad7a" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=I9_m2Hb1Tv_B0qTMDG8bMbnkNSHUkv5oUaG9-V5NZ8qQ2VFlu60I8y8gfr3vPmZjbiPnu43MOQdFVDeYF-nDAEKBLmyxD3DCTGmes9NNbbvaDEHyEuuRWgccIkK3ik5TI48YGDxjHjqdn-gTK4Fkgd17LGw1&t=2610f696" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=8vNbe34dAujgZMPnfnacfjeoweX1vHgyns8KlAV4vpGpsZC9Cf3pro__lv8ekBa0NiCgXGMMolzOUNH__lrnEI_qjlNBIAuuLeemtAXV_i6E0QIMZa8nGSYmWGF5nQOJK3rmZzvTxsr2Mh4Ebdba_1ywGLUSH_U_XIe-jzecfRQwwvjZ0&t=2610f696" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=l5IqBBbOFPRmpVAJwxQpHQyZ16ITBnk7fYRIeFc1JaDh64igpOv-k92v3DpzWBikWWvRdoxgNXda9cdmIFt2Ryy2gD2Tv71tVdwVNB4i-d1_vwLdJifCsG55PNiibmPX-x1Vspbf6jGBVWDKxT4kuLr2vWh-XRcY7PiryWks0UgjSCXEHO05VytTmCI6A-IhnCg2kD_i3YytsXr36qf0k6q0vQ41" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=mw8CUwVrYP9IGhC7WIGT8qdlVInGzqviii3RV8GrEEiOV2Nqjk57cAorEy9ACR1-rU7I3CZphWXcx81x-LDKIItu7BGPceT7Q61MOAXhSyJyW2DF3crLIX0Xef7vI1s2RLsp2bf8Aazkh-w4559ltQCi1H8uzBcnORltR9bo05Oe5VlRs1WnFqxyOK9aLEH4pBXNx8Bhb2-oIOLExj6kkCQgF06_A6ksiNnQXuGaKfXh1LjjCyujVv1xsxL_muSivN4bS4R4JR4M2Z3WmsBSnQXzJkIKkQB7kOS3JYimpNQ7sw1_qOYPZVB0xYbSCGD-xptYnX3Q4DLGiBNW4mP5R1Xv0QiVlwA9uiMAy_mQKBalvK4YjYdSbW9T9WZdtn39cD799HNy--sDKm1hhlBWb8Dz1jgxR2B9glqCYkqQmk3DSoPhPx9eWxB5q9VFjw1Q4u3d0Rgu8lF3NszOnHmJ19E6XZOdbRPyOjljcqTy1MWgNSwFAV-E3kWUGiJ0QNel49k3VkdjBUTKhIqIdQ9wve0zAcvWgxHEaFuvXv92aYmJwFYFDbNPvkYfBRLakBbpHIzGs9e0xu5sbTAVijArOHlzTSMNx2jK2mdt8VSjThXQAkMSV5W0jY2I6tuqFunlegJeA9zrFE9HdfbBtj9gOSe3LQQNMG7NaUShNTYUbJ5eZbQ8g7O5gjKFbDylaSZqv0aXQu0Lgrn7EdKV3B0BMhNeG3pR32zEBX1T3hEAnDKiYVOX0" type="text/javascript"></script>
+<script src="js/cachedetails.js" type="text/javascript"></script>
+<script src="../js/latlng.js" type="text/javascript"></script>
+<script src="/WebResource.axd?d=Np8DmZmh2tcIkgE9SU7mE6n1BWbJ0opng-rHikqBjFQo0nbLYSeBBVhJhCHcmx1ihKnAnQv_ZhnItUUjENzIzc1uoXk1&t=634449413070371108" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+function WebForm_OnSubmit() {
+if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;
+return true;
+}
+//]]>
+</script>
+
+<div>
+
+ <input type="hidden" name="__PREVIOUSPAGE" id="__PREVIOUSPAGE" value="Q3QLAIGc3fycf1xcmR0oeYDSmxzti-0045OC6NZQvsE42Tm2u2QIX8zoZDBQxLovJ-hK6GtvJtlghgEFizixxK5opmWjeHAxzOpw_rZ8ZR8kHZBX0" />
+</div>
+ <script type="text/javascript">
+//<![CDATA[
+Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00');
+//]]>
+</script>
+
+ <div id="Top" class="SkipLinks">
+
+ <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
+ <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
+
+ </div>
+
+ <!--[if lte IE 6]>
+ <div class="WarningMessage PhaseOut">
+
+ <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
+
+ </div>
+ <![endif]-->
+
+
+
+ <div class="PrintOnly">
+
+ <p>
+ <img src="/images/logo_print_bw.png" alt="Geocaching.com" /></p>
+ <hr />
+
+ </div>
+
+ <header>
+
+ <div class="container">
+
+ <h1 class="Logo span-16">
+ <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">Geocaching</a></h1>
+ <div class="ProfileWidget span-8 last">
+
+ <div id="ctl00_divNotSignedIn" class="FloatContainer">
+
+ <p class="NotSignedInText"><strong>Welcome, Visitor!</strong><br /></p>
+ <p class="LoginWithFacebook">
+ <a id="ctl00_uxSignIn" title="Login with Facebook" class="btnFacebookLogin NoWrap" href="javascript:__doPostBack('ctl00$uxSignIn','')"><span>Login with Facebook</span></a></p>
+ <p class="NotSignedInLinks clear">
+ <a id="hlSignIn" accesskey="s" title="Sign In" class="SignInLink" href="/login/">Sign In</a> | <a id="ctl00_hlRegister" accesskey="r" title="Sign Up" href="../membership/register.aspx?type=basic">Sign Up</a></p>
+ <div id="SignInWidget">
+
+ <h3>Sign In with Geocaching</h3>
+ <div id="ctl00_vsSignInWidgetForm" class="FormSummaryWidget FormErrorWidget InputWidth" style="color:Red;display:none;">
+
+</div>
+ <p>
+ <label for="ctl00_tbUsername" id="ctl00_lblUsername" title="Geocaching Username">Geocaching Username:</label><br />
+ <input name="ctl00$tbUsername" type="text" id="ctl00_tbUsername" class="text" autocomplete="off" />
+ <span id="ctl00_rfvUsername" title="Username is a required field; please enter a valid username." style="color:Red;display:none;"><span class="FormIcon FormValidationIcon">*</span></span>
+ </p>
+ <p>
+ <label for="ctl00_tbPassword" id="ctl00_lblPassword" title="Geocaching Password">Geocaching Password:</label><br />
+ <input name="ctl00$tbPassword" type="password" id="ctl00_tbPassword" class="text" autocomplete="off" />
+ <span id="ctl00_rfvPassword" title="Password is a required field; please enter a valid password." style="color:Red;display:none;"><span class="FormIcon FormValidationIcon">*</span></span>
+ </p>
+ <p>
+ <span class="Checkbox" title="Keep Me Signed In" autocomplete="off"><input id="ctl00_cbRememberMe" type="checkbox" name="ctl00$cbRememberMe" /><label for="ctl00_cbRememberMe">Keep Me Signed In</label></span><br />
+ <small>
+ Uncheck if on a shared computer.</small>
+ </p>
+ <p>
+ <input type="submit" name="ctl00$btnSignIn" value="Sign In" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$btnSignIn", "", true, "SignInForm", "https://www.geocaching.com/login/default.aspx?redir=%2fseek%2fcache_details.aspx%3fwp%3dGC431F2%26Submit6%3dGo", false, false))" id="ctl00_btnSignIn" title="Sign In" />
+ or
+ <a id="ctl00_hlSignInClose" title="Close this Window" class="SignInCloseLink" href="javascript:void(0);">Close</a></p>
+ <p>
+ <small>
+ <a id="ctl00_hlForgot" title="Forgot your username or password?" href="../login/password.aspx">Forgot your username or password?</a></small></p>
+
+ </div>
+
+
+ </div>
+
+
+
+
+ </div>
+
+ <div class="NavContainer span-24 last">
+ <nav id="Navigation">
+
+ <ul class="Menu">
+ <li>
+ <a id="ctl00_hlNavLearn" accesskey="1" title="Learn" href="../guide/">Learn ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavGeocaching101" accesskey="i" title="Geocaching 101" href="../guide/">Geocaching 101</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeocaching2Minutes" title="Geocaching in 2 Minutes" href="../videos/#cat=cat:newbies&vid=-4VFeYZTTYs">Geocaching in 2 Minutes</a></li>
+ </ul>
+ </li>
+ <li id="ctl00_liNavJoin">
+ <a id="ctl00_hlNavJoin" accesskey="2" title="Join" href="../membership/register.aspx?type=basic">Join</a></li>
+
+ <li>
+ <a id="ctl00_hlNavPlay" accesskey="3" title="Play" href="./">Play ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavHide" accesskey="d" title="Hide & Seek a Cache" href="./">Hide & Seek a Cache</a></li>
+ <li>
+ </li>
+ <li><a id="ctl00_hlSubNavMap" accesskey="/" title="View Geocache Map" href="../map/">View Geocache Map</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTrackables" accesskey="e" title="Find Trackables" href="../track/">Find Trackables</a></li>
+ <li>
+ <a id="ctl00_hlSubNavHelpCenter" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavCommunity" accesskey="6" title="Community" href="../forums/">Community ▼</a>
+ <ul class="SubMenu">
+
+ <li>
+ <a id="ctl00_hlSubNavTellaFriend" accesskey="-" title="Tell a Friend" href="../account/SendReferral.aspx">Tell a Friend</a></li>
+
+ <li><a id="ctl00_hlSubNavVolunteers" accesskey="+" title="Volunteers" href="../volunteers/">Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavLocal" accesskey="z" title="Local Organizations" href="../organizations/">Local Organizations</a></li>
+ <li>
+ <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBlog" accesskey="b" title="Blog" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEvents" accesskey="v" title="Events" href="../calendar/">Events</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavShop" accesskey="4" title="Shop" href="http://shop.geocaching.com/">Shop ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavShop" accesskey="j" title="Shop Geocaching" rel="external" href="http://shop.geocaching.com/">Shop Geocaching</a></li>
+ <li>
+ <a id="ctl00_hlSubNavIntlRetailers" title="International Retailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGPSReviews" accesskey="w" title="GPS Reviews" href="/reviews/gps">GPS Reviews</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGPSGuide" accesskey="k" title="Guide to Buying a GPS Device" href="../about/buying.aspx">Guide to Buying a GPS Device</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavPartnering" accesskey="5" title="Partnering" href="../travel/">Partnering ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavTravel" title="Travel and GeoTourism" href="../travel/">Travel and GeoTourism</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBrandedPromotions" title="Branded Promotions" href="../brandedpromotions/">Branded Promotions</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEducation" title="Geocaching and Education" href="../education/">Geocaching and Education</a></li>
+ <li>
+ <a id="ctl00_hlSubNavAdvertisingWithUs" title="Advertising with Us" href="../about/advertising.aspx">Advertising with Us</a></li>
+ <li>
+ <a id="ctl00_hlSubNavAPIProgram" title="API Program" href="../live/apidevelopers/">API Program</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavVideos" accesskey="7" title="Videos" href="../videos/">Videos</a></li>
+ <li>
+ <a id="ctl00_hlNavFollowUs" title="Follow Us" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts">Follow Us ▼</a>
+ <ul class="SubMenu NavSocialMedia">
+ <li>
+ <a id="ctl00_hlSubNavFacebook" title="Facebook" class="SubNavFacebook" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts">Facebook</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTwitter" title="Twitter" class="SubNavTwitter" href="http://twitter.com/GoGeocaching">Twitter</a></li>
+ <li>
+ <a id="ctl00_hlSubNavFlickr" title="Flickr" class="SubNavFlickr" href="http://www.flickr.com/photos/geocaching_com/">Flickr</a></li>
+ <li>
+ <a id="ctl00_hlSubNavYouTube" title="YouTube" class="SubNavYouTube" href="http://www.youtube.com/user/GoGeocaching">YouTube</a></li>
+ </ul>
+ </li>
+ </ul>
+
+ </nav>
+ <div class="LanguageSelector">
+
+
+<div class="LocaleText">
+
+ <strong>Choose Your Language:</strong>
+
+</div>
+<div class="LocaleList">
+
+ <div class="selected-language">
+
+ <a href="#">English▼</a>
+
+ </div>
+ <ul class="language-list">
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl05$uxLocaleItem','')">Svenska</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl06$uxLocaleItem','')">Español</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl07$uxLocaleItem','')">Italiano</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl08$uxLocaleItem','')">Nederlands</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl09$uxLocaleItem','')">Català</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl10$uxLocaleItem','')">Polski</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl11$uxLocaleItem','')">Eesti</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl12$uxLocaleItem','')">Norsk, Bokmål</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl13$uxLocaleItem','')">한국어</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl14$uxLocaleItem','')">Magyar</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl15$uxLocaleItem','')">Română</a></li>
+
+ </ul>
+
+</div>
+<script type="text/javascript">
+
+ jQuery(document).ready(function () {
+ jQuery(".selected-language a").click(function (e) {
+ e.preventDefault();
+ var $loc = jQuery(this).parent().next();
+ jQuery($loc).show().position({
+ of: $loc.parent(),
+ my: "left top",
+ at: "left bottom",
+ offset: "0 0",
+ collision: "fit fit"
+ });
+ jQuery(this).addClass("Expanded");
+ jQuery(document).click(function () {
+ jQuery(".language-list").fadeOut("fast");
+ jQuery(".selected-language a").removeClass("Expanded");
+ });
+ return false;
+ });
+ });
+</script>
+ </div>
+ </div>
+
+
+ </div>
+
+
+ </header>
+ <section id="Content">
+
+
+ <div class="container">
+
+ <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
+
+ <p>
+ <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
+ </p>
+
+
+ </div>
+
+ <div id="ctl00_divContentMain" class="span-24 last">
+
+
+
+
+ <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
+
+ <p>
+ <a href="#" class="CoordInfoLink">
+ <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC431F2</span>
+ <span class="arrow">▼</span> </a>
+ </p>
+
+</div>
+<div id="dlgClipboard">
+ <input type="text" class="TextFormat" />
+ <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close">
+ x</a>
+</div>
+<script type="text/javascript">
+ $("a.CoordInfoLink").click(function (e) {
+ e.preventDefault();
+
+ $("#dlgClipboard")
+ .show()
+ .position({
+ of: $("a.CoordInfoLink"),
+ my: "right top",
+ at: "right bottom",
+ offset: "0 5"
+ })
+ .find("input")
+ .val('http://coord.info/' + $('.CoordInfoCode').text())
+ .focus()
+ .select();
+
+ $(document).mouseup(function (e) {
+ if ($(e.target).parent("div#dlgClipboard").length == 0) {
+ $(this).unbind(e);
+ $("div#dlgClipboard").hide();
+ }
+ });
+
+ return false;
+ });
+
+
+</script>
+
+ <div class="span-17">
+
+ <div class="span-17 last BottomSpacing" id="cacheDetails">
+ <p class="cacheImage">
+ <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/8.gif" alt="Unknown Cache" title="Unknown Cache" /></a>
+ </p>
+
+ <h2 class="NoBottomSpacing">
+ <span id="ctl00_ContentBody_CacheName">Needle in a Haystack</span></h2>
+ <div class="minorCacheDetails Clear">
+ <div id="ctl00_ContentBody_mcd1">
+ A cache by <a href="http://www.geocaching.com/profile/?guid=f3d7b7c8-8698-4e21-a6ad-24e148f5c6a5&wid=98e6f5a9-cf2d-42f8-9cdf-a3f53436f384&ds=2">The North Star</a></div>
+ <div id="ctl00_ContentBody_mcd2">
+ Hidden:
+ 12/21/2012
+
+ </div>
+ <div>In California, United States</div>
+ </div>
+ </div>
+ <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-3 BottomSpacing">
+
+ Difficulty:
+ <br />
+ Terrain:
+
+ </div>
+
+ <div id="ctl00_ContentBody_diffTerrStars" class="CacheStarImgs span-2">
+
+ <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars3.gif" alt="3 out of 5" /></span>
+ <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars1_5.gif" alt="1.5 out of 5" /></span>
+
+ </div>
+
+ <div id="ctl00_ContentBody_size" class="CacheSize span-9">
+
+ <p style="text-align: center;">
+ Size: <span class="minorCacheDetails"><img src="/images/icons/container/other.gif" alt="Size: other" title="Size: other" /> <small>(other)</small></span></p>
+
+ </div>
+
+
+
+ <div class="span-3 right last">
+
+
+
+ </div>
+
+
+ <div id="lus_container" class="lus-container Clear">
+ <div class="lus-header">
+ <span>
+ Join now to view geocache location details. It's free!
+ </span>
+ <span class="lus-signup">
+ <a id="ctl00_ContentBody_locdSignUpLink" title="Sign up" href="/membership/register.aspx?type=basic">Sign up</a><a id="hlFBLogin" title="Log in with Facebook" class="btnFacebookLogin" href="/api/beginfacebook"><span id="ctl00_ContentBody_locFBLogin">Login</span></a>
+ </span>
+ </div>
+ <div style="position: relative;height:257px;">
+ <div class="lus-video">
+ <div class="lus-textblock">
+ <div class="play-control AlignCenter"><a id="ctl00_ContentBody_hlPlayArrow" title="Play Video">▶</a></div>
+ <h4>
+ Watch
+ </h4>
+ How Geocaching Works
+ </div>
+ </div>
+ <div class="lus-image">
+ <img src="/images/seek/locdp_cityscape.jpg" width="380" height="257" />
+ </div>
+ </div>
+ <div class="lus-footer">
+ <span class="AlignRight">
+ <span>Looking for a different adventure?</span>
+ </span>
+ <span class="lus-findacache NoWrap">
+ <input type="submit" name="ctl00$ContentBody$findacache" value="Find a Cache Near Me" id="findacache" title="Find a Cache Near Me" />
+ </span>
+ </div>
+ </div>
+ <script type="text/javascript">
+
+ $("#lus_container")
+ .on("click", "div.lus-video", function () {
+ var $this = $(this),
+ h = $this.height(),
+ w = $this.width();
+
+ $("div.lus-image").hide('slide', { direction: 'right' }, 500, function () {
+ var vhtml = ["<iframe width=\"" + w + "\" height=\"" + h + "\" src=\"http://www.youtube.com/embed/-4VFeYZTTYs?rel=0&autoplay=1\" frameborder=\"0\" allowfullscreen></iframe>"].join('');
+ $this.replaceWith(vhtml);
+ });
+ return false;
+ });
+
+ $("#findacache").click(function (e) {
+ e.preventDefault();
+ $("#txtFindCache").text("Searching...");
+
+ navigator.geolocation.getCurrentPosition(
+ function (position) { // Browser success
+ $(window.location).attr('href', '/seek/nearest.aspx?origin_lat=' + position.coords.latitude + '&origin_long=' + position.coords.longitude + '&dist=100');
+ }, function (error) { // Browser failure, fallback to geocode.
+ $.ajax({
+ url: '/api/geocode?cmd=whoami',
+ dataType: 'json',
+ async: false,
+ success: function (response) {
+ if (response.status == 'success') { // Geocode success
+ $(window.location).attr('href', '/seek/nearest.aspx?origin_lat=' + response.data.lat + '&origin_long=' + response.data.lng + '&dist=100');
+ } else { // Total failure, just go to the search page.
+ $(window.location).attr('href', '/seek/nearest.aspx');
+ }
+ }
+ });
+ },
+ {
+ timeout: 3000 // Wait on the browser for a max of 3 seconds.
+ });
+ return false;
+ });
+
+ // Geolocation emulator
+ (function (geolocation) {
+
+ if (geolocation) return;
+
+ var cache;
+
+ geolocation = window.navigator.geolocation = {};
+ geolocation.getCurrentPosition = function (callback) {
+
+ if (cache) callback(cache);
+
+ $.getScript('//www.google.com/jsapi', function () {
+
+ cache = {
+ coords: {
+ "latitude": google.loader.ClientLocation.latitude,
+ "longitude": google.loader.ClientLocation.longitude
+ }
+ };
+
+ callback(cache);
+ });
+
+ };
+
+ geolocation.watchPosition = geolocation.getCurrentPosition;
+ })(navigator.geolocation);
+
+
+ </script>
+
+ <p class="Clear">
+ </p>
+
+
+
+
+
+
+ <fieldset class="DisclaimerWidget">
+ <legend class="warning">
+ Please note
+ </legend>
+ <p class="NoBottomSpacing">
+ Use of geocaching.com services is subject to the terms and conditions <a href="/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>.
+ </p>
+ </fieldset>
+
+
+ <div class="UserSuppliedContent">
+
+ <span id="ctl00_ContentBody_ShortDescription">
+</span>
+
+ </div>
+
+ <br />
+ <div class="UserSuppliedContent">
+
+ <span id="ctl00_ContentBody_LongDescription"><div class="Section1">
+<p><span style="font-size:10.0pt;font-family:Verdana;mso-bidi-font-family:Arial;color:red;">The cache is not at the posted coordinates but is less than 2 miles away</span></p>
+<p><span style="font-size:10.0pt;font-family:Verdana;mso-bidi-font-family:Arial;color:#333333;"><a href="http://coord.info/GC430FM" target="_blank" rel="nofollow">Cache is Unpublished</a> is a little like looking for a Needle in a Haystack. The “<b>Needle</b>” should be easier to find in this <a href="http://dl.dropbox.com/u/1930940/Haystack.zip" target="_blank" rel="nofollow">Haystack</a>.<br />
+<span style="font-size:10.0pt;font-family:Verdana;mso-bidi-font-family:Arial;color:#333333;"><br />
+Cache is "sign" only. Don't forget to bring your pen.<br />
+<br />
+Enjoy!<br />
+<br />
+You can validate your puzzle solution with <a href="http://certitude.comxa.com/certitude.php?wp=GC431F2">Certitude</a> or see <a href="http://certitude.comxa.com/certified.php?wp=GC431F2">who solved</a> this puzzle.<br />
+<br />
+Congratulations to <a href="http://www.geocaching.com/profile/?u=fmoraes" target="_blank" rel="nofollow">fmoraes</a> on FTS and <a href="http://www.geocaching.com/profile/?u=TeamOttlet" target="_blank" rel="nofollow">TeamOttlet</a> on FTF. That's two The North Star FTF's in a row!</span></span></p>
+</div></span>
+
+ </div>
+
+ <p>
+
+
+ </p>
+ <p id="ctl00_ContentBody_hints">
+ <strong>
+ Additional Hints</strong>
+ (<a id="ctl00_ContentBody_lnkDH" title="Decrypt" onclick="return false;" href="#">No hints available.</a>)</p>
+ <div id="div_hint" class="span-8 WrapFix">
+ </div>
+ <div id='dk' style="display: block;" class="span-9 last">
+ <span id="ctl00_ContentBody_EncryptionKey" class="right"></span>
+ </div>
+ <div class="Clear">
+ </div>
+
+ </div>
+
+
+ <div class="span-6 prepend-1 last">
+
+
+<div class="CacheDetailNavigationWidget NoPrint">
+
+ <h3 class="WidgetHeader">
+ Navigation
+ </h3>
+ <div class="WidgetBody">
+
+ <ul class="CacheDetailsNavLinks">
+ <li><a href="https://www.geocaching.com/login/?RESET=Y&redir=%2fseek%2flog.aspx%3fID%3d3373765" class="lnk"><img src="/images/icons/16/write_log_locked.png" /> <span>Log in to log your visit</span></a></li>
+<li><a href="https://www.geocaching.com/login/?RESET=Y&redir=%2fmy%2fwatchlist.aspx%3fw%3d3373765" class="lnk"><img src="/images/icons/16/watch_locked.png" /> <span>Log in to watch this listing</span></a></li>
+
+ </ul>
+
+ </div>
+
+
+</div>
+
+
+
+
+
+
+
+ <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing">
+
+ <h3 class="WidgetHeader">
+ Attributes</h3>
+ <div class="WidgetBody">
+ <img src="/images/attributes/bicycles-yes.gif" alt="bikes allowed" title="bikes allowed" width="30" height="30" /> <img src="/images/attributes/available-yes.gif" alt="available 24-7" title="available 24-7" width="30" height="30" /> <img src="/images/attributes/food-yes.gif" alt="food nearby" title="food nearby" width="30" height="30" /> <img src="/images/attributes/stealth-yes.gif" alt="stealth required" title="stealth required" width="30" height="30" /> <img src="/images/attributes/parking-yes.gif" alt="parking available" title="parking available" width="30" height="30" /> <img src="/images/attributes/onehour-yes.gif" alt="takes less than 1 hour" title="takes less than 1 hour" width="30" height="30" /> <img src="/images/attributes/kids-yes.gif" alt="kid friendly" title="kid friendly" width="30" height="30" /> <img src="/images/attributes/dogs-yes.gif" alt="dogs allowed" title="dogs allowed" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p>
+ </div>
+
+ </div>
+
+
+ <div id="ctl00_ContentBody_uxBanManWidget" class="CacheDetailPageAds clear">
+
+ <div id="ctl00_ContentBody_divContentSide">
+
+ <p class="NoBottomSpacing">
+ <span id="ctl00_ContentBody_ADModules_09"><iframe type="iframe" src="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Get&SiteID=1&X='0d1ee02cdbf3498284b0b44ef7d7aeef'" width="120" height="240" Marginwidth="0" Marginheight="0" Hspace="0" Vspace="0" Frameborder="0" Scrolling="no" style="width:120px;Height:240px;"><a href="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Click&;Mode=HTML&SiteID=1" target="_blank"><img src="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Get&Mode=HTML&SiteID=1" width="120" height="240" border="0" alt="" /></a></iframe></span>
+ </p>
+ <p class="AlignCenter">
+ <small><a href="../about/advertising.aspx" id="ctl00_ContentBody_advertisingWithUs" title="Advertising with Us">Advertising with Us</a></small></p>
+
+ </div>
+
+</div>
+
+
+
+ <div class="GoogleAds AlignCenter BottomSpacing">
+ </div>
+ <div class="clear">
+ </div>
+
+ <span id="ctl00_ContentBody_lnkTravelBugs"></span>
+
+
+<div class="CacheDetailNavigationWidget">
+
+ <h3 class="WidgetHeader">
+ <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span>
+ </h3>
+ <div class="WidgetBody">
+
+
+ <div id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItems">
+
+ <p class="NoBottomSpacing"><span id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItemsLabel">There are no Trackables in this cache.</span></p>
+
+</div>
+ <div class="TopSpacing">
+
+ <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory" href="../track/search.aspx?wid=98e6f5a9-cf2d-42f8-9cdf-a3f53436f384">View past Trackables</a></p>
+ <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="../track/default.aspx">What are Trackable Items?</a></p>
+ </div>
+
+
+ </div>
+
+
+</div>
+
+
+<div class="CacheDetailNavigationWidget">
+
+ <h3 class="WidgetHeader">Bookmark Lists</h3>
+ <div class="WidgetBody">
+
+
+ <ul>
+
+ <li style='padding: .5em;' class=''>
+ <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=9fd39fb8-9502-47b4-ae08-86ce236fc661">
+ fmoraes' solved but far</a><br />
+ <small><em>
+ by
+ <a href="http://www.geocaching.com/profile/?guid=440cf61b-dcf3-4220-a877-ce312f103921">
+ fmoraes</a> </em></small>
+ </li>
+
+ <li style='padding: .5em;' class='AlternatingRow'>
+ <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=da19f503-8df2-4a36-aa98-5d4179f58550">
+ Solved Puzzles</a><br />
+ <small><em>
+ by
+ <a href="http://www.geocaching.com/profile/?guid=371d312e-e828-4da8-8021-651422a44621">
+ w00fel</a> </em></small>
+ </li>
+
+ </ul>
+
+ <p class="NoBottomSpacing">
+ <a href="/bookmarks/default.aspx?guid=98e6f5a9-cf2d-42f8-9cdf-a3f53436f384&WptTypeID=8" title="View all bookmark lists...">View all bookmark lists...</a>
+ </p>
+
+ </div>
+
+
+</div>
+
+
+
+
+
+ </div>
+
+
+ <div id="ctl00_ContentBody_bottomSection" class="span-24 last">
+
+ <p>
+
+ <br />
+
+
+ </p>
+
+
+
+ <p class="NoPrint">
+ <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span>
+ <br />
+ <span id="ctl00_ContentBody_FindText"></span>
+ </p>
+ <ul class="NoPrint">
+ <li>
+ ...other caches
+ <a id="ctl00_ContentBody_uxFindLinksHiddenByThisUser" href="/seek/nearest.aspx?u=The+North+Star">hidden</a>
+ or
+ <a id="ctl00_ContentBody_uxFindLinksFoundByThisUser" href="/seek/nearest.aspx?ul=The+North+Star">found</a>
+ by this user
+ </li>
+
+
+ <li>
+ ...nearby <a id="ctl00_ContentBody_uxFindLinksHotels" href="/reviews/hotels-in-Sunnyvale,CA,US">Hotels</a>
+ </li>
+ </ul>
+ <p class="NoPrint">
+
+ </p>
+ <span class="NoPrint">
+
+ </span>
+ <p class="NoPrint">
+
+ </p>
+
+ <div class="InformationWidget Clear">
+ <h3>
+ 2 Logged Visits</h3>
+ <div class="EncryptDecrypt">
+ <a href="#" class="decrypt-link">
+ Decrypt
+ </a>
+ </div>
+ <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 1 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 1 </p></span>
+ <p class="HalfLeft">
+ <a id="ctl00_ContentBody_uxLogbookLink" href="cache_logbook.aspx?guid=98e6f5a9-cf2d-42f8-9cdf-a3f53436f384">View Logbook</a>
+ </p>
+ <p class="NoBottomSpacing AlignRight">
+ <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links.
+ </p>
+ </div>
+
+ <div id="cache_logs_container">
+ <table id="cache_logs_table" class="LogsTable NoBottomSpacing">
+ <tbody>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="AlignCenter">
+ <div id="pnlLazyLoad" style="display: none;">
+ <img src="/images/loading2.gif" class="StatusIcon" alt="Loading" />
+ Loading Cache Logs...
+ </div>
+ <div id="pnlButtonLoad" style="display: none;">
+ <a class="MobileButton">
+ Load More Logs...</a>
+ </div>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+ <p>
+ <small>
+ Current Time: <time datetime="2012-12-21T10:52:24Z">12/21/2012 10:52:24 AM (UTC-08:00) Pacific Time (US & Canada) (6:52 PM GMT)</time><br/>Last Updated: <time class="timeago" datetime="2012-12-21T16:59:00Z">2012-12-21T16:59:00Z</time> on 12/21/2012 8:59:00 AM (UTC-08:00) Pacific Time (US & Canada) (4:59 PM GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum
+ </small>
+ </p>
+
+
+ </div>
+ <script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl">
+ <tr class="log-row" data-encoded="${IsEncoded}" >
+ <td>
+ <div class="FloatLeft LogDisplayLeft" >
+ <p class="logOwnerProfileName">
+ <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong></p>
+ <p class="logOwnerBadge">
+ <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle}
+ </p>
+ <p class="logOwnerAvatar">
+ <a href="/profile/?guid=${AccountGuid}">
+ {{if includeAvatars && AvatarImage}}
+ <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}">
+ {{else includeAvatars }}
+ <img width="48" height="48" src="/images/default_avatar.jpg">
+ {{/if}}
+ </a></p>
+ <p class="logOwnerStats">
+
+ {{if GeocacheFindCount > 0 }}
+ <img title="Caches Found" src="/images/icons/icon_smile.png"> ${GeocacheFindCount}
+ {{/if}}
+
+ </p>
+ </div>
+ <div class="FloatLeft LogDisplayRight">
+ <div class="HalfLeft LogType">
+ <strong>
+ <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong></div>
+ <div class="HalfRight AlignRight">
+ <span class="minorDetails LogDate">${Visited}</span></div>
+ <div class="Clear LogContent">
+ {{if LatLonString.length > 0}}
+ <strong>${LatLonString}</strong>
+ {{/if}}
+ <p class="LogText">{{html LogText}}</p>
+ {{if Images.length > 0}}
+ <table cellspacing="0" cellpadding="3" class="LogImagesTable">
+ {{tmpl(Images) "tmplCacheLogImages"}}
+ </table>
+ {{/if}}
+
+ <div class="AlignRight">
+ <small><a title="View Log" href="log.aspx?LUID=${LogGuid}" target="_blank">
+ {{if (userInfo.ID==AccountID)}}
+ View / Edit Log / Images
+ {{else}}
+ View Log
+ {{/if}}
+ </a></small>
+ {{if (userInfo.ID==AccountID)}}
+ <small><a title="Upload Image" href="upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small>
+ {{/if}}
+ </div>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </script>
+ <script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl">
+ <tr>
+ <td>
+ <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}">
+ <img title="Photo" alt="Photo" src="/images/icons/16/photo.png">
+ <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span>
+ </a>
+ </td>
+ </tr>
+ </script>
+ <script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl">
+ <span class="LogImgTitle"> ${ $('<div />').text($('<div />').text($('<div />').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink">
+
+ <a target="_blank" href="log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a>
+
+ <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span>
+
+ {{if (Descr && Descr.length > 0) }}
+ <br /><p class="LogImgDescription">${ $('<div />').text($('<div />').text($('<div />').html($item.data.Descr).text()).html()).html() }</p>
+ {{/if}}
+ </script>
+ <script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl">
+ <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}">
+ <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4>
+ <dl>
+ <dt>Original:</dt>
+ <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd>
+ </dl>
+ <dl class="ccu-parse">
+ <dt>Change To:</dt>
+ <dd>
+ <input type="text" max="40" size="35" class="cc-parse-text">
+ <button class="ccu-button ccu-parse">Submit</button>
+ </dd>
+ </dl>
+ <dl class="ccu-parseverify" style="display:none;">
+ <dt>Change To:</dt>
+ <dd>
+ <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span>
+
+ <button class="ccu-button ccu-parseverify-accept">Accept</button> <button class="ccu-button ccu-parseverify-cancel">Cancel</button>
+ </dd>
+ </dl>
+ </div>
+ <div class="Clear"></div>
+
+ </script>
+
+ <script type="text/javascript">
+ <!--
+ var dh, lat, lng, guid;
+
+ dh = 'true';
+
+ lat=null;lng=null;guid=null;
+
+
+ function s2gps(guid) {
+ var w = window.open('sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no');
+ w.focus();
+ }
+
+ function s2phone(wpid) {
+ window.location.href='sendtophone.aspx?gc=' + wpid;
+ }
+
+ function pl(lc) {
+ document.location.href='cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n');
+ }
+ function setNotification(id) {
+ //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'});
+ //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'});
+ }
+ function cmo(id) {
+ //new Effect.Fade(id);
+ Cookie.set('sn', true);
+ }
+ function pp(img) {
+ var w = window.open(img);
+ w.focus();
+ }
+
+ //-->
+ </script>
+ <script language="javascript" type="text/javascript">
+ var map, bounds;
+ var canUpdateFavoriteStatus = true;
+ var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false;
+ var logInitialLoaded = false;
+ var $tfoot = $("#cache_logs_table").find("tfoot");
+ var currentPageIdx = 1, totalPages = 1, pageSize = 10;
+ var isBusy = false;
+
+ var locString = {
+ decrypt: 'Decrypt',
+ encrypt: 'Encrypt'
+ };
+
+ $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle");
+ $("#tmpl_CacheLogImages").template("tmplCacheLogImages");
+ $("#tmpl_CacheLogRow").template("tmplCacheLogRow");
+
+ $(".EncryptDecrypt")
+ .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} })
+ .click(function (e) {
+ e.preventDefault();
+ $("tr.log-row").each(function (i, obj) {
+ var $obj = $(obj);
+ if ($obj.data("encoded") == true) {
+ var lt = $obj.find("p.LogText");
+ //var ltDecoded = $('<div />').html(lt.html()).text();
+ lt.html(convertROTStringWithBrackets(lt.html()));
+ }
+ });
+
+ decryptLogs = !decryptLogs;
+
+ $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
+
+ return false;
+ });
+
+ function appendNewLogs(obj) {
+
+ totalPages = obj.pageInfo.totalPages;
+
+ var $newBody = $(document.createElement("TBODY"));
+
+ $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody);
+
+ $newBody.find("a.tb_images").each(function()
+ {
+ var $this = $(this);
+ $this.fancybox({
+ 'type': 'image',
+ 'titlePosition': 'inside',
+ 'padding': 10,
+ titleFormat: function() { return $this.data('title'); }
+ });
+ });
+
+ $("#cache_logs_table")
+ .append($newBody.children());
+
+ currentPageIdx = obj.pageInfo.idx + 1;
+ pageSize = obj.pageInfo.size;
+ }
+
+ function callLogLoad(hideFooter) {
+ $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs },
+ function (response) {
+ if (response.status == "success") {
+ appendNewLogs(response);
+ if( hideFooter || (totalPages < currentPageIdx) ) {
+ $tfoot.hide();
+ }
+ } else if (response.status == "error" && response.value == "1") {
+ // reload the page since the data had expired.
+ window.location.reload();
+ }
+ isBusy = false;
+ });
+ }
+
+ $("#add_to_favorites").click(function () {
+
+ if (canUpdateFavoriteStatus) {
+ canUpdateFavoriteStatus = false;
+
+ var fv = parseInt($(".favorite-value").text());
+ fv++;
+ $(".favorite-value").text(fv);
+
+ var fr = parseInt($(".favorite-rank").text());
+ fr--;
+ $(".favorite-rank").text(fr);
+
+ $("#pnlNonfavoriteCache").fadeOut("fast", function () {
+ $("#pnlFavoriteCache").fadeIn("fast");
+ });
+
+ $.ajax({
+ type: "POST",
+ cache: false,
+ url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true',
+ success: function () {
+ canUpdateFavoriteStatus = true;
+ gotScore = false;
+ showFavoriteScore();
+ }
+ });
+
+ return false;
+ }
+ });
+
+ $("#remove_from_favorites").click(function () {
+
+ if (canUpdateFavoriteStatus) {
+ canUpdateFavoriteStatus = false;
+
+ var fv = parseInt($(".favorite-value").text());
+ fv--;
+ $(".favorite-value").text(fv);
+
+ var fr = parseInt($(".favorite-rank").text());
+ fr++;
+ $(".favorite-rank").text(fr);
+
+ $("#pnlFavoriteCache").fadeOut("fast", function () {
+ $("#pnlNonfavoriteCache").fadeIn("fast");
+ });
+
+ $.ajax({
+ type: "POST",
+ cache: false,
+ url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false',
+ success: function () {
+ canUpdateFavoriteStatus = true;
+ gotScore = false;
+ showFavoriteScore();
+ }
+ });
+
+ return false;
+ }
+ });
+
+ $(function () {
+
+ // CSP Section
+ if ($("#cspMessage").length) {
+
+ var editLink = $('a[href*="report.aspx"]').attr('href');
+
+ $("#cspMessage").prepend('<P>Please take a moment to check the listing and ensure it is ready to enable. Clicking "Submit for Review" will enable your cache page.</P>');
+ $("#cspMessage").prepend('<P>Once it is enabled, you will receive a confirmation email that it was successfully submitted. It is peak season for cache placement. Your volunteer reviewer will strive to begin the review process within the next 7 days.</P>');
+ $("#cspMessage").prepend('<P>Your cache page has not been reviewed yet. It will not appear in the review queue until you enable it.</P>');
+
+ $("#cspGoBack").click(function (e) {
+ e.preventDefault();
+ window.location = editLink;
+ return false;
+ });
+
+ $("#cspSubmit").click(function (e) {
+ e.preventDefault();
+ $.pageMethod("EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) {
+ var r = JSON.parse(r.d);
+ if (r.success == true) {
+ window.location = '/seek/cache_details.aspx?guid=' + r.guid;
+ } else {
+ alert("There was an error enabling your cache.");
+ }
+ });
+ return false;
+ });
+
+ $("#cspConfirm").change(function() {
+ if ($("#cspConfirm").is(":checked")) {
+ $("#cspSubmit").removeAttr('disabled');
+ $("#cspGoBack").attr('disabled', true);
+ } else {
+ $("#cspSubmit").attr('disabled', true);
+ $("#cspGoBack").removeAttr('disabled');
+ }
+ });
+ }
+
+
+ //override coords
+ if (typeof(userDefinedCoords) != "undefined") {
+ if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) {
+ mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
+ $("#uxLatLon")
+ .data("isOverridden", true)
+ .addClass("myLatLon");
+ } else if (userDefinedCoords.status == "success") {
+ mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
+ } else {
+ $("#uxLatLonLink").contents().unwrap();
+ }
+ } else {
+ $("#uxLatLonLink").contents().unwrap();
+ }
+
+
+ var cacheNoteText = {
+ DefaultText: 'Click to enter a note',
+ ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.',
+ SavingText: 'Please wait, saving your note...'
+ };
+
+
+
+ $("time.timeago").timeago();
+
+ $(".button").button();
+
+ var sn = Cookie.get('sn');
+
+ if ($('#trNotPM').length > 0) {
+ $('#trNotPM').toggle(!sn);
+ }
+
+ $("#cache_note").editInPlace({
+ callback: function (unused, enteredText) {
+ var me = $(this);
+
+ var et = $.trim(enteredText);
+ if (et.length > 500)
+ et = et.substr(0, 500);
+
+ $.pageMethod("SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) {
+ var r = JSON.parse(r.d);
+ if (r.success == true) {
+ if ($.trim(r.note) == "") {
+ $("#cache_note").text(cacheNoteText.DefaultText);
+ } else {
+ $("#cache_note").text(r.note);
+ }
+
+ me.effect('highlight', { color: '#ffb84c' }, 'slow');
+ } else {
+ alert(cacheNoteText.ErrorInSaving);
+ $("#cache_note").text(cacheNoteText.DefaultText);
+ }
+
+ });
+
+ return cacheNoteText.SavingText;
+ }
+ , default_text: cacheNoteText.DefaultText
+ , field_type: "textarea"
+ , textarea_rows: "7"
+ , textarea_cols: "65"
+ , show_buttons: true
+ , bg_over: "#FDEBBB"
+ //, callback_skip_dom_reset: true
+
+ });
+
+ $("#lnk_slippyMap").click(function(e) {
+ e.preventDefault();
+ loadDynamicMap();
+ return false;
+ });
+
+ $(".inplace_field").live("focus", function () {
+ if ($(this).data("created") == null) {
+ $(this).data("created", true)
+ $(this).countable({
+ maxLength: 500
+ });
+ }
+ });
+
+ $("#pcn_help").tipTip({ activation: 'hover', content: 'Enter your own notes here. No other user will be able to access them.' });
+
+ $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
+
+ if ($("#cache_logs_container").length > 0) {
+
+ appendNewLogs(initalLogs);
+
+ if (DetectMobileQuick()) {
+ $("#pnlButtonLoad")
+ .show()
+ .find("a.MobileButton")
+ .click(function (e) {
+ e.preventDefault();
+ callLogLoad(false);
+ return false;
+ })
+ .button();
+ if(!DetectTierTablet()){
+ $("a.MobileButton").addClass("Phone");
+ }
+ } else {
+ $("#pnlLazyLoad").show();
+
+ $(window).endlessScroll({
+ fireOnce: true,
+ fireDelay: 500,
+ bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50,
+ ceaseFire: function(){
+ // stop the scrolling if the last page is reached.
+ return (isLoggedIn == false) || (totalPages < currentPageIdx);
+ },
+ callback: function() {
+ if (!isBusy) {
+
+ isBusy = true;
+ $tfoot.show();
+ callLogLoad(true);
+ }
+ }
+ });
+ }
+ }
+
+ if (!isLoggedIn) {
+ $("#cache_logs_table").find("tfoot").hide();
+ }
+
+ if (mapLatLng != null) {
+
+ $("#uxLatLonLink").qtip({
+ suppress:false,
+ content: buildCacheCoordMenu(),
+ position: {
+ my: 'left top',
+ at: 'right top',
+ adjust: {
+ x: 10, y: -10
+ }
+ },
+ show: {
+ ready: false,
+ event: "click",
+ solo: true
+ }, hide: {
+ event: 'unfocus'
+ },
+ style: {
+ tip: {
+ corner: false
+ },
+ classes: 'ui-tooltip-widget'
+ },
+ events: {
+ show: function () {
+ if ($("#uxLatLon").data("isOverridden")) {
+ $("a.ccu-restore").show();
+ } else {
+ $("a.ccu-restore").hide();
+ }
+
+ if (userDefinedCoords.status != "success") {
+ $("div.ccu-update").hide();
+ } else {
+ $("div.ccu-update").show();
+ }
+ }
+ }
+ }).click(function (e) {
+ e.preventDefault();
+ return false;
+ });
+
+ setStaticMaps();
+ //$("#staticMap").lazyload();
+ }
+ });
+
+ function setStaticMaps() {
+
+ var map = new L.Map('map_preview_canvas', {
+ center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
+ zoom: 10,
+ doubleClickZoom: false,
+ dragging: false,
+ touchZoom: false,
+ scrollWheelZoom: false,
+ attributionControl: false
+ })
+ .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }));
+
+
+ var mapLarge = new L.Map('map_canvas', {
+ center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
+ zoom: 14,
+ doubleClickZoom: true,
+ dragging: true,
+ touchZoom: false,
+ scrollWheelZoom: false,
+ zoomControl: true,
+ attributionControl: false
+ })
+ .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }))
+ .addControl(new L.Control.Scale());
+
+ var tileOptions = {
+ tileUrl: "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg",
+ name: "mpqosm",
+ alt: "MapQuest",
+ //attribution: "Tiles Courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='http://developer.mapquest.com/content/osm/mq_logo.png'>, Map and map data © 2012 <a href=\"http://www.openstreetmap.org\" target='_blank'>OpenStreetMap</a> and contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>. ",
+ subdomains: "1234",
+ tileSize: 256,
+ minZoom: 0,
+ maxZoom: 18
+ };
+
+ map.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
+ mapLarge.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
+
+ var pinIcon = L.Icon.extend({
+ iconSize: new L.Point(20, 23),
+ iconAnchor: new L.Point(10,23),
+ shadowUrl: null
+ });
+
+ var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng),
+ {
+ icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
+ title: mapLatLng.name
+ })
+ .on("click", function () {
+ document.getElementById("uxlrgMap").scrollIntoView(true);
+ return false;
+ });
+
+ var mkA2 = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), {
+ icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
+ clickable: false, zIndexOffset:99, title: mapLatLng.name
+ });
+
+ map.addLayer(mkA);
+ mapLarge.addLayer(mkA2);
+
+ $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({
+ overlayShow: false
+ });
+
+
+ if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) {
+ var llBounds = new L.LatLngBounds();
+
+ for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) {
+ var item = cmapAdditionalWaypoints[x],
+ ll = new L.LatLng(item.lat, item.lng),
+ marker = new L.Marker(ll, {
+ icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + item.type + '.png', iconAnchor: new L.Point(10,23)}),
+ title: item.name,
+ clickable:false
+ });
+
+ llBounds.extend(ll);
+ mapLarge.addLayer(marker);
+ }
+ var bz = mapLarge.getBoundsZoom(llBounds);
+
+ mapLarge.setView(new L.LatLng(mapLatLng.lat, mapLatLng.lng), bz);
+ }
+ }
+
+
+
+ function dht() {
+ try {
+ $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html()));
+ var linkText = (($('#ctl00_ContentBody_lnkDH').attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt');
+ $('#ctl00_ContentBody_lnkDH').text(linkText);
+ $('#ctl00_ContentBody_lnkDH').attr('title', linkText);
+ } catch (e) {
+ alert(e);
+ return false;
+ }
+ return false;
+ }
+
+ function buildCacheCoordMenu() {
+ var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng)
+ $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" );
+
+ var $menu = $("<div></div>");
+
+ $( "#tmpl_CacheCoordinateUpdate" ).tmpl( {
+ ll: [mapLatLng.lat, mapLatLng.lng],
+ ll_formatted: mapLatLng.oldLatLngDisplay
+ } ).appendTo( $menu );
+
+ $menu.find("button.ccu-button").button();
+
+ $menu.delegate("button.ccu-parse", "click", function (e) {
+ e.preventDefault();
+ var $this = $(e.target),
+ $parse =$this.closest('dd').find(".cc-parse-text"),
+ parseCoords = $.trim($parse.val());
+
+ if (parseCoords.length == 0) {
+ alert('Please provide valid coordinates.');
+ } else {
+ $.getJSON("/api/geocode", { parse: parseCoords}, function (response) {
+ if (response.status == "success") {
+ var newLatLng = new LatLon(response.data.lat, response.data.lng);
+
+ // update the displayed coords
+ var dist = curLatLng.rhumbDistanceTo(newLatLng);
+ var bearingTo = curLatLng.rhumbBearingTo(newLatLng);
+ var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N";
+
+ var formats = response.data.formats;
+ // all these finds, make me feel dirty
+ $menu
+ .find("span.ccu-parseverify-coords").text(formats.DM).end()
+ .find("dl.ccu-parse").hide().end()
+ .find("dl.ccu-parseverify").show().end()
+ .find("button.ccu-parseverify-accept")
+ .data("utm", '')
+ .data("dm", formats.DM)
+ .data("lat", response.data.lat)
+ .data("lng", response.data.lng)
+ .end();
+ } else {
+ alert("Sorry unable to parse the coordinates you entered.");
+ }
+ });
+ }
+
+ return false;
+ });
+
+ $menu.delegate("button.ccu-parseverify-accept", "click", function (e) {
+ e.preventDefault();
+ var $this = $(this);
+ // update to webmethod
+ $.pageMethod("SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) {
+ var r = JSON.parse(r.d);
+ if (r.status == "success") {
+ window.location.reload();
+ } else {
+ $("#uxLatLonLink").qtip('hide');
+ }
+
+ });
+
+ return false;
+ });
+
+ $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) {
+ e.preventDefault();
+ $menu
+ .find("input.cc-parse-text").val('').end()
+ .find("dl.ccu-parse").show().end()
+ .find("dl.ccu-parseverify").hide().end();
+ return false;
+ });
+
+ $menu.delegate("a.ccu-restore", "click", function (e) {
+ e.preventDefault();
+
+ $.pageMethod("ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) {
+ var r = JSON.parse(r.d);
+ if (r.status == "success") {
+ window.location.reload();
+ }
+ });
+
+ return false;
+ });
+
+ return $menu;
+ }
+
+ GSPK = window.GSPK || {};
+ GSPK.Selector = {};
+ GSPK.Selector.getSelected = function(){
+ var t = null;
+ if ( window.getSelection ){
+ t = window.getSelection();
+ }else if(document.getSelection){
+ t = document.getSelection();
+ }else if(document.selection){
+ t = document.selection.createRange().text;
+ }
+ return t;
+ }
+
+ try { _gaq.push(['_trackEvent', 'Geocaching', 'CacheDetailsMemberType', 'NotSignedIn', null, true]); } catch(err) { }
+ </script>
+
+
+
+ </div>
+
+
+
+
+ </div>
+
+
+ </section>
+
+ <footer>
+
+ <div class="container">
+
+ <div class="span-24 last FooterTop">
+
+
+
+<div class="LocaleText">
+
+ <strong>Choose Your Language:</strong>
+
+</div>
+<div class="LocaleList">
+
+ <div class="selected-language">
+
+ <a href="#">English▼</a>
+
+ </div>
+ <ul class="language-list">
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Svenska</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Español</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Italiano</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Nederlands</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Català</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">Polski</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">Eesti</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">Norsk, Bokmål</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">한국어</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Magyar</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Română</a></li>
+
+ </ul>
+
+</div>
+<script type="text/javascript">
+
+ jQuery(document).ready(function () {
+ jQuery(".selected-language a").click(function (e) {
+ e.preventDefault();
+ var $loc = jQuery(this).parent().next();
+ jQuery($loc).show().position({
+ of: $loc.parent(),
+ my: "left top",
+ at: "left bottom",
+ offset: "0 0",
+ collision: "fit fit"
+ });
+ jQuery(this).addClass("Expanded");
+ jQuery(document).click(function () {
+ jQuery(".language-list").fadeOut("fast");
+ jQuery(".selected-language a").removeClass("Expanded");
+ });
+ return false;
+ });
+ });
+</script>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ About</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterGlossary" title="Glossary of Terms" href="../about/glossary.aspx">Glossary of Terms</a></li>
+ <li>
+ <a id="ctl00_hlFooterBrochures" title="Brochures" href="../tools/#Guide">Brochures</a></li>
+ <li>
+ <a id="ctl00_hlFooterAbout" title="About Groundspeak" href="../about/groundspeak.aspx">About Groundspeak</a></li>
+ <li>
+ <a id="ctl00_hlFooterVolunteers" title="About Our Volunteers" href="../volunteers/">About Our Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlFooterHistory" title="History" href="../about/history.aspx">History</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ Press</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterNews" title="News Articles" href="../press/">News Articles</a></li>
+ <li>
+ <a id="ctl00_hlFooterMediaFAQs" title="Media FAQs" rel="document" href="../articles/Brochures/footer/FAQ_Media.pdf">Media FAQs</a></li>
+ <li>
+ <a id="ctl00_hlFooterMediaInquiries" title="Media Inquiries" rel="external" href="http://support.groundspeak.com/index.php?pg=request&xCategory=11">Media Inquiries</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-5">
+
+ <p class="FooterHeader">
+ <strong>
+ Questions & Suggestions</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterHelpCenterLink" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
+ <li>
+ <a id="ctl00_hlFooterDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlFooterParksPoliceLink" title="Land Management and Law Enforcement" href="../parksandpolice/">Land Management and Law Enforcement</a></li>
+ <li>
+ <a id="ctl00_hlFooterContactUs" title="Contact Us" href="../contact/">Contact Us</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ Resources</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterTools" accesskey="o" title="Tools and Downloads" href="../tools/">Tools and Downloads</a></li>
+ <li>
+ <a id="ctl00_hlFooterAPIProgram" title="API Program" href="../live/">API Program</a></li>
+ <li>
+ <a id="ctl00_hlFooterBenchmarks" title="Find a Benchmark" href="../mark/">Find a Benchmark</a></li>
+ </ul>
+
+ </div>
+ <div class="span-4 append-3 last">
+
+ <p class="FooterHeader">
+ <strong>
+ Follow Us</strong></p>
+ <ul class="FooterLinks FollowUsLinks">
+ <li><a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts"><img id="ctl00_imgFacebook" title="Facebook" src="../images/home/icon_facebook.png" alt="Facebook" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"><img id="ctl00_imgTwitter" title="Twitter" src="../images/twitter/twitter_icon_white_22.png" alt="Twitter" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlFlickr" title=" Flickr" href="http://www.flickr.com/photos/geocaching_com/"><img id="ctl00_imgFlickr" title="Flickr" src="../images/home/icon_flickr.png" alt="Flickr" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"><img id="ctl00_imgYouTube" title="YouTube" src="../images/home/icon_youtube.png" alt="YouTube" style="border-width:0px;" /></a></li>
+ </ul>
+
+ </div>
+
+ <p class="span-24 last FooterBottom">
+ Copyright
+ © 2000-2012
+ <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
+ All Rights Reserved.<br />
+ <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
+ |
+ <a id="ctl00_hlFooterPrivacy" accesskey="x" title="Privacy Policy" href="../about/privacypolicy.aspx">Privacy Policy</a>
+ |
+ <a id="ctl00_hlFooterLogo" accesskey="l" title="Geocaching Logo Usage Guidelines" href="../about/logousage.aspx">Geocaching Logo Usage Guidelines</a>
+ |
+ <a id="ctl00_hlFooterAPI" accesskey="`" title="API License Agreement" href="../live/api_license_agreement.aspx">API License Agreement</a>
+ |
+ <a id="ctl00_HlFooterStatus" accesskey="`" title="Current Service Status" href="http://status.geocaching.com">Service Status</a></p>
+
+ </div>
+
+
+ </footer>
+ <div class="SkipLinks">
+
+ <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
+
+ </div>
+
+
+
+<script type="text/javascript">
+//<![CDATA[
+var Page_ValidationSummaries = new Array(document.getElementById("ctl00_vsSignInWidgetForm"));
+var Page_Validators = new Array(document.getElementById("ctl00_rfvUsername"), document.getElementById("ctl00_rfvPassword"));
+//]]>
+</script>
+
+<script type="text/javascript">
+//<![CDATA[
+var ctl00_vsSignInWidgetForm = document.all ? document.all["ctl00_vsSignInWidgetForm"] : document.getElementById("ctl00_vsSignInWidgetForm");
+ctl00_vsSignInWidgetForm.headertext = "<h4>Please correct the following issues:</h4>";
+ctl00_vsSignInWidgetForm.validationGroup = "SignInForm";
+var ctl00_rfvUsername = document.all ? document.all["ctl00_rfvUsername"] : document.getElementById("ctl00_rfvUsername");
+ctl00_rfvUsername.controltovalidate = "ctl00_tbUsername";
+ctl00_rfvUsername.errormessage = "Username is a required field; please enter a valid username.";
+ctl00_rfvUsername.display = "Dynamic";
+ctl00_rfvUsername.validationGroup = "SignInForm";
+ctl00_rfvUsername.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
+ctl00_rfvUsername.initialvalue = "";
+var ctl00_rfvPassword = document.all ? document.all["ctl00_rfvPassword"] : document.getElementById("ctl00_rfvPassword");
+ctl00_rfvPassword.controltovalidate = "ctl00_tbPassword";
+ctl00_rfvPassword.errormessage = "Password is a required field; please enter a valid password.";
+ctl00_rfvPassword.display = "Dynamic";
+ctl00_rfvPassword.validationGroup = "SignInForm";
+ctl00_rfvPassword.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
+ctl00_rfvPassword.initialvalue = "";
+//]]>
+</script>
+
+
+<script type="text/javascript">
+//<![CDATA[
+var isLoggedIn = false;
+var userDefinedCoords = {"status":"fail","data":{"isUserDefined":false,"oldLatLngDisplay":"N 37° 21.540' W 122° 01.937'"}};
+userInfo = {ID: 0};
+userToken = 'WQZID4ZFAYC6SULYQF74LYDA3S3BDCRFF42MHAMCQ2FV344K2FX57T5PR5HMIIEYY3CGMUR4ZCJLPZTNFNAGW2TB5YIQR6RFKPTVW2ZNM3FM5APRUY3SDKBHWTW64K6GBBSWW67UP4QLB3IAMCTNJVRWCDBKLLDOGPUFLZA';
+//]]>
+</script>
+<script type="text/javascript">setNotification('ctl00_ContentBody_trNotLoggedIn');</script>
+<script type="text/javascript">
+//<![CDATA[
+initalLogs = {"status":"success", "data": [{"LogID":284793524,"CacheID":3373765,"LogGuid":"28f4aded-353c-4cb8-a8ac-17873b5e136f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"FTF 8am.<br />Woo-Hoo, two TNS cache FTFs in a row. This one was much easier, I just pulled out my really big magnet and sucked the needle right out of the stack! TFTP","Created":"12/21/2012","Visited":"12/21/2012","UserName":"TeamOttlet","MembershipLevel":3,"AccountID":623076,"AccountGuid":"b9f2639c-5ed0-4625-82ed-f7723aad6a24","Email":"","AvatarImage":"b4d5c924-f0b3-4668-866d-0c7eafe6a6ad.jpg","GeocacheFindCount":7971,"GeocacheHideCount":11,"ChallengesCompleted":2,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":284780265,"CacheID":3373765,"LogGuid":"28f7397c-4d68-419d-a78c-d9af48530900","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Publish Listing","LogTypeImage":"24.png","LogText":"Published","Created":"12/21/2012","Visited":"12/21/2012","UserName":"Nomex","MembershipLevel":3,"AccountID":651514,"AccountGuid":"930c9960-afb8-4517-937c-a9256effcdb7","Email":"","AvatarImage":"f2fe44a0-95e7-4e94-b152-f462505ceb79.jpg","GeocacheFindCount":0,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Reviewer","GroupImageUrl":"/images/icon_admin.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 5, "totalRows": 2, "rows": 2 } };
+
+document.getElementById('ctl00_vsSignInWidgetForm').dispose = function() {
+ Array.remove(Page_ValidationSummaries, document.getElementById('ctl00_vsSignInWidgetForm'));
+}
+
+var Page_ValidationActive = false;
+if (typeof(ValidatorOnLoad) == "function") {
+ ValidatorOnLoad();
+}
+
+function ValidatorOnSubmit() {
+ if (Page_ValidationActive) {
+ return ValidatorCommonOnSubmit();
+ }
+ else {
+ return true;
+ }
+}
+ WebForm_AutoFocus('btnSignIn');
+document.getElementById('ctl00_rfvUsername').dispose = function() {
+ Array.remove(Page_Validators, document.getElementById('ctl00_rfvUsername'));
+}
+
+document.getElementById('ctl00_rfvPassword').dispose = function() {
+ Array.remove(Page_Validators, document.getElementById('ctl00_rfvPassword'));
+}
+//]]>
+</script>
+</form>
+ <script type="text/javascript">
+ var browserType = {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ };
+
+ $(function () {
+ // Make the menu system play nice with all browsers:
+ $('ul.Menu li').hover(function () {
+ $(this).addClass('hover');
+ $('ul:first', this).css('visibility', 'visible');
+ }, function () {
+ $(this).removeClass('hover');
+ $('ul:first', this).css('visibility', 'hidden');
+ });
+ if (!isiOS()) {
+ // Constructing a Twitter-esque Login:
+ $(".SignInLink").click(function (e) {
+ e.preventDefault();
+ $("#SignInWidget").toggle();
+ $(".ProfileWidget").toggleClass("WidgetOpen");
+ $(this).blur();
+ $("#ctl00_tbUsername").focus();
+ });
+ $(".SignInCloseLink").click(function () {
+ $("#SignInWidget").toggle();
+ $(".ProfileWidget").toggleClass("WidgetOpen");
+ });
+ }
+ $('.SignedInProfileLink').truncate({
+ width: 120,
+ after: '&hellip;',
+ center: false,
+ addclass: false,
+ addtitle: false
+ });
+
+ // Hide the warning message if the user closed it already
+ if ($.cookie('hide_warning') != null) {
+ $(".WarningMessage").hide();
+ } else {
+ $("#warningCloseButton").click(function () {
+ $('.WarningMessage').hide('blind');
+ $.cookie('hide_warning', 'true', { expires: 1 });
+ });
+ }
+
+ function isiOS() {
+ return (
+ (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
+ );
+ }
+ });
+ </script>
+
+
+ <script id="loc_favPointsScoreDesc" type="text/html">
+ Favorites/Premium Logs
+ </script>
+ <script type="text/javascript" language="javascript">
+ <!--
+
+
+
+ var gotScore = false;
+ var favDropDown = $('.favorite-dropdown');
+ var favContainer = $('.favorite-container');
+
+ function showFavoriteScore() {
+ $('#imgFavoriteScore').attr('src', '/images/loading3.gif');
+
+ $('#uxFavoriteScore').parent().fadeTo(200, .001, function () {
+ $.ajax({
+ type: "POST",
+ cache: false,
+ url: '/datastore/favorites.svc/score?u=' + userToken,
+ success: function (scoreResult) {
+ gotScore = true;
+
+ var score = 0;
+
+ if(scoreResult)
+ score = scoreResult;
+
+ if(score > 100)
+ score = 100;
+
+ $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png');
+ var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim();
+ $('#imgFavoriteScore').attr('alt', pieDesc);
+ $('#imgFavoriteScore').attr('title', pieDesc);
+
+ $('#uxFavoriteScore').parent().fadeTo(1000, 1);
+ $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html());
+ }
+ });
+ });
+ }
+
+
+
+ $(document).bind('mouseup', function (e) {
+ var $clicked = $(e.target);
+
+
+ if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) {
+ favDropDown.hide(1, function () {
+ favContainer.addClass('favorite-container');
+ favContainer.removeClass('favorite-container-open');
+ $('#imgFavoriteArrow').attr('src', '/images/arrow-down.png');
+ });
+ }
+ });
+
+ $('#uxFavContainerLink').click(function () {
+ if ($(favDropDown).is(':visible')) {
+ favDropDown.hide(1, function(){
+ favContainer.addClass('favorite-container');
+ favContainer.removeClass('favorite-container-open');
+ $('#imgFavoriteArrow').attr('src', '/images/arrow-down.png');
+ });
+ }
+ else {
+ if (!gotScore) {
+ showFavoriteScore();
+ }
+
+ favContainer.addClass('favorite-container-open');
+ favContainer.removeClass('favorite-container');
+ $('#imgFavoriteArrow').attr('src', '/images/arrow-up.png');
+ favDropDown.show(1);
+ }
+ });
+ // End -->
+ </script>
+
+
+ <script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-2020240-1']);
+ _gaq.push(['_trackPageview']);
+ (function () {
+ var ga = document.createElement('script');
+ ga.src = ('https:' == document.location.protocol ?
+ 'https://ssl' : 'http://www') +
+ '.google-analytics.com/ga.js';
+ ga.setAttribute('async', 'true');
+ document.documentElement.firstChild.appendChild(ga);
+ })();
+ $(function () {
+ $("a.language").click(function (e) {
+ e.preventDefault();
+ window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang"));
+ });
+ });
+ </script>
+
+
+ <!-- Quantcast Tag -->
+ <div id="Quantcast">
+ <script type="text/javascript">
+ var _qevents = _qevents || [];
+
+ (function () {
+ var elem = document.createElement('script');
+
+ elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
+ elem.async = true;
+ elem.type = "text/javascript";
+ var scpt = document.getElementsByTagName('script')[0];
+ scpt.parentNode.insertBefore(elem, scpt);
+ })();
+ </script>
+ <script type="text/javascript">
+ _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
+ </script>
+ <noscript>
+ <div style="display: none;">
+ <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
+ alt="Quantcast" /></div>
+ </noscript>
+ </div>
+ <!-- End Quantcast tag -->
+
+ <!-- Server: WEB03; Build: Web.HotFix_20121211.1 -->
+</body>
+</html>
diff --git a/tests/res/raw/gc433yc_owner_unpublished.html b/tests/res/raw/gc433yc_owner_unpublished.html new file mode 100644 index 0000000..aa144b0 --- /dev/null +++ b/tests/res/raw/gc433yc_owner_unpublished.html @@ -0,0 +1,2188 @@ +<!DOCTYPE html> +<html class=" js flexbox canvas canvastext webgl no-touch geolocation postmessage no-websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients no-cssreflections csstransforms csstransforms3d csstransitions fontface video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths" lang="en"><script id="bug.surrogate">var urchinTracker=function(){},_gaq={push:function(){try {if(arguments[0][0]=='_link')window.location.href=arguments[0][1]}catch(er){}}},_gat={_createTracker:function(){}, _getTracker:function(){return{__noSuchMethod__:function(){},_link:function(o){if(o)location.href=o;},_linkByPost:function(){return true;},_getLinkerUrl:function(o){return o;},_trackEvent:function(){}}}}; if (document.location.host == 'www.salon.com') {var _ga_ = document.querySelectorAll('script[src$=ga\\.js]')[0], ga_e = document.createEvent('Event'); ga_e.initEvent('load', true, true);_ga_.dispatchEvent(ga_e);}</script><head id="ctl00_Head1"> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta charset="utf-8"> + <!--[if IE]><![endif]--> + <title> + GC433YC Stenarna (Earthcache) in Södermanland, Sweden created by ra_sch +</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site"><meta id="ctl00_ogTitle" property="og:title" content="Geocaching - The Official Global GPS Cache Hunt Site"><meta id="ctl00_ogSiteName" property="og:site_name" content="Geocaching - The Official Global GPS Cache Hunt Site"><meta id="ctl00_ogType" property="og:type" content="website"><meta id="ctl00_ogUrl" property="og:url" content="http://www.geocaching.com/"><meta name="author" content="Groundspeak, Inc."><meta name="DC.creator" content="Groundspeak, Inc."><meta name="Copyright" content="Copyright (c) 2000-2012 Groundspeak, Inc. All Rights Reserved."><!-- Copyright (c) 2000-2012 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world."><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world."><meta id="ctl00_ogDescription" property="og:description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world."><meta http-equiv="imagetoolbar" content="no"><meta name="distribution" content="global"><meta name="MSSmartTagsPreventParsing" content="true"><meta name="rating" content="general"><meta name="revisit-after" content="1 days"><meta name="robots" content="all"><meta http-equiv="X-UA-Compatible" content="IE=8"><link rel="icon" href="http://www.geocaching.com/favicon.ico"><link rel="shortcut icon" href="http://www.geocaching.com/favicon.ico"><link rel="apple-touch-icon" href="http://www.geocaching.com/apple-touch-icon.png"><link id="ctl00_imageSrc" rel="image_src" href="http://www.geocaching.com/preview.png"><meta id="ctl00_ogImage" property="og:image" content="/preview.png"><link rel="stylesheet" type="text/css" media="all" href="gc433yc_files/reset.css"><link rel="stylesheet" type="text/css" media="all" href="gc433yc_files/typography.css"><link rel="stylesheet" type="text/css" media="screen,projection" href="gc433yc_files/grid.css"> + <!--[if lt IE 8]> + <link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/ie.css" /> + <![endif]--> + <link id="uxCssMaster" rel="stylesheet" type="text/css" media="screen,projection" href="gc433yc_files/tlnMasterScreen.css"><link id="uxCssMain" rel="stylesheet" type="text/css" media="all" href="gc433yc_files/tlnMain.css"><link rel="Stylesheet" type="text/css" media="all" href="gc433yc_files/jquery-ui-1.css"><link rel="stylesheet" type="text/css" media="all" href="gc433yc_files/jquery.css"><link rel="stylesheet" type="text/css" media="print" href="gc433yc_files/tlnMasterPrint.css"> + <script type="text/javascript" src="gc433yc_files/modernizr-1.js"></script> + <script type="text/javascript" src="gc433yc_files/jquery_002.js"></script> + <script type="text/javascript" src="gc433yc_files/jquery-ui.js"></script> + <script type="text/javascript" src="gc433yc_files/jquery_003.js"></script> + + + + <link href="gc433yc_files/jquery_004.css" rel="stylesheet" type="text/css"> + <link href="gc433yc_files/jquery_003.css" rel="stylesheet" type="text/css"> + <link href="gc433yc_files/tipTip.css" rel="stylesheet" type="text/css"> + <link href="gc433yc_files/jquery_002.css" rel="stylesheet" type="text/css"> + <!--[if lte IE 8]> + <style type="text/css" media="all"> + legend{ + position: absolute; + top: -.6em; + left: 1em; + line-height: 1.3; + } + fieldset p{ + margin-top:1em; + } + img.CacheNoteHelpImg{ + top:-.2em; + } + </style> + <![endif]--> + <style type="text/css" media="screen,projection"> + #otherSearchOptions li + { + list-style-image: none; + list-style-position: outside; + list-style-type: none; + } + .ff + { + font-family: "Andale Mono" , "Courier New" ,Courier,monospace; + } + .fr + { + margin-top: 1.5em; + float: right; + } + .fl + { + float: left; + } + .clsCell + { + border: 1px solid #c0cee3; + font-size: 80%; + background-color: #fff; + } + .clsResultTitle, .clsResultTitleNoBold + { + color: #0000de; + } + .clsResultDescription + { + color: #333; + } + .clsURL + { + color: #999; + } + a.title:link, a.title:visited, a.title:hover, a.title:active + { + color: #000; + text-decoration: underline; + } + a.title + { + text-align: right; + font-size: 10px; + font-family: arial,sans-serif; + padding: 0 1px 0 0; + } + #mapSizePager a:hover + { + font-weight: bold; + } + #mapSizePager ul + { + width: 100%; + margin: 0; + padding: 0; + list-style: none; + } + #mapSizePager li + { + float: left; + list-style: none; + } + #mapSizePager li a + { + font-family: verdana,sans-serif; + font-size: x-small; + display: block; + margin: 0 2px 0 0; + padding: 4px; + text-decoration: none; + border: solid 1px #c0c0c0; + height: 10px; + min-width: 10px; + cursor: pointer; + } + #mapPrintingNotes + { + width: 280px; + text-align: left; + overflow: auto; + } + .inplace_field { + width:100%; + resize: none; + } + legend.note{ + background:url('../images/icons/16/user_note.png') no-repeat 0 0; + padding-left:18px; + } + legend.warning{ + background:url('../images/icons/16/take_note.png') no-repeat 0 0; + padding-left:18px; + } + fieldset.CacheNote{ + border-color: #e9a24c !important; + background-color:#ffffde; + position:relative; + } + .CacheNoteHelpImg{ + position:relative; + cursor:pointer; + top:-1em; + right:-.75em; + float:right; + } + .InformationWidget h3{ + margin-bottom:.5em; + } + .InformationWidget .AlignRight{ + font-size:.8em; + } + #tiptip_content{ + *background-color:#000; + box-shadow:none; + } + .maxed{ + color:#992a2a; + } + + + span.ccu-parseverify-distance img{ + text-align:center !important; + vertical-align:text-bottom !important; + } + .edit-cache-coordinates{ + text-decoration: none; + color: #000 !important; + background: url(/images/icons/16/edit.png) no-repeat right 0; + padding:2px 20px 2px 0px; + margin-right:4px; + } + .ccc-coord{ + cursor: text; + font-family: Courier New, Sans-Serif; + } + .ccu-update dl { + margin-bottom:.25em; + } + .ccu-update dt{ + float:left; + min-width:90px; + } + .ccu-update .ui-button-text-only .ui-button-text{ + padding:.3em .75em; + } + .ccu-parseverify-coords{ + font-style:italic; + margin-right:.25em; + } + .ccu-parseverify-accept, .ccu-parseverify-cancel{ + margin-top:-5px; + } + .ui-tooltip-widget .ui-tooltip-content{ + border-width:1px; + background-color:#fff; + border-color:#c0cee3; + color:#594a42; + padding:1em; + width:420px; + } + .myLatLon { + border-bottom:2px solid #c0cee3; + font-style:italic; + } + .leaflet-control-attribution{ + padding:3px !important; + } + .leaflet-control-attribution img{ + vertical-align:middle; + } + </style> + <link rel="Stylesheet" type="text/css" media="screen" href="gc433yc_files/CSPScreen.css"> + <link rel="stylesheet" type="text/css" media="all" href="gc433yc_files/leaflet.css"> + <!--[if IE]> + <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/v5/leaflet.ie.css" /> + <![endif]--> + <script type="text/javascript" language="javascript" src="gc433yc_files/leaflet.js"></script> + <script type="text/javascript" src="gc433yc_files/jquery.js"></script> + <script type="text/javascript" src="gc433yc_files/geometa.js"></script> + <script type="text/javascript"> + var userToken = null, + urlParams = {}, + mapLatLng = null, + cmapAdditionalWaypoints = [], + initalLogs = null, totalLogs = 0, includeAvatars = false; + + (function () { + var e, + d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); }, + q = window.location.search.substring(1), + r = /([^&=]+)=?([^&]*)/g; + + while (e = r.exec(q)) { + urlParams[d(e[1])] = d(e[2]); + } + })(); + </script> +<meta name="description" content="Stenarna (GC433YC) was created by ra_sch on 12/21/2012. It's a Not chosen size geocache, with difficulty of 1.5, terrain of 1.5. It's located in Södermanland, Sweden. "><style type="text/css">/** GCTour - Container*/#gctourButtonWrapper { height: 32px !important; padding: 0 !important; position: fixed !important; top: 30px !important; width: 35px !important; background-color: #fff; z-index: 100001 !important; border: 1px solid #333; border-width: 1px 1px 1px 0; border-radius: 0 5px 5px 0; -moz-user-select: none;}#gctourButtonWrapper img { position: relative; top: 8px; left: 8px;}#gctourContainer { background-color: #fff; overflow: hidden; left: -210px; padding: 0 !important; position: fixed !important; top: 30px !important; width: 200px; z-index: 100002 !important; border: 1px solid #333; border-left: 0px; border-radius: 0 5px 5px 0; font-size: 12px; line-height: 1.5;}#gctourContainer .cachelist { width: 100%; margin: 0; padding:0; font-size:80%; list-style-type:none;}#gctourContainer .cachelist li { color:#000; margin:0.5em; padding:3px; width:120px; min-height:44px; list-style-position:inside; border:1pt dashed gray; background-color:#FFF; -moz-background-clip:border; -moz-background-inline-policy:continuous; -moz-background-origin:padding; -moz-border-radius:8px 0 8px 0; border-radius:8px 0 8px 0;}#gctourContainer img.imgShadow { -moz-box-shadow: 0 0 4px 2px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px 2px rgba(0, 0, 0, 0.2); background-color: lightgray;}#gctourContainer img.tourImage { cursor: pointer; margin: 0 2px 0 2px;}/* Styling the placeholder for when the user starts dragging an item */#gctourContainer li.ui-sortable-placeholder { min-height:50px; max-height:80px; width: 90%; background-color: rgba(0, 0, 0, 0.03);}/** GCTour - Grand*/.gctour-grand-default { /* http://www.colorzilla.com/gradient-editor/#a7cfef+0,c9dded+3,ffffff+10;gctour-grand-default * http://css3please.com/ */ background: rgb(167,207,239); /* Old browsers */ background: -moz-linear-gradient(top, rgba(167,207,239,1) 0%, rgba(201,221,237,1) 3px, rgba(255,255,255,1) 10px); /* FF3.6+ */ background: -webkit-linear-gradient(top, rgba(167,207,239,1) 0%,rgba(201,221,237,1) 3px,rgba(255,255,255,1) 10px); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, rgba(167,207,239,1) 0%,rgba(201,221,237,1) 3px,rgba(255,255,255,1) 10px); /* Opera 11.10+ */ background: linear-gradient(top, rgba(167,207,239,1) 0%,rgba(201,221,237,1) 3px,rgba(255,255,255,1) 10px); /* W3C */}.gctour-grand-hover { /* http://www.colorzilla.com/gradient-editor/#ffad32+0,ffd699+3,ffffff+10;gctour-grand-hover */ background: rgb(255,173,50); /* Old browsers */ background: -moz-linear-gradient(top, rgba(255,173,50,1) 0%, rgba(255,214,153,1) 3px, rgba(255,255,255,1) 10px); /* FF3.6+ */ background: -webkit-linear-gradient(top, rgba(255,173,50,1) 0%,rgba(255,214,153,1) 3px,rgba(255,255,255,1) 10px); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, rgba(255,173,50,1) 0%,rgba(255,214,153,1) 3px,rgba(255,255,255,1) 10px); /* Opera 11.10+ */ background: linear-gradient(top, rgba(255,173,50,1) 0%,rgba(255,214,153,1) 3px,rgba(255,255,255,1) 10px); /* W3C */}.gctour-grand-highlight { /* http://www.colorzilla.com/gradient-editor/#ffe000+0,ffee7f+3,ffffff+10;gctour-grand-highlight */ background: rgb(255,224,0); /* Old browsers */ background: -moz-linear-gradient(top, rgba(255,224,0,1) 0%, rgba(255,238,127,1) 3px, rgba(255,255,255,1) 10px); /* FF3.6+ */ background: -webkit-linear-gradient(top, rgba(255,224,0,1) 0%,rgba(255,238,127,1) 3px,rgba(255,255,255,1) 10px); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, rgba(255,224,0,1) 0%,rgba(255,238,127,1) 3px,rgba(255,255,255,1) 10px); /* Opera 11.10+ */ background: linear-gradient(top, rgba(255,224,0,1) 0%,rgba(255,238,127,1) 3px,rgba(255,255,255,1) 10px); /* W3C */}.gctour-grand-active { /* Grün http://www.colorzilla.com/gradient-editor/#3dff32+0,9eff99+3,ffffff+10;gctour-grand-active */ background: rgb(61,255,50); /* Old browsers */ background: -moz-linear-gradient(top, rgba(61,255,50,1) 0%, rgba(158,255,153,1) 3px, rgba(255,255,255,1) 10px); /* FF3.6+ */ background: -webkit-linear-gradient(top, rgba(61,255,50,1) 0%,rgba(158,255,153,1) 3px,rgba(255,255,255,1) 10px); /* Chrome10+,Safari5.1+ */ background: linear-gradient(top, rgba(61,255,50,1) 0%,rgba(158,255,153,1) 3px,rgba(255,255,255,1) 10px); /* W3C */$$$$ background: -o-linear-gradient(top, rgba(61,255,50,1) 0%,rgba(158,255,153,1) 3px,rgba(255,255,255,1) 10px); /* Opera 11.10+ */}.gctour-grand-error { /* http://www.colorzilla.com/gradient-editor/#ff3232+0,ff9999+3,ffffff+10;gctour-grand-error */ background: rgb(255,50,50); /* Old browsers */ background: -moz-linear-gradient(top, rgba(255,50,50,1) 0%, rgba(255,153,153,1) 3px, rgba(255,255,255,1) 10px); /* FF3.6+ */ background: -webkit-linear-gradient(top, rgba(255,50,50,1) 0%,rgba(255,153,153,1) 3px,rgba(255,255,255,1) 10px); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, rgba(255,50,50,1) 0%,rgba(255,153,153,1) 3px,rgba(255,255,255,1) 10px); /* Opera 11.10+ */ background: linear-gradient(top, rgba(255,50,50,1) 0%,rgba(255,153,153,1) 3px,rgba(255,255,255,1) 10px); /* W3C */}/** GCTour Slider*/.gct_scrollbar { background-color:pink; height: 20px; left: 0; position: absolute; top: 0; width: 100%;}.gct_scroller{ background-color:lime; height: 20px; left: 0; position: absolute; top: 0; width: 20px; }/* * GCTour Pop-Up */.gct_popup{ position:absolute; z-index:10; width:172px; height:102px; text-align:center; color:#FF0000; font: 14px Verdana, Arial, Helvetica, sans-serif; background-color:lime; border-radius: 5px;}.gct_popup_header{ border-radius: 5px 5px 0px 0px;}.dialogMask { background-image:url(data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%08%00%00%00%08%08%06%00%00%00%C4%0F%BE%8B%00%00%00%01sRGB%00%AE%CE%1C%E9%00%00%00%06bKGD%00%FF%00%FF%00%FF%A0%BD%A7%93%00%00%00%09pHYs%00%00%0E%C4%00%00%0E%C4%01%95%2B%0E%1B%00%00%00%07tIME%07%DB%03%17%0C%03%0F%8C%CB%E4%8C%00%00%00%19tEXtComment%00Created%20with%20GIMPW%81%0E%17%00%00%00%26IDAT%18%D3c%F8%FF%FF%FF%FFMW%3E%FF%C7E3%FC%87%02%98%20%3A%9F%81%A0%09%B8t%C2%00%C3%20p%03%00%DA%B4%F2%A1%8A%CD%18%A3%00%00%00%00IEND%AEB%60%82); height:100%; left:0; opacity:0.7; position:fixed; top:0; width:100%; z-index:9000000;}.dialogBody { -moz-border-radius:5px; border-radius:5px; background:none repeat scroll 0 0 #fff; border:1px solid #333333; color:#333333; cursor:default; font-family:Arial; font-size:12px; left:50%; margin-left:-250px; margin-top:20px; padding:0 0 1em; position:fixed; text-align:left; top:0; width:600px; z-index:9000010; max-height:85%; min-height:440px; overflow:auto;}.dialogBody p { font-size:12px; font-weight:normal; margin:1em 0;}.header h1 { background-color:#B2D4F3; background-repeat:repeat-x; font-size:110% !important; font-family:Helvetica Neue,Arial,Helvetica,sans-serif; margin-bottom:0.2em; margin-top:0; padding:0.5em; -moz-border-radius: 5px 5px 0 0; border-radius: 5px 5px 0 0; color:#333333; background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEcAAABWCAYAAACdOoshAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oKAwcSHqDAeZMAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAArElEQVR42u3XMQ5AUBRFwU9ESEgIlmn%2F5bMBt9Ap5ixhutNVVTXpa11V3RjeG1prF4aMc2LIOAeGjLNjyDgbhoyzYsg4C4aMM2PIOBOGjDNiyPtgPEM9Ajhw4MCBAwcOHDiCAwcOHDhw4MCBA0dw4MCBAwcOHDhwBAcOHDhw4MCBAweO4MCBAwcOHDhw4AgOHDhw4MCBAwcOHMGBAwcOHDhw4MARHDhw4MD5TQ9jZAyriwnP2QAAAABJRU5ErkJggg%3D%3D)}/*.dialogBody h1 { background-color:#7A7A7A; border-bottom:1px solid #333333; font-size:110%; font-family:Helvetica Neue,Arial,Helvetica,sans-serif; margin-bottom:0.2em; padding:0.5em; -moz-border-radius:5px 5px 0px 0px; border-radius:5px 5px 0px 0px; color:#fff;}*/.dialogHistory { border:1px inset #999999; margin:0 1em 1em; padding-bottom: 1em; max-height: 200px; overflow-y:auto; width:518px; padding-left:1em;}.dialogHistory ul { margin-left:2em;}.dialogHistory li { list-style-type:circle;}.dialogFooter input { -moz-border-radius:3px; border-radius:3px; background:none no-repeat scroll 4px center #EEEEEE; border:1px outset #666666; cursor:pointer; float:right; margin-left:0.5em; padding:3px 5px 5px 20px; min-width:100px; font-size: 12px;}.dialogFooter input:hover { background-color:#f9f9f9;}.dialogContent { padding:0 10px 0 10px;}.dialogMin { min-height:0 !important}#dialogDetails { height:364px; padding:3px; overflow:auto; background-color:#eff4f9; border:1px solid #C0CEE3; -moz-border-radius: 0 5px 5px 0; width:424px; position: absolute; right: 10px;}.dialogList li { font-size:10px; padding:3px; clear:both; list-style-type: none;}.dialogList { margin:0; padding:0}.activeTour { border: 1px solid #C0CEE3; -moz-border-radius: 5px 0 0 5px; border-radius: 5px 0 0 5px; background-color:#eff4f9; padding:1px;}#dialogListContainer { height:374px; overflow:auto; width:146px; position: absolute; left: 10px;}.unselectable { -o-user-select: none; -webkit-user-select: none; -moz-user-select: -none; -khtml-user-select: none; user-select: none;}#cacheList .counter { position:absolute; right:4px; bottom: 0; z-index:0; overflow:hidden; font: normal 24px arial,sans-serif; color: #d5d5d5; text-align:right; text-shadow: 1px 1px 1px #C0C0C0; vertical-align: text-bottom; background-color: transparent; margin-right:0; margin-bottom:0; padding: 0;}0</style><style type="text/css"></style><script type="text/javascript">function s2cgeo(code) {window.open('http://send2.cgeo.org/add.html?cache='+code,'cgeo','height=50,width=50'); }</script><style>@media print, screen and (view-mode:minimized){#ghostery-purple-bubble{display:none}}</style></head> +<body gcvotemarker="3.0c"> + <form name="aspnetForm" method="post" action="cache_details.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68&csp=1" id="aspnetForm" class="csp"> +<div> +<input name="__EVENTTARGET" id="__EVENTTARGET" value="" type="hidden"> +<input name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" type="hidden"> +<input name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="2" type="hidden"> +<input name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTc1MjcwNzgxNg8WAh4EQy5JRCgpWVN5c3RlbS5JbnQ2NCwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BzMzNzYxMzEWAmYPZBYGZg9kFgoCCg8WAh4EVGV4dAViPG1ldGEgbmFtZT0iQ29weXJpZ2h0IiBjb250ZW50PSJDb3B5cmlnaHQgKGMpIDIwMDAtMjAxMiBHcm91bmRzcGVhaywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLiIgLz5kAgsPFgIfAQVHPCEtLSBDb3B5cmlnaHQgKGMpIDIwMDAtMjAxMiBHcm91bmRzcGVhaywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAtLT5kAiEPFgIeBGhyZWYFHX4vY3NzL3Rsbk1hc3RlclNjcmVlbi5jc3M/cj0xZAIiDxYCHwIFFX4vY3NzL3Rsbk1haW4uY3NzP3I9MWQCJw8WAh4HVmlzaWJsZWhkAgEPFgIeBWNsYXNzBQNjc3AWEgIFDxYCHwFkZAIIDxYCHwNnFggCAQ8PFgIeCEltYWdlVXJsBTNodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2ltYWdlcy9kZWZhdWx0X2F2YXRhci5qcGdkZAIDDxYCHwEFaEhlbGxvLCA8YSBocmVmPSIvbXkvZGVmYXVsdC5hc3B4IiB0aXRsZT0iVmlldyBQcm9maWxlIGZvciByYV9zY2giIGNsYXNzPSJTaWduZWRJblByb2ZpbGVMaW5rIj5yYV9zY2g8L2E+ZAIFDw8WAh4LTmF2aWdhdGVVcmwFrwFodHRwczovL3d3dy5nZW9jYWNoaW5nLmNvbS9sb2dpbi9kZWZhdWx0LmFzcHg/UkVTRVQ9WSZyZWRpcj1odHRwJTNhJTJmJTJmd3d3Lmdlb2NhY2hpbmcuY29tJTJmc2VlayUyZmNhY2hlX2RldGFpbHMuYXNweCUzZmd1aWQlM2RmZWUxYWQ1YS1kM2RmLTQ2YjctOWZlMC0zMmViMGQ0NTJiNjglMjZjc3AlM2QxZGQCCw8WAh8BBRA5NTcgQ2FjaGVzIEZvdW5kZAINDxYCHwNnFgICDQ8PFgIfBgVAfi90cmFjay9zZWFyY2guYXNweD9vPTEmdWlkPWRmZDQ0NGQwLTUzN2EtNDlmZi05MGYxLWQ3ZWY5Yjg5MzYwYmRkAhAPDxYCHwNnZGQCLA9kFgQCAw8WAh8BBQdFbmdsaXNoZAIFDxYCHgtfIUl0ZW1Db3VudAIQFiBmD2QWAgIBDw8WCB4PQ29tbWFuZEFyZ3VtZW50BQVlbi1VUx4LQ29tbWFuZE5hbWUFDVNldFRlbXBMb2NhbGUfAQUHRW5nbGlzaB4QQ2F1c2VzVmFsaWRhdGlvbmhkZAIBD2QWAgIBDw8WCB8IBQVkZS1ERR8JBQ1TZXRUZW1wTG9jYWxlHwEFB0RldXRzY2gfCmhkZAICD2QWAgIBDw8WCB8IBQVmci1GUh8JBQ1TZXRUZW1wTG9jYWxlHwEFCUZyYW7Dp2Fpcx8KaGRkAgMPZBYCAgEPDxYIHwgFBXB0LVBUHwkFDVNldFRlbXBMb2NhbGUfAQUKUG9ydHVndcOqcx8KaGRkAgQPZBYCAgEPDxYIHwgFBWNzLUNaHwkFDVNldFRlbXBMb2NhbGUfAQUJxIxlxaF0aW5hHwpoZGQCBQ9kFgICAQ8PFggfCAUFc3YtU0UfCQUNU2V0VGVtcExvY2FsZR8BBQdTdmVuc2thHwpoZGQCBg9kFgICAQ8PFggfCAUFZXMtRVMfCQUNU2V0VGVtcExvY2FsZR8BBQhFc3Bhw7FvbB8KaGRkAgcPZBYCAgEPDxYIHwgFBWl0LUlUHwkFDVNldFRlbXBMb2NhbGUfAQUISXRhbGlhbm8fCmhkZAIID2QWAgIBDw8WCB8IBQVubC1OTB8JBQ1TZXRUZW1wTG9jYWxlHwEFCk5lZGVybGFuZHMfCmhkZAIJD2QWAgIBDw8WCB8IBQVjYS1FUx8JBQ1TZXRUZW1wTG9jYWxlHwEFB0NhdGFsw6AfCmhkZAIKD2QWAgIBDw8WCB8IBQVwbC1QTB8JBQ1TZXRUZW1wTG9jYWxlHwEFBlBvbHNraR8KaGRkAgsPZBYCAgEPDxYIHwgFBWV0LUVFHwkFDVNldFRlbXBMb2NhbGUfAQUFRWVzdGkfCmhkZAIMD2QWAgIBDw8WCB8IBQVuYi1OTx8JBQ1TZXRUZW1wTG9jYWxlHwEFDk5vcnNrLCBCb2ttw6VsHwpoZGQCDQ9kFgICAQ8PFggfCAUFa28tS1IfCQUNU2V0VGVtcExvY2FsZR8BBQntlZzqta3slrQfCmhkZAIOD2QWAgIBDw8WCB8IBQVodS1IVR8JBQ1TZXRUZW1wTG9jYWxlHwEFBk1hZ3lhch8KaGRkAg8PZBYCAgEPDxYIHwgFBXJvLVJPHwkFDVNldFRlbXBMb2NhbGUfAQUIUm9tw6JuxIMfCmhkZAIuD2QWAgIDD2QWAgIBDxYCHwNnFgICAQ8WAh8BBVxZb3VyIGNhY2hlIGhhcyAxIG5vdGUocykgZnJvbSBhIHJldmlld2VyLiA8YSBocmVmPScjY2FjaGVfbG9nc19jb250YWluZXInPlJlYWQgdGhlbSBub3c8L2E+LmQCLw8WAh8EBQxzcGFuLTI0IGxhc3QWAgIBD2QWKgIBD2QWAmYPZBYCAgEPDxYCHwEFB0dDNDMzWUNkZAICDxYCHwEFmgE8YSBocmVmPSIvYWJvdXQvY2FjaGVfdHlwZXMuYXNweCIgdGFyZ2V0PSJfYmxhbmsiIHRpdGxlPSJBYm91dCBDYWNoZSBUeXBlcyI+PGltZyBzcmM9Ii9pbWFnZXMvV3B0VHlwZXMvMTM3LmdpZiIgYWx0PSJFYXJ0aGNhY2hlIiB0aXRsZT0iRWFydGhjYWNoZSIgLz48L2E+ZAIGD2QWBAIBDxYCHwNnZAIGDxYCHwNoZAILD2QWBAIBDxYCHwEFATBkAgUPDxYCHwYFRC9zZWVrL2NhY2hlX2Zhdm9yaXRlZC5hc3B4P2d1aWQ9ZmVlMWFkNWEtZDNkZi00NmI3LTlmZTAtMzJlYjBkNDUyYjY4ZGQCDQ8PFgIfA2hkZAIQDxYCHwNoZAIRDxYCHwNoZAISD2QWDAIDDxYCHgVzdHlsZQUPZGlzcGxheTppbmxpbmU7FgICAQ8WAh8BBRtVVE06IDMzViBFIDY2MjM0NyBOIDY1MjEyMjdkAg0PDxYCHwYFM2NkcGYuYXNweD9ndWlkPWZlZTFhZDVhLWQzZGYtNDZiNy05ZmUwLTMyZWIwZDQ1MmI2OGRkAg8PDxYCHwYFOGNkcGYuYXNweD9ndWlkPWZlZTFhZDVhLWQzZGYtNDZiNy05ZmUwLTMyZWIwZDQ1MmI2OCZsYz01ZGQCEQ8PFgIfBgU5Y2RwZi5hc3B4P2d1aWQ9ZmVlMWFkNWEtZDNkZi00NmI3LTlmZTAtMzJlYjBkNDUyYjY4JmxjPTEwZGQCEw8PFgQfBgVuaHR0cDovL21hcHMuZ29vZ2xlLmNvbS9tYXBzP2Y9ZCZobD1lbiZzYWRkcj00OS43MzMyLDguNTY5NjY3IChIb21lIExvY2F0aW9uKSZkYWRkcj01OC44MDAzNSwxNy44MTAwNShTdGVuYXJuYSkeBlRhcmdldAUGX2JsYW5rZGQCGw9kFggCAQ8PFgQeCUZvcmVDb2xvcgweBF8hU0ICBGRkAgMPDxYEHw0MHw4CBGRkAgUPDxYCHwNnFgIeB29uY2xpY2sFO3MyZ3BzKCdmZWUxYWQ1YS1kM2RmLTQ2YjctOWZlMC0zMmViMGQ0NTJiNjgnKTtyZXR1cm4gZmFsc2U7ZAIHDw8WAh8DZxYCHw8FIHMycGhvbmUoJ0dDNDMzWUMnKTtyZXR1cm4gZmFsc2U7ZAIUDxYCHwNnZAIXD2QWCGYPFgIfA2hkAgEPDxYCHwNoZGQCAg8PFgIfA2hkZAIDDxYCHwNoZAIYD2QWAgIDDw8WAh8BBRNObyBoaW50cyBhdmFpbGFibGUuFgIfDwUNcmV0dXJuIGZhbHNlO2QCGQ8WAh8DaGQCHA8WAh8DaGQCHQ8PFgIfA2hkFgICAw8PFgIfA2hkZAIeDxYCHwNnZAIfDxYCHwNoZAIiD2QWAgIBD2QWBAIBDw8WAh8BBf8DPGlmcmFtZSB0eXBlPSJpZnJhbWUiIHNyYz0iaHR0cDovL2Fkcy5ncm91bmRzcGVhay5jb20vYS5hc3B4P1pvbmVJRD05JlRhc2s9R2V0JlNpdGVJRD0xJlg9J2U1MjJhZjRiNWM2NTQ0ZWViYTY3MmRkZDA2ODk2MTRhJyIgd2lkdGg9IjEyMCIgaGVpZ2h0PSIyNDAiIE1hcmdpbndpZHRoPSIwIiBNYXJnaW5oZWlnaHQ9IjAiIEhzcGFjZT0iMCIgVnNwYWNlPSIwIiBGcmFtZWJvcmRlcj0iMCIgU2Nyb2xsaW5nPSJubyIgc3R5bGU9IndpZHRoOjEyMHB4O0hlaWdodDoyNDBweDsiPjxhIGhyZWY9Imh0dHA6Ly9hZHMuZ3JvdW5kc3BlYWsuY29tL2EuYXNweD9ab25lSUQ9OSZUYXNrPUNsaWNrJjtNb2RlPUhUTUwmU2l0ZUlEPTEiIHRhcmdldD0iX2JsYW5rIj48aW1nIHNyYz0iaHR0cDovL2Fkcy5ncm91bmRzcGVhay5jb20vYS5hc3B4P1pvbmVJRD05JlRhc2s9R2V0Jk1vZGU9SFRNTCZTaXRlSUQ9MSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSIyNDAiIGJvcmRlcj0iMCIgYWx0PSIiIC8+PC9hPjwvaWZyYW1lPmRkAgMPFgIeCWlubmVyaHRtbAUTQWR2ZXJ0aXNpbmcgd2l0aCBVc2QCKQ9kFhYCAw8WAh8DZxYCAgEPDxYCHwYFRS9oaWRlL3dwdGxpc3QuYXNweD9SZWZXcHRJRD1mZWUxYWQ1YS1kM2RmLTQ2YjctOWZl" type="hidden"> +<input name="__VIEWSTATE1" id="__VIEWSTATE1" value="MC0zMmViMGQ0NTJiNjgmRFM9MWRkAgUPFgIfA2dkAgcPDxYGHgZSRFMuSUQLKXZHcm91bmRzcGVhay5XZWIuR1BYLldwdERhdGFTb3VyY2VzLCBUdWNzb24uQ29tbW9uLkxlZ2FjeSwgVmVyc2lvbj0zLjAuNDcyOC4xNjE1MiwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1udWxsAR4HUldQVC5JRCgrBAczMzc2MTMxHwNoZGQCCQ8PFgIfA2dkFgICAQ8PFgQfBgUrL21hcC9kZWZhdWx0LmFzcHg/bGF0PTU4LjgwMDM1JmxuZz0xNy44MTAwNR8DZ2RkAhEPDxYCHwYFGy9zZWVrL25lYXJlc3QuYXNweD91PXJhX3NjaGRkAhUPDxYCHwYFHC9zZWVrL25lYXJlc3QuYXNweD91bD1yYV9zY2hkZAIZD2QWCgIDDw8WAh8GBVYvc2Vlay9uZWFyZXN0LmFzcHg/dHg9YzY2ZjVjZjMtOTUyMy00NTQ5LWI4ZGQtNzU5Y2QyZjE4ZGI4JmxhdD01OC44MDAzNTAmbG5nPTE3LjgxMDA1MGRkAgUPDxYCHwYFWi9zZWVrL25lYXJlc3QuYXNweD90eD1jNjZmNWNmMy05NTIzLTQ1NDktYjhkZC03NTljZDJmMThkYjgmbGF0PTU4LjgwMDM1MCZsbmc9MTcuODEwMDUwJmY9MWRkAgkPDxYCHwYFLi9zZWVrL25lYXJlc3QuYXNweD9sYXQ9NTguODAwMzUwJmxuZz0xNy44MTAwNTBkZAILDw8WAh8GBTIvc2Vlay9uZWFyZXN0LmFzcHg/bGF0PTU4LjgwMDM1MCZsbmc9MTcuODEwMDUwJmY9MWRkAg8PDxYCHwYFSGh0dHA6Ly93d3cud2F5bWFya2luZy5jb20vZGlyZWN0b3J5LmFzcHg/Zj0xJmxhdD01OC44MDAzNTAmbG9uPTE3LjgxMDA1MGRkAhsPFgIfA2hkAh8PDxYCHwYFJi9yZXZpZXdzL2hvdGVscy1jb29yZHMtNTguODAwNCwxNy44MTAxZGQCIw9kFgICAQ8PFgQfAQXCBzxsaT48YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL21hcC9kZWZhdWx0LmFzcHg/bGF0PTU4LjgwMDM1JmxuZz0xNy44MTAwNSIgdGFyZ2V0PSJfYmxhbmsiPkdlb2NhY2hpbmcuY29tIE1hcDwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vbWFwcy5nb29nbGUuY29tL21hcHM/cT1OKzU4JWMyJWIwKzQ4LjAyMStFKzAxNyVjMiViMCs0OC42MDMrKEdDNDMzWUMpKyIgdGFyZ2V0PSJfYmxhbmsiPkdvb2dsZSBNYXBzPC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly93d3cubWFwcXVlc3QuY29tL21hcHMvbWFwLmFkcD9zZWFyY2h0eXBlPWFkZHJlc3MmZm9ybXR5cGU9bGF0bG9uZyZsYXRsb25ndHlwZT1kZWNpbWFsJmxhdGl0dWRlPTU4LjgwMDM1JmxvbmdpdHVkZT0xNy44MTAwNSZ6b29tPTEwIiB0YXJnZXQ9Il9ibGFuayI+TWFwUXVlc3Q8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL21hcHMueWFob28uY29tLyNsYXQ9NTguODAwMzUmbG9uPTE3LjgxMDA1Jnpvb209MTYmcT01OC44MDAzNSwxNy44MTAwNSZjb25mPTEmc3RhcnQ9MSZtdnQ9bSZ0cmY9MCIgdGFyZ2V0PSJfYmxhbmsiPllhaG9vIE1hcHM8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5iaW5nLmNvbS9tYXBzL2RlZmF1bHQuYXNweD92PTImbHZsPTE0JnNwPXBvaW50LjU4LjgwMDM1XzE3LjgxMDA1X0dDNDMzWUMiIHRhcmdldD0iX2JsYW5rIj5CaW5nIE1hcHM8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5vcGVuY3ljbGVtYXAub3JnLz96b29tPTEyJmxhdD01OC44MDAzNSZsb249MTcuODEwMDUiIHRhcmdldD0iX2JsYW5rIj5PcGVuIEN5Y2xlIE1hcHM8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy8/bWxhdD01OC44MDAzNSZtbG9uPTE3LjgxMDA1Jnpvb209MTIiIHRhcmdldD0iX2JsYW5rIj5PcGVuIFN0cmVldCBNYXBzPC9hPjwvbGk+HwNnZGQCJw9kFggCAQ8WAh8BBQ4xIExvZ2dlZCBWaXNpdGQCBw8PFgIfBgVDfi9zZWVrL2NhY2hlX2xvZ2Jvb2suYXNweD9ndWlkPWZlZTFhZDVhLWQzZGYtNDZiNy05ZmUwLTMyZWIwZDQ1MmI2OGRkAggPFgIfA2hkAgkPDxYCHwNoZGQCKg8WAh8BBQR0cnVlZAIrDxYCHwEFSmxhdD01OC44MDAzNTsgbG5nPTE3LjgxMDA1OyBndWlkPSdmZWUxYWQ1YS1kM2RmLTQ2YjctOWZlMC0zMmViMGQ0NTJiNjgnOw0KZAIsDxYCHwEFcXRyeSB7IF9nYXEucHVzaChbJ190cmFja0V2ZW50JywgJ0dlb2NhY2hpbmcnLCAnQ2FjaGVEZXRhaWxzTWVtYmVyVHlwZScsICdQcmVtaXVtJywgbnVsbCwgdHJ1ZV0pOyB9IGNhdGNoKGVycikgeyB9ZAIwDxYCHwNoZAIxD2QWBAIDDxYCHwEFB0VuZ2xpc2hkAgUPFgIfBwIQFiBmD2QWAgIBDw8WCB8IBQVlbi1VUx8JBQ1TZXRUZW1wTG9jYWxlHwEFB0VuZ2xpc2gfCmhkZAIBD2QWAgIBDw8WCB8IBQVkZS1ERR8JBQ1TZXRUZW1wTG9jYWxlHwEFB0RldXRzY2gfCmhkZAICD2QWAgIBDw8WCB8IBQVmci1GUh8JBQ1TZXRUZW1wTG9jYWxlHwEFCUZyYW7Dp2Fpcx8KaGRkAgMPZBYCAgEPDxYIHwgFBXB0LVBUHwkFDVNldFRlbXBMb2NhbGUfAQUKUG9ydHVndcOqcx8KaGRkAgQPZBYCAgEPDxYIHwgFBWNzLUNaHwkFDVNldFRlbXBMb2NhbGUfAQUJxIxlxaF0aW5hHwpoZGQCBQ9kFgICAQ8PFggfCAUFc3YtU0UfCQUNU2V0VGVtcExvY2FsZR8BBQdTdmVuc2thHwpoZGQCBg9kFgICAQ8PFggfCAUFZXMtRVMfCQUNU2V0VGVtcExvY2FsZR8BBQhFc3Bhw7FvbB8KaGRkAgcPZBYCAgEPDxYIHwgFBWl0LUlUHwkFDVNldFRlbXBMb2NhbGUfAQUISXRhbGlhbm8fCmhkZAIID2QWAgIBDw8WCB8IBQVubC1OTB8JBQ1TZXRUZW1wTG9jYWxlHwEFCk5lZGVybGFuZHMfCmhkZAIJD2QWAgIBDw8WCB8IBQVjYS1FUx8JBQ1TZXRUZW1wTG9jYWxlHwEFB0NhdGFsw6AfCmhkZAIKD2QWAgIBDw8WCB8IBQVwbC1QTB8JBQ1TZXRUZW1wTG9jYWxlHwEFBlBvbHNraR8KaGRkAgsPZBYCAgEPDxYIHwgFBWV0LUVFHwkFDVNldFRlbXBMb2NhbGUfAQUFRWVzdGkfCmhkZAIMD2QWAgIBDw8WCB8IBQVuYi1OTx8JBQ1TZXRUZW1wTG9jYWxlHwEFDk5vcnNrLCBCb2ttw6VsHwpoZGQCDQ9kFgICAQ8PFggfCAUFa28tS1IfCQUNU2V0VGVtcExvY2FsZR8BBQntlZzqta3slrQfCmhkZAIOD2QWAgIBDw8WCB8IBQVodS1IVR8JBQ1TZXRUZW1wTG9jYWxlHwEFBk1hZ3lhch8KaGRkAg8PZBYCAgEPDxYIHwgFBXJvLVJPHwkFDVNldFRlbXBMb2NhbGUfAQUIUm9tw6JuxIMfCmhkZAIDDxYCHwEFK1NlcnZlcjogV0VCMTM7IEJ1aWxkOiBXZWIuSG90Rml4XzIwMTIxMjExLjFkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBRtjdGwwMCRDb250ZW50Q1NQJGNzcENvbmZpcm06xL130XjARa21fe+yF8/udheOWQ==" type="hidden"> +</div> + +<script type="text/javascript"> +//<![CDATA[ +var theForm = document.forms['aspnetForm']; +if (!theForm) { + theForm = document.aspnetForm; +} +function __doPostBack(eventTarget, eventArgument) { + if (!theForm.onsubmit || (theForm.onsubmit() != false)) { + theForm.__EVENTTARGET.value = eventTarget; + theForm.__EVENTARGUMENT.value = eventArgument; + theForm.submit(); + } +} +//]]> +</script> + + +<script src="gc433yc_files/WebResource.axd" type="text/javascript"></script> + + +<script src="gc433yc_files/ScriptResource_004.axd" type="text/javascript"></script> +<script src="gc433yc_files/ScriptResource.axd" type="text/javascript"></script> +<script src="gc433yc_files/ScriptResource_003.axd" type="text/javascript"></script> +<script src="gc433yc_files/ScriptResource_002.axd" type="text/javascript"></script> +<script src="gc433yc_files/cachedetails.js" type="text/javascript"></script> +<script src="gc433yc_files/latlng.js" type="text/javascript"></script> + <script type="text/javascript"> +//<![CDATA[ +Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00'); +//]]> +</script> + + <div id="Top" class="SkipLinks"> + + <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a> + <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a> + + </div> + + <!--[if lte IE 6]> + <div class="WarningMessage PhaseOut"> + + <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p> + + </div> + <![endif]--> + + + + <div class="PrintOnly"> + + <p> + <img src="gc433yc_files/logo_print_bw.png" alt="Geocaching.com"></p> + <hr> + + </div> + + <header> + + <div class="container"> + + <h1 class="Logo span-16"> + <a href="http://www.geocaching.com/" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">Geocaching</a></h1> + <div class="ProfileWidget span-8 last"> + + + + <div id="ctl00_divSignedIn"> + + <p class="Avatar NoBottomSpacing"> + <a id="ctl00_hlHeaderAvatar" accesskey="p" title="Your Profile" href="http://www.geocaching.com/my/"><img title="Your Profile" src="gc433yc_files/default_avatar.jpg" alt="" style="border-width:0px;"></a></p> + <p class="SignedInText"> + <strong> + Hello, <a href="http://www.geocaching.com/my/default.aspx" title="View Profile for ra_sch" class="SignedInProfileLink">ra_sch</a></strong> (<a id="ctl00_hlSignOut" accesskey="s" title="Sign Out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fguid%3dfee1ad5a-d3df-46b7-9fe0-32eb0d452b68%26csp%3d1">Sign Out</a>)<br> + <span id="ctl00_litPMLevel">Premium Member</span> + + <strong style="display:block"> + 957 Caches Found</strong> + + </p> + + </div> + + + </div> + + <div class="NavContainer span-24 last"> + <nav id="Navigation"> + + <ul class="Menu"> + <li class=""> + <a id="ctl00_hlNavLearn" accesskey="1" title="Learn" href="http://www.geocaching.com/guide/">Learn ▼</a> + <ul style="visibility: hidden;" class="SubMenu"> + <li> + <a id="ctl00_hlSubNavGeocaching101" accesskey="i" title="Geocaching 101" href="http://www.geocaching.com/guide/">Geocaching 101</a></li> + <li> + <a id="ctl00_hlSubNavGeocaching2Minutes" title="Geocaching in 2 Minutes" href="http://www.geocaching.com/videos/#cat=cat:newbies&vid=-4VFeYZTTYs">Geocaching in 2 Minutes</a></li> + </ul> + </li> + + <li class="" id="ctl00_liNavProfile"> + <a id="ctl00_hlNavProfile" accesskey="2" title="Your Profile" href="http://www.geocaching.com/my/">Your Profile ▼</a> + <ul style="visibility: hidden;" class="SubMenu"> + <li> + <a id="ctl00_hlSubNavQuickView" accesskey="p" title="Quick View" href="http://www.geocaching.com/my/">Quick View</a></li> + <li> + <a id="ctl00_hlSubNavLists" accesskey="q" title="Lists" href="http://www.geocaching.com/my/lists.aspx">Lists</a></li> + <li class="ExtraText"> + <a id="ctl00_hlSubNavGeocaches" accesskey="m" title="Geocaches" class="NoRightPadding" href="http://www.geocaching.com/my/geocaches.aspx">Geocaches</a> + (<a id="ctl00_hlSubNavGeocachesYours" accesskey="y" title="Yours" class="NoSidePadding" href="http://www.geocaching.com/my/owned.aspx">Yours</a>)</li> + <li class="ExtraText"> + <a id="ctl00_hlSubNavProfileTrackables" title="Trackables" class="NoRightPadding" href="http://www.geocaching.com/my/travelbugs.aspx">Trackables</a> + (<a id="ctl00_hlSubNavTrackablesYours" accesskey="8" title="Yours" class="NoSidePadding" href="http://www.geocaching.com/track/search.aspx?o=1&uid=dfd444d0-537a-49ff-90f1-d7ef9b89360b">Yours</a>)</li> + <li> + <a id="ctl00_hlSubNavPocketQueries" accesskey="9" title="Pocket Queries" href="http://www.geocaching.com/pocket/">Pocket Queries</a></li> + <li> + <a id="ctl00_hlSubNavFieldNotes" accesskey="0" title="Field Notes" href="http://www.geocaching.com/my/fieldnotes.aspx">Field Notes</a></li> + <li> + <a id="ctl00_hlSubNavAccount" accesskey="a" title="Account Details" href="http://www.geocaching.com/account/">Account Details</a></li> + </ul> + </li> + <li> + <a id="ctl00_hlNavPlay" accesskey="3" title="Play" href="http://www.geocaching.com/seek/">Play ▼</a> + <ul class="SubMenu"> + <li> + <a id="ctl00_hlSubNavHide" accesskey="d" title="Hide & Seek a Cache" href="http://www.geocaching.com/seek/">Hide & Seek a Cache</a></li> + <li> + <a id="ctl00_hlSubNavLogCache" title="Log a Cache" href="http://www.geocaching.com/my/recentlyviewedcaches.aspx">Log a Cache</a></li> + <li><a id="ctl00_hlSubNavMap" accesskey="/" title="View Geocache Map" href="http://www.geocaching.com/map/">View Geocache Map</a></li> + <li> + <a id="ctl00_hlSubNavTrackables" accesskey="e" title="Find Trackables" href="http://www.geocaching.com/track/">Find Trackables</a></li> + <li> + <a id="ctl00_hlSubNavHelpCenter" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li> + </ul> + </li> + <li> + <a id="ctl00_hlNavCommunity" accesskey="6" title="Community" href="http://www.geocaching.com/forums/">Community ▼</a> + <ul class="SubMenu"> + + <li> + <a id="ctl00_hlSubNavTellaFriend" accesskey="-" title="Tell a Friend" href="http://www.geocaching.com/account/SendReferral.aspx">Tell a Friend</a></li> + + <li><a id="ctl00_hlSubNavVolunteers" accesskey="+" title="Volunteers" href="http://www.geocaching.com/volunteers/">Volunteers</a></li> + <li> + <a id="ctl00_hlSubNavLocal" accesskey="z" title="Local Organizations" href="http://www.geocaching.com/organizations/">Local Organizations</a></li> + <li> + <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" title="Discussion Forums" href="http://www.geocaching.com/forums/">Discussion Forums</a></li> + <li> + <a id="ctl00_hlSubNavBlog" accesskey="b" title="Blog" rel="external" href="http://blog.geocaching.com/">Blog</a></li> + <li> + <a id="ctl00_hlSubNavEvents" accesskey="v" title="Events" href="http://www.geocaching.com/calendar/">Events</a></li> + </ul> + </li> + <li> + <a id="ctl00_hlNavShop" accesskey="4" title="Shop" href="http://shop.geocaching.com/">Shop ▼</a> + <ul class="SubMenu"> + <li> + <a id="ctl00_hlSubNavShop" accesskey="j" title="Shop Geocaching" rel="external" href="http://shop.geocaching.com/">Shop Geocaching</a></li> + <li> + <a id="ctl00_hlSubNavIntlRetailers" title="International Retailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li> + <li> + <a id="ctl00_hlSubNavGPSReviews" accesskey="w" title="GPS Reviews" href="http://www.geocaching.com/reviews/gps">GPS Reviews</a></li> + <li> + <a id="ctl00_hlSubNavGPSGuide" accesskey="k" title="Guide to Buying a GPS Device" href="http://www.geocaching.com/about/buying.aspx">Guide to Buying a GPS Device</a></li> + </ul> + </li> + <li> + <a id="ctl00_hlNavPartnering" accesskey="5" title="Partnering" href="http://www.geocaching.com/travel/">Partnering ▼</a> + <ul class="SubMenu"> + <li> + <a id="ctl00_hlSubNavTravel" title="Travel and GeoTourism" href="http://www.geocaching.com/travel/">Travel and GeoTourism</a></li> + <li> + <a id="ctl00_hlSubNavBrandedPromotions" title="Branded Promotions" href="http://www.geocaching.com/brandedpromotions/">Branded Promotions</a></li> + <li> + <a id="ctl00_hlSubNavEducation" title="Geocaching and Education" href="http://www.geocaching.com/education/">Geocaching and Education</a></li> + <li> + <a id="ctl00_hlSubNavAdvertisingWithUs" title="Advertising with Us" href="http://www.geocaching.com/about/advertising.aspx">Advertising with Us</a></li> + <li> + <a id="ctl00_hlSubNavAPIProgram" title="API Program" href="http://www.geocaching.com/live/apidevelopers/">API Program</a></li> + </ul> + </li> + <li> + <a id="ctl00_hlNavVideos" accesskey="7" title="Videos" href="http://www.geocaching.com/videos/">Videos</a></li> + <li> + <a id="ctl00_hlNavFollowUs" title="Follow Us" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts">Follow Us ▼</a> + <ul class="SubMenu NavSocialMedia"> + <li> + <a id="ctl00_hlSubNavFacebook" title="Facebook" class="SubNavFacebook" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts">Facebook</a></li> + <li> + <a id="ctl00_hlSubNavTwitter" title="Twitter" class="SubNavTwitter" href="http://twitter.com/GoGeocaching">Twitter</a></li> + <li> + <a id="ctl00_hlSubNavFlickr" title="Flickr" class="SubNavFlickr" href="http://www.flickr.com/photos/geocaching_com/">Flickr</a></li> + <li> + <a id="ctl00_hlSubNavYouTube" title="YouTube" class="SubNavYouTube" href="http://www.youtube.com/user/GoGeocaching">YouTube</a></li> + </ul> + </li> + </ul> + + </nav> + <div class="LanguageSelector"> + + +<div class="LocaleText"> + + <strong>Choose Your Language:</strong> + +</div> +<div class="LocaleList"> + + <div class="selected-language"> + + <a href="#">English▼</a> + + </div> + <ul class="language-list"> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl05$uxLocaleItem','')">Svenska</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl06$uxLocaleItem','')">Español</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl07$uxLocaleItem','')">Italiano</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl08$uxLocaleItem','')">Nederlands</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl09$uxLocaleItem','')">Català</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl10$uxLocaleItem','')">Polski</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl11$uxLocaleItem','')">Eesti</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl12$uxLocaleItem','')">Norsk, Bokmål</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl13$uxLocaleItem','')">한국어</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl14$uxLocaleItem','')">Magyar</a></li> + + <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl15$uxLocaleItem','')">Română</a></li> + + </ul> + +</div> +<script type="text/javascript"> + + jQuery(document).ready(function () { + jQuery(".selected-language a").click(function (e) { + e.preventDefault(); + var $loc = jQuery(this).parent().next(); + jQuery($loc).show().position({ + of: $loc.parent(), + my: "left top", + at: "left bottom", + offset: "0 0", + collision: "fit fit" + }); + jQuery(this).addClass("Expanded"); + jQuery(document).click(function () { + jQuery(".language-list").fadeOut("fast"); + jQuery(".selected-language a").removeClass("Expanded"); + }); + return false; + }); + }); +</script> + </div> + </div> + + + </div> + + + </header> + <section id="Content"> + + + <div class="container"> + + <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last"> + + <p> + <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="http://www.geocaching.com/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="http://www.geocaching.com/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span> + </p> + + + + + <div style="display:none;"> + <p> + Your cache has 1 note(s) from a reviewer. <a href="#cache_logs_container">Read them now</a>. + </p> + </div> + + + <div id="cspMessage" class="cspWidget cspWarningWidget"><p>Your cache page has not been reviewed yet. It will not appear in the review queue until you enable it.</p><p>Once + it is enabled, you will receive a confirmation email that it was +successfully submitted. It is peak season for cache placement. Your +volunteer reviewer will strive to begin the review process within the +next 7 days.</p><p>Please take a moment to check the listing and ensure +it is ready to enable. Clicking "Submit for Review" will enable your +cache page.</p> + <p> + <span class="Checkbox" title="Yes, the cache is in place and ready to be found" autocomplete="off"><input id="cspConfirm" name="ctl00$ContentCSP$cspConfirm" type="checkbox"><label for="cspConfirm">Yes, the cache is in place and ready to be found</label></span> + </p> + <p class="NoBottomSpacing"> + <input name="ctl00$ContentCSP$cspSubmit" value="Submit for Review" id="cspSubmit" disabled="disabled" title="Submit for Review" class="cspButton cspPrimaryButton" type="submit"> + <input name="ctl00$ContentCSP$cspGoBack" value="Edit Listing" id="cspGoBack" title="Edit Listing" class="cspButton" type="submit"></p> + </div> + + </div> + + <div id="ctl00_divContentMain" class="span-24 last"> + + + + + <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget"> + + <p> + <a href="#" class="CoordInfoLink"> + <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC433YC</span> + <span class="arrow">▼</span> </a> + </p> + +</div> +<div id="dlgClipboard"> + <input class="TextFormat" type="text"> + <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close"> + x</a> +</div> +<script type="text/javascript"> + $("a.CoordInfoLink").click(function (e) { + e.preventDefault(); + + $("#dlgClipboard") + .show() + .position({ + of: $("a.CoordInfoLink"), + my: "right top", + at: "right bottom", + offset: "0 5" + }) + .find("input") + .val('http://coord.info/' + $('.CoordInfoCode').text()) + .focus() + .select(); + + $(document).mouseup(function (e) { + if ($(e.target).parent("div#dlgClipboard").length == 0) { + $(this).unbind(e); + $("div#dlgClipboard").hide(); + } + }); + + return false; + }); + + +</script> + + <div class="span-17"> + + <div class="span-17 last BottomSpacing" id="cacheDetails"> + <p class="cacheImage"> + <a href="http://www.geocaching.com/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="gc433yc_files/137.gif" alt="Earthcache" title="Earthcache"></a> + </p> + + <h2 class="NoBottomSpacing"> + <span id="ctl00_ContentBody_CacheName">Stenarna</span></h2> + <div class="minorCacheDetails Clear"> + <div id="ctl00_ContentBody_mcd1"> + A cache by <a href="http://www.geocaching.com/profile/?guid=dfd444d0-537a-49ff-90f1-d7ef9b89360b&wid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68&ds=2">ra_sch</a></div> + <div id="ctl00_ContentBody_mcd2"> + Hidden: + 12/21/2012 + + </div> + <div></div> + </div> + </div> + <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-3 BottomSpacing"> + + Difficulty: + <br> + Terrain: + + </div> + + <div id="ctl00_ContentBody_diffTerrStars" class="CacheStarImgs span-2"> + + <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="gc433yc_files/stars1_5.gif" alt="1.5 out of 5"></span> + <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="gc433yc_files/stars1_5.gif" alt="1.5 out of 5"></span> + + </div> + + <div id="ctl00_ContentBody_size" class="CacheSize span-9"> + + <p style="text-align: center;"> + Size: <span class="minorCacheDetails"><img src="gc433yc_files/not_chosen.gif" alt="Size: not chosen" title="Size: not chosen"> <small>(not chosen)</small><span id="GCVote_container"><div name="VoteControlfee1ad5a-d3df-46b7-9fe0-32eb0d452b68" style="float: right;"><div style="white-space: nowrap; font-size: small; padding: 0px; margin: 0px; line-height: 80%;"><table id="gcvoteDetailsfee1ad5a-d3df-46b7-9fe0-32eb0d452b68" style="z-index: 200; position: absolute; visibility: hidden; background-color: rgb(239, 244, 249); border: 1px solid rgb(192, 206, 227); width: auto;"><tr><td style="font-weight: bold;">Verteilung der Bewertungen:</td></tr><tr><td style="text-align: center;"><img src="gc433yc_files/chart.png"></td></tr></table><img style="cursor: pointer;" id="gcvoteStarsfee1ad5a-d3df-46b7-9fe0-32eb0d452b68" title="Durchschnitt (Mittel) 0.0 von 5" alt="Durchschnitt (Mittel) 0.0 von 5" src="gc433yc_files/stars0.gif" align="absmiddle"><small><em style="color: rgb(0, 0, 0); font-weight: normal; font-size: 1.15em;"> (0)</em></small></div><div style="white-space: nowrap; font-size: 1.3em;"><small></small><a title="unbewertet" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=0" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=0" style="background-color: rgb(48, 224, 48); font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=0">?</a><a title="1: schlecht" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=1" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=1" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=1">1</a><span style="color: grey; font-size: 1.4ex;"><a title="1,5: lohnt nicht" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=1.5" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=1.5" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=1.5">½</a></span><a title="2: schwach" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=2" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=2" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=2">2</a><span style="color: grey; font-size: 1.4ex;"><a title="2,5: ok" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=2.5" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=2.5" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=2.5">½</a></span><a title="3: durchschnittlich" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=3" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=3" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=3">3</a><span style="color: grey; font-size: 1.4ex;"><a title="3,5: besser" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=3.5" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=3.5" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=3.5">½</a></span><a title="4: gut" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=4" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=4" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=4">4</a><span style="color: grey; font-size: 1.4ex;"><a title="4,5: fast perfekt" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=4.5" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=4.5" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=4.5">½</a></span><a title="5: großartig" name="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=5" id="GCVoteLinkfee1ad5a-d3df-46b7-9fe0-32eb0d452b68=5" style="font-weight: normal;" href="#fee1ad5a-d3df-46b7-9fe0-32eb0d452b68=5">5</a><img name="GCVoteWaitfee1ad5a-d3df-46b7-9fe0-32eb0d452b68" id="GCVoteWaitfee1ad5a-d3df-46b7-9fe0-32eb0d452b68" style="display: none;" src="gc433yc_files/loading.gif" height="14px" width="14px"></div></div></span></span></p> + + </div> + + + + <div class="span-3 right last"> + + + <div class="favorite right"> + <a id="uxFavContainerLink" href="javascript:void(0);"> + <div class="favorite-container"> + <span class="favorite-value"> + 0</span><br> + Favorites + <img id="imgFavoriteArrow" src="gc433yc_files/arrow-down.png" alt="Expand" title="Expand"> + </div> + </a> + <div class="favorite-dropdown"> + <dl class="top"> + <dt> + <img id="imgFavoriteScore" src="gc433yc_files/loading3.gif" alt="Loading" title="Loading" height="20" width="20"></dt> + <dd> + <span id="uxFavoriteScore"> </span></dd> + </dl> + <dl class="bottom"> + <dt> + <img src="gc433yc_files/view_user.png" alt="View Who Favorited this Cache" title="View Who Favorited this Cache"></dt> + <dd> + <a id="hlViewWhoFavorited" title="View Who Favorited this Cache" href="http://www.geocaching.com/seek/cache_favorited.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68">View Who Favorited this Cache</a></dd> + <dt> + <img src="gc433yc_files/help.png" alt="About Favorites" title="About Favorites"></dt> + <dd> + <a id="hlAboutFavorites" title="About Favorites" href="http://support.groundspeak.com/index.php?pg=kb.page&id=287" target="_blank">About Favorites</a> + </dd> + </dl> + </div> + </div> + + + </div> + + + <p class="Clear"> + </p> + + + + + <div id="ctl00_ContentBody_CacheInformationTable" class="CacheInformationTable"> + <div class="LocationData FloatContainer"> + <div class="span-9"> + <p class="NoBottomSpacing"> + + <span id="uxLatLon" style="font-weight:bold;">N 58° 48.021 E 017° 48.603</span> + + <br> + <span id="ctl00_ContentBody_LocationSubPanel" style="display:inline;"><small> + UTM: 33V E 662347 N 6521227</small> + <br> + </span><small> + <a id="ctl00_ContentBody_lnkConversions" title="Other Conversions" href="http://www.geocaching.com/wpt/?lat=58.80035&lon=17.81005&detail=1" target="_blank">Other Conversions</a> + </small> + </p> + </div> + <div class="span-7 last AlignRight"> + <span id="ctl00_ContentBody_Location">In Södermanland, Sweden</span><br> + <span id="lblDistFromHome"><img src="gc433yc_files/NE.gif" alt="NE" style="vertical-align:text-bottom"> NE 1170.9 km from your home location</span> + </div> + </div> + <div id="Print"> + <p class="NoBottomSpacing"> + <span id="ctl00_ContentBody_uxPrintHeader" style="font-weight:bold;">Print</span>: + <br> + <small> + <a id="ctl00_ContentBody_lnkPrintFriendly" class="lnk" href="http://www.geocaching.com/seek/cdpf.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68" target="_blank"> + <img src="gc433yc_files/print.png" alt="Print" title="Print" height="16" width="16"> <span> + No Logs + </span> + </a> + <a id="ctl00_ContentBody_lnkPrintFriendly5Logs" href="http://www.geocaching.com/seek/cdpf.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68&lc=5" target="_blank">5 Logs</a> + <a id="ctl00_ContentBody_lnkPrintFriendly10Logs" href="http://www.geocaching.com/seek/cdpf.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68&lc=10" target="_blank">10 Logs</a> · + <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="lnk" href="http://maps.google.com/maps?f=d&hl=en&saddr=49.7332,8.569667%20%28Home%20Location%29&daddr=58.80035,17.81005%28Stenarna%29" target="_blank"> + <img src="gc433yc_files/directions.png" alt="Driving Directions" title="Driving Directions" height="16" width="16"> <span> + Driving Directions + </span> + </a></small></p> + <div id="ctl00_ContentBody_uxPrintPDFSection" style="display: none;"> + <p> + <img src="gc433yc_files/pdf_icon.gif" alt="PDF" title="PDF" height="16" width="16"> <small>[PDF:] <a id="ctl00_ContentBody_lnkPDFPrintNoLogs" href="javascript:pl(0);">No Logs</a> <a id="ctl00_ContentBody_lnkPDFPrint5Logs" href="javascript:pl(5);">5 Logs</a> <a id="ctl00_ContentBody_lnkPDFPrint10Logs" href="javascript:pl(10);">10 Logs</a></small></p> + </div> + </div> + <div id="Download"> + <p class="NoBottomSpacing"> + <span id="ctl00_ContentBody_uxDownloadLabel" style="font-weight:bold;">Download</span>: + <small> + <a id="ctl00_ContentBody_lnkDownloads" title="Read about waypoint downloads" href="http://www.geocaching.com/software/default.aspx">Read about waypoint downloads</a> + </small> + </p> + + <p class="NoBottomSpacing TopSpacing"> + <input name="ctl00$ContentBody$btnLocDL" value="LOC waypoint file" id="ctl00_ContentBody_btnLocDL" type="submit"> + | + <input name="ctl00$ContentBody$btnGPXDL" value="GPX file" id="ctl00_ContentBody_btnGPXDL" type="submit"> + | + <input name="ctl00$ContentBody$btnSendToGPS" value="Send to My GPS" onclick="s2gps('fee1ad5a-d3df-46b7-9fe0-32eb0d452b68');return false;" id="ctl00_ContentBody_btnSendToGPS" type="submit"> + | + <input name="ctl00$ContentBody$btnSendToPhone" value="Send to My Phone" onclick="s2phone('GC433YC');return false;" id="ctl00_ContentBody_btnSendToPhone" type="submit"> + | <input name="ctl00$ContentBody$btnSendTocgeo" value="Send to c:geo" onclick="s2cgeo('GC433YC'); return false;" id="ctl00_ContentBody_btnSendTocgeo" type="button"></p> + + </div> + <div style="border-top: 1px solid rgb(192, 206, 227);"><fieldset class="dialogFooter" style="background-color: #EFF4F9;border-color: #C0CEE3 !important;margin-top:0;padding: 0.5em;"><legend class="note" style="background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDGQg7CZXhIq0AAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAD30lEQVQ4yy3M2W8UBRwH8O9vjj2ms92rpUsPutClLdjVQi0WS%2BHBNCq2QCKJhoemLxhr9QlTEhIjPIgxKiRINKSiQEKEBINIsVpSSRpQMLZKCU3tfQBdeyzda3Z3ZnZ%2Bvvj5Az5kWZaLiOwAFAAeZl6z%2BNevNRM%2FnGoB4JEUl5ReeuRNRaY9joKSZFnT%2Fpny5rYRu7tgEsA%2FAMaImSsBuP5P8mb7L25%2BfPvqzuo3D8%2F5qupVQ0sUyoqLLNPgse9Pls%2FevFCua3E5tOedBxWtHX2ykn9HAlDFM39uIFESkjZveuH367X1Xed%2FkZ15%2Fid3e8omrp1%2Brul47z1BklPVb3TFK%2FZ0LE799HVo%2BMz729jQ9eoDR2YkTixtxc3PX%2BP2s7cfnuiorDvUfUNyKGlmThc3tDy5d%2FzAbiLKAkgBEGWnyxXa%2B%2B5TpaAUeYGgJYhSoUBDVxqxMh2MR6MVzoISu%2Bx0qUTkJCKZmaXSptdnouNDfmZWcnpG1RNR1UhEHe4NYcHQ4r6ckQ2Q9UnjAoVeNEesYi0QbpzyVdWPA0gDUAEEsvGVwgfdh4Nrt7dGVifv58dnR%2FypyJRLj6%2BIejrFzWeGr0mIRVQE65%2Fqg4MeW76%2FAIDAc0OO5G%2BXS1aXI66Et9LKrC45kyMDtuJsxFa2721NKgpZDn%2BxOH%2BqzS5c%2F2CrBLaAlVkHBMkm2hyF030XSsa%2F6ija5taENTvbk4H9h%2BKr44P68qUjHq8tKiDPyXD7BZxvz1s3elk2fEESEN49hzvfuFQzJqXmR92e0BZ74KX2jHpiftn27KuWfLS6SFFdtmTx85wmhVASlhAZdfAfl2RiE5RNigL2fnSLFa9W8fCcU%2FiuU%2FUaS1K483RW8pWKqN1ngS2SVa%2FIVk7U3OsIfZ8pfOsLG1kGMjnAbO6akEhx3%2Bf3eon%2BvvqCMnCu0jz5ikuq3GFy01smhm%2FI8Ach%2B0ul4vUbybaQIP75Y5GMDHIWMO8OZ8sb26eImRuYOQSgiixz8%2FjFYw3ywJeBYD4IWpwgiIBdZTZ1gpEBLBNEQEwHzLZv53y72vqJmQPMXARgIxHVAtgy1tNdZ%2FR%2BWrCJZ0XkTBAIAMMCYAl2XvDWZO2ymCtSZY2D9UPEzA4AbgBBAHVs6ttJT4ZTpuB3HK1aG9vUkhB0zQDYyNjcmccJy%2FLW7Fhab08amLwro%2FXYFQmAwcwZIkrC1OP48cMAj%2FSVKU0Hl1BYHvMdPNuvJVZXQMKKR81PBACdmU0iymJXZ4yZ%2F5WYmYnIYGYNorwI1TeGZ142UBKOoLMnAuCRU3VHAESZWQNgEpHFzCYAnYhS%2FwF8odAV4EB4aAAAAABJRU5ErkJggg%3D%3D") no-repeat scroll 0 0 transparent">GCTour</legend><input onclick="return false;" style="float:left;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB9kFFAUXKNiDRngAAAJmSURBVDjLjZPPS1RRFMc%2F972n1qiUpqMRaj8UXPVj46Igw0WrKIKkwEWSCC4jjKLoX5BoU5GUJg6KFrVpFYiBEAouAkH0Of4endHRKSSY53v3tHgzbyxddFb3Xu753O%2F3nHMVwOBw5LpSvBQtFQIggpAJkV1lGCOe53a13Ln7lYNicKg%2FtrWdlIMinU7LenxNPn4e%2Ft0%2F8P7Jv7kGgOu6x48eKWEzmWA9ESMWX2FlbYml1XnimzF%2BplLcuHbzcEW48mlfpOfxPoAWQRBcz2XWnsWetbFtmzl7jpmZWaILUQzD4MrlplBB%2FqFn73q7G7MAC0C0BgHPc6mprvaBotGiEa1ZXl7hw6ch8q0Czp09H%2Fo%2BPtYJjAYArTUArreLbUcR0YgIon2QJ5q8vDzCleUopXB33atv3r6y2u91uFbWgg%2FQVFdXAeIDBH5cbMTZ2AQgXV5GQzzB6LcRU0RbgJuzkGnfQnQeUf4awNnY5FJbGyjFWHc3%2FoMa0cI%2BC0opTp05jVIqqPJGVqEEk4FoHajOAPyNaZoszi%2BSuHUbN7nlXwiFfIVKkVdYSMQwKAJTGcYiUGFlJfkAi9q6WmLJLRpaW4MXdUbRhebm4Gy8pyf8dxsVWIaJPb8AwK%2BpKf4nAgsKMAyTuro61sNhpicmAMgvKuJkfT0AC9PTODs7mRE0EmjNHgsK0zQBaJqeyhRS8aXkWFAwZ2eHFtE8f9HliUgN9x%2F6AMu0Vre2kydKS8vI1T%2B30ns6kEqlsCwznk476cCC4zjtA4OR147jVOV%2BsZ9UXlxMdHLSBxUX09vXs%2BJ5bkfng0cC8AdIoVh%2Ffv3rlAAAAABJRU5ErkJggg%3D%3D)" value="Add to Tour" type="button"><input onclick="return false;" style="float:left;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9oIGQopDsx58QcAAAHySURBVDjLpZNNaxNRFIafuWYRQRCLoCnTQIsfFAwxGFGQLBVRXPqJQfFHCEqd2iIupK6q7lwIfiVZ6EKrVkRGjQUDlRJQIVqoRd0Ixk7aTGbm3uuqTYbUVPDC4XIOnOe897xc%2BM9jtCb5Qm4IsP6hb%2FjI4aODbdV8IacbjUbHcF1X5ws5vdgTWQ5fKpX%2BOjqdTofyZQGJRKL5RsMI3VrrzgClFOVyGQAhRBsolUqtrMA0TYQQGIbRFisq0Fpj2%2FbSRCEEmUyGkddZ6t4co8cn2m28YA0MAVY0GmXL5q0opULyAZ7PX6W7q5cP3yZJ%2Fsriui7A8KICa9C6iJQS3%2FcBOP9wP1oFeCrAkwHd6zbRH9uF487zsj7K7TNTXL9xzYq0LqlSqRCLxbBtm0B57N12CqkVUkkUmu%2FVWRI9e6h5dQ7ejHOAs80dOI6DW69TrVZJJpM8sj2kVsz8rOCrgED5%2BNJnruGwvSdDzV%2Fg7vSlJkAIwZzjMD7%2BjFqthtvrEsiADWvjBFIiteLH7690rdnI5GyR4uci2VUDYReklOxI7wTg45cct96O4CkPN%2FDpW9%2FP7r59lGbe8OLTK3KHJhh78rgJ8DwP0zSX7LscHwu5cOJBGkOs5t30FE9PvkcpFbLxHnCs0%2Fe7o67gK8npyLnW8v0%2F5Gb7fMJoZowAAAAASUVORK5CYII%3D)" value="Print this geocache" type="button"><input onclick="return false;" style="float:left;background-image:url(http://www.geocaching.com/images/icons/coord_update.gif)" value="Move the coordinates" type="button"></fieldset></div></div> + + <fieldset class="DisclaimerWidget"> + <legend class="warning"> + Please note + </legend> + <p class="NoBottomSpacing"> + Use of geocaching.com services is subject to the terms and conditions <a href="http://www.geocaching.com/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>. + </p> + </fieldset> + + + <fieldset class="NotesWidget"> + <legend class="note"> + Personal Cache Note + </legend> + <img src="gc433yc_files/help.png" id="pcn_help" class="CacheNoteHelpImg"> + <p id="cache_note" class="NoBottomSpacing">Click to enter a note</p> + </fieldset> + + <div class="UserSuppliedContent"> + + <span id="ctl00_ContentBody_ShortDescription">Test +</span> + + </div> + + <br> + <div class="UserSuppliedContent"> + + <span id="ctl00_ContentBody_LongDescription">Test</span> + + </div> + + <p> + + + </p> + <p id="ctl00_ContentBody_hints"> + <strong> + Additional Hints</strong> + (<a id="ctl00_ContentBody_lnkDH" title="Decrypt" onclick="return false;" href="#">No hints available.</a>)</p> + <div id="div_hint" class="span-8 WrapFix"> + </div> + <div id="dk" style="display: block;" class="span-9 last"> + <span id="ctl00_ContentBody_EncryptionKey" class="right"></span> + </div> + <div class="Clear"> + </div> + + </div> + + + <div class="span-6 prepend-1 last"> + + +<div class="CacheDetailNavigationWidget NoPrint"> + + <h3 class="WidgetHeader"> + Navigation + </h3> + <div class="WidgetBody"> + + <ul class="CacheDetailsNavLinks"> + <li><a href="http://www.geocaching.com/seek/log.aspx?ID=3376131" class="lnk"><img src="gc433yc_files/write_log.png"> <span>Log your visit</span></a></li> +<li><a href="http://www.geocaching.com/my/watchlist.aspx?w=3376131" class="lnk"><img src="gc433yc_files/watch.png"> <span>Watch Listing</span></a></li> +<li><a href="http://www.geocaching.com/hide/report.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68" class="lnk"><img src="gc433yc_files/edit.png"> <span>Edit Listing</span></a></li> +<li><a href="http://www.geocaching.com/hide/attributes.aspx?WptID=3376131" class="lnk"><img src="gc433yc_files/edit_attributes.png"> <span>Edit Attributes</span></a></li> +<li><a href="http://www.geocaching.com/hide/wptlist.aspx?RefWptID=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68&DS=1" class="lnk"><img src="gc433yc_files/waypoints.png"> <span>Waypoints</span></a></li> +<li><a href="http://www.geocaching.com/seek/upload.aspx?id=3376131" class="lnk"><img src="gc433yc_files/photo.png"> <span>Upload Images</span></a></li> +<li><a href="http://www.geocaching.com/seek/log.aspx?ID=3376131&LogType=5" class="lnk"><img src="gc433yc_files/archive.png"> <span>Archive Listing</span></a></li> +<li><a href="http://www.geocaching.com/seek/log.aspx?ID=3376131&LogType=23" class="lnk"><img src="gc433yc_files/enable.png"> <span>Enable Listing</span></a></li> +<li><a href="http://www.geocaching.com/bookmarks/ignore.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68&WptTypeID=137" class="lnk"><img src="gc433yc_files/ignore.png"> <span>Ignore Listing</span></a></li> +<li><a href="http://www.geocaching.com/bookmarks/mark.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68&WptTypeID=137" class="lnk"><img src="gc433yc_files/bookmark_list.png"> <span>Bookmark Listing</span></a></li> + + </ul> + + </div> + + +</div> + + + + + + <div id="map_preview_canvas" class="TopSpacing leaflet-container leaflet-fade-anim" style="width: 228px; height: 175px; position: relative;"><div style="left: 0px; top: 0px;" class="leaflet-map-pane"><div class="leaflet-tile-pane"><div class="leaflet-layer"><img src="gc433yc_files/303_002.jpg" style="width: 256px; height: 256px; left: -55px; top: -187px;" class="leaflet-tile leaflet-tile-loaded"><img src="gc433yc_files/303.jpg" style="width: 256px; height: 256px; left: 201px; top: -187px;" class="leaflet-tile leaflet-tile-loaded"><img src="gc433yc_files/304_002.jpg" style="width: 256px; height: 256px; left: -55px; top: 69px;" class="leaflet-tile leaflet-tile-loaded"><img src="gc433yc_files/304.jpg" style="width: 256px; height: 256px; left: 201px; top: 69px;" class="leaflet-tile leaflet-tile-loaded"></div></div><div class="leaflet-objects-pane"><div class="leaflet-shadow-pane"></div><div class="leaflet-overlay-pane"></div><div class="leaflet-marker-pane"><img title="Stenarna" style="margin-left: -10px; margin-top: -23px; opacity: 1; left: 114px; top: 88px; z-index: 88;" class="leaflet-marker-icon leaflet-clickable" src="gc433yc_files/137.png"></div><div class="leaflet-popup-pane"></div></div></div><div class="leaflet-control-container"><div class="leaflet-top leaflet-left"><div class="leaflet-control-zoom leaflet-control"><a title="Zoom in" href="#" class="leaflet-control-zoom-in"></a><a title="Zoom out" href="#" class="leaflet-control-zoom-out"></a></div></div><div class="leaflet-top leaflet-right"></div><div class="leaflet-bottom leaflet-left"></div><div class="leaflet-bottom leaflet-right"><div class="leaflet-control-attribution leaflet-control"><a href="http://www.geocaching.com/about/maps.aspx#leaflet" target="_blank">About our maps</a></div></div></div></div> + + + + <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing"> + + <h3 class="WidgetHeader"> + Attributes</h3> + <div class="WidgetBody"> + <img src="gc433yc_files/wheelchair-no.gif" alt="not wheelchair accessible" title="not wheelchair accessible" height="30" width="30"> <img src="gc433yc_files/available-yes.gif" alt="available 24-7" title="available 24-7" height="30" width="30"> <img src="gc433yc_files/scenic-yes.gif" alt="scenic view" title="scenic view" height="30" width="30"> <img src="gc433yc_files/restrooms-yes.gif" alt="restrooms available" title="restrooms available" height="30" width="30"> <img src="gc433yc_files/attribute-blank.gif" alt="blank" title="blank" height="30" width="30"> <img src="gc433yc_files/attribute-blank.gif" alt="blank" title="blank" height="30" width="30"> <p class="NoBottomSpacing"><small><a href="http://www.geocaching.com/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p> + </div> + + </div> + + + <div id="ctl00_ContentBody_uxBanManWidget" class="CacheDetailPageAds clear"> + + <div id="ctl00_ContentBody_divContentSide"> + + <p class="NoBottomSpacing"> + <span id="ctl00_ContentBody_ADModules_09"><iframe type="iframe" src="gc433yc_files/a.html" marginwidth="0" marginheight="0" hspace="0" vspace="0" style="width:120px;Height:240px;" frameborder="0" height="240" scrolling="no" width="120"><a + +href="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Click&;Mode=HTML&SiteID=1" + target="_blank"><img +src="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Get&Mode=HTML&SiteID=1" + width="120" height="240" border="0" alt="" /></a></iframe></span> + </p> + <p class="AlignCenter"> + <small><a href="http://www.geocaching.com/about/advertising.aspx" id="ctl00_ContentBody_advertisingWithUs" title="Advertising with Us">Advertising with Us</a></small></p> + + </div> + +</div> + + + + <div class="GoogleAds AlignCenter BottomSpacing"> + </div> + <div class="clear"> + </div> + + <span id="ctl00_ContentBody_lnkTravelBugs"></span> + + +<div class="CacheDetailNavigationWidget"> + + <h3 class="WidgetHeader"> + <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span> + </h3> + <div class="WidgetBody"> + + + + <div class="TopSpacing"> + + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory">View past Trackables</a></p> + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="http://www.geocaching.com/track/default.aspx">What are Trackable Items?</a></p> + </div> + + + </div> + + +</div> + + + + + </div> + + + <div id="ctl00_ContentBody_bottomSection" class="span-24 last"> + + <p> + <span id="ctl00_ContentBody_WaypointsInfo" style="font-weight:bold;">Additional Waypoints</span> <span id="ctl00_ContentBody_addEditWptLink">(<a id="ctl00_ContentBody_uxAddEditWaypoints" href="http://www.geocaching.com/hide/wptlist.aspx?RefWptID=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68&DS=1">Add / Edit waypoints</a>)</span> + <br> + No additional waypoints to display. + + </p> + + <div id="uxlrgMap" class="fr"> + + <div class="PageBreakBefore"> + </div> + <div class="CDMapWidget"> + <p class="WidgetHeader NoBottomSpacing"> + <a id="ctl00_ContentBody_uxViewLargerMap" title="View Larger Map" href="http://www.geocaching.com/map/default.aspx?lat=58.80035&lng=17.81005" target="_blank">View Larger Map</a> + </p> + + <div class=" leaflet-container leaflet-fade-anim" id="map_canvas" style="width: 325px; height: 325px; position: relative;"><div style="left: 0px; top: 0px;" class="leaflet-map-pane"><div class="leaflet-tile-pane"><div class="leaflet-layer"><img src="gc433yc_files/4864.jpg" style="width: 256px; height: 256px; left: 20px; top: -139px;" class="leaflet-tile leaflet-tile-loaded"><img src="gc433yc_files/4865.jpg" style="width: 256px; height: 256px; left: 20px; top: 117px;" class="leaflet-tile leaflet-tile-loaded"><img src="gc433yc_files/4864_002.jpg" style="width: 256px; height: 256px; left: -236px; top: -139px;" class="leaflet-tile leaflet-tile-loaded"><img src="gc433yc_files/4864_003.jpg" style="width: 256px; height: 256px; left: 276px; top: -139px;" class="leaflet-tile leaflet-tile-loaded"><img src="gc433yc_files/4865_003.jpg" style="width: 256px; height: 256px; left: -236px; top: 117px;" class="leaflet-tile leaflet-tile-loaded"><img src="gc433yc_files/4865_002.jpg" style="width: 256px; height: 256px; left: 276px; top: 117px;" class="leaflet-tile leaflet-tile-loaded"></div></div><div class="leaflet-objects-pane"><div class="leaflet-shadow-pane"></div><div class="leaflet-overlay-pane"></div><div class="leaflet-marker-pane"><img title="Stenarna" style="margin-left: -10px; margin-top: -23px; opacity: 1; left: 162px; top: 162px; z-index: 261;" class="leaflet-marker-icon " src="gc433yc_files/137.png"></div><div class="leaflet-popup-pane"></div></div></div><div class="leaflet-control-container"><div class="leaflet-top leaflet-left"><div class="leaflet-control-zoom leaflet-control"><a title="Zoom in" href="#" class="leaflet-control-zoom-in"></a><a title="Zoom out" href="#" class="leaflet-control-zoom-out"></a></div></div><div class="leaflet-top leaflet-right"></div><div class="leaflet-bottom leaflet-left"><div class="leaflet-control-scale leaflet-control"><div style="width: 30px;" class="leaflet-control-scale-line">200 m</div><div style="width: 52px;" class="leaflet-control-scale-line">1000 ft</div></div></div><div class="leaflet-bottom leaflet-right"><div class="leaflet-control-attribution leaflet-control"><a href="http://www.geocaching.com/about/maps.aspx#leaflet" target="_blank">About our maps</a></div></div></div></div> + <p class="WidgetFooter"> + <a id="ctl00_ContentBody_uxNotesAboutPrinting" href="#mapPrintingNotes" class="NoPrint">Notes about Printing Maps</a></p> + </div> + <div style="display: none;"> + <div id="mapPrintingNotes"> + To print the map in Firefox and Opera, enable background images in the print dialog. + <a href="#dlgMapPrintWarning" class="dialog" onclick="$.fancybox.close()"> + Close + </a> + </div> + </div> + +</div> + + <p class="NoPrint"> + <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span> + <br> + <span id="ctl00_ContentBody_FindText"></span> + </p> + <ul class="NoPrint"> + <li> + ...other caches + <a id="ctl00_ContentBody_uxFindLinksHiddenByThisUser" href="http://www.geocaching.com/seek/nearest.aspx?u=ra_sch">hidden</a> + or + <a id="ctl00_ContentBody_uxFindLinksFoundByThisUser" href="http://www.geocaching.com/seek/nearest.aspx?ul=ra_sch">found</a> + by this user + </li> + + <li> + ...nearby <a id="ctl00_ContentBody_uxFindLinksNearbyCachesOfType" href="http://www.geocaching.com/seek/nearest.aspx?tx=c66f5cf3-9523-4549-b8dd-759cd2f18db8&lat=58.800350&lng=17.810050">caches of this type</a>, + <a id="ctl00_ContentBody_uxFindLinksNearbyNotFound" href="http://www.geocaching.com/seek/nearest.aspx?tx=c66f5cf3-9523-4549-b8dd-759cd2f18db8&lat=58.800350&lng=17.810050&f=1">that I haven't found</a> + </li> + <li> + ...all nearby <a id="ctl00_ContentBody_uxFindLinksAllNearbyCaches" href="http://www.geocaching.com/seek/nearest.aspx?lat=58.800350&lng=17.810050">caches</a>, + <a id="ctl00_ContentBody_uxFindLinksAllNearbyNotFound" href="http://www.geocaching.com/seek/nearest.aspx?lat=58.800350&lng=17.810050&f=1">that I haven't found</a> + </li> + <li> + ...all nearby <a id="ctl00_ContentBody_uxFindLinksWaymarking" href="http://www.waymarking.com/directory.aspx?f=1&lat=58.800350&lon=17.810050">waymarks on Waymarking.com</a> + </li> + + + <li> + ...nearby <a id="ctl00_ContentBody_uxFindLinksHotels" href="http://www.geocaching.com/reviews/hotels-coords-58.8004,17.8101">Hotels</a> + </li> + </ul> + <p class="NoPrint"> + <span id="ctl00_ContentBody_uxMapLinkHeader" style="font-weight:bold;">For online maps...</span> + </p> + <span class="NoPrint"> + +<ul> + <span id="ctl00_ContentBody_MapLinks_MapLinks"><li><a href="http://www.geocaching.com/map/default.aspx?lat=58.80035&lng=17.81005" target="_blank">Geocaching.com Map</a></li><li><a href="http://maps.google.com/maps?q=N+58%c2%b0+48.021+E+017%c2%b0+48.603+%28GC433YC%29+" target="_blank">Google Maps</a></li><li><a href="http://www.mapquest.com/maps/map.adp?searchtype=address&formtype=latlong&latlongtype=decimal&latitude=58.80035&longitude=17.81005&zoom=10" target="_blank">MapQuest</a></li><li><a href="http://maps.yahoo.com/#lat=58.80035&lon=17.81005&zoom=16&q=58.80035,17.81005&conf=1&start=1&mvt=m&trf=0" target="_blank">Yahoo Maps</a></li><li><a href="http://www.bing.com/maps/default.aspx?v=2&lvl=14&sp=point.58.80035_17.81005_GC433YC" target="_blank">Bing Maps</a></li><li><a href="http://www.opencyclemap.org/?zoom=12&lat=58.80035&lon=17.81005" target="_blank">Open Cycle Maps</a></li><li><a href="http://www.openstreetmap.org/?mlat=58.80035&mlon=17.81005&zoom=12" target="_blank">Open Street Maps</a></li></span> +</ul> + + </span> + <p class="NoPrint"> + + </p> + + <div class="InformationWidget Clear"> + <h3> + 1 Logged Visit</h3> + <div role="button" class="EncryptDecrypt ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-secondary"><span class="ui-button-text"> + <a href="#" class="decrypt-link">Decrypt</a> + </span><span class="ui-button-icon-secondary ui-icon ui-icon-arrowreturnthick-1-w"></span></div> + <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="gc433yc_files/18.png" alt="Post Reviewer Note" title="Post Reviewer Note"> 1 </p></span> + <p class="HalfLeft"> + <a id="ctl00_ContentBody_uxLogbookLink" href="http://www.geocaching.com/seek/cache_logbook.aspx?guid=fee1ad5a-d3df-46b7-9fe0-32eb0d452b68">View Logbook</a> + </p> + <p class="NoBottomSpacing AlignRight"> + <span class="Warning">**Warning!</span> <a href="http://www.geocaching.com/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links. + </p> + </div> + + <div id="cache_logs_container"> + <table id="cache_logs_table" class="LogsTable NoBottomSpacing"> + <tbody> + <tr class="log-row" data-encoded="false"> <td> <div class="FloatLeft LogDisplayLeft"> <p class="logOwnerProfileName"> <strong><a id="143568283" href="http://www.geocaching.com/profile/?guid=dfd444d0-537a-49ff-90f1-d7ef9b89360b">ra_sch</a></strong></p> <p class="logOwnerBadge"> <img title="Premium Member" src="gc433yc_files/prem_user.gif">Premium Member </p> <p class="logOwnerAvatar"> <a href="http://www.geocaching.com/profile/?guid=dfd444d0-537a-49ff-90f1-d7ef9b89360b"> </a></p> <p class="logOwnerStats"> <img title="Caches Found" src="gc433yc_files/icon_smile.png"> 957 </p> </div> <div class="FloatLeft LogDisplayRight"> <div class="HalfLeft LogType"> <strong> <img title="Post Reviewer Note" alt="Post Reviewer Note" src="gc433yc_files/18.png"> Post Reviewer Note</strong></div> <div class="HalfRight AlignRight"> <span class="minorDetails LogDate">12/21/2012</span></div> <div class="Clear LogContent"> <p class="LogText">test</p> <div class="AlignRight"> <small><a title="View Log" href="http://www.geocaching.com/seek/log.aspx?LUID=c5548283-9e9b-4dfd-bee3-bc4a2b17e1db" target="_blank"> + + View / Edit Log / Images + </a></small> <small><a title="Upload Image" href="http://www.geocaching.com/seek/upload.aspx?LID=284810941" target="_blank">Upload Image</a></small> </div> </div> </div> </td> </tr></tbody> + <tfoot style="display: none;"> + <tr> + <td class="AlignCenter"> + <div id="pnlLazyLoad" style=""> + <img src="gc433yc_files/loading2.gif" class="StatusIcon" alt="Loading"> + Loading Cache Logs... + </div> + <div id="pnlButtonLoad" style="display: none;"> + <a class="MobileButton"> + Load More Logs...</a> + </div> + </td> + </tr> + </tfoot> + </table> + </div> + <p> + <small> + Current Time: <time datetime="2012-12-21T11:14:37Z">12/21/2012 11:14:37 (UTC-08:00) Pacific Time (US & Canada) (19:14 GMT)</time><br>Last Updated: <time title="2012-12-21T19:14:41Z" class="timeago" datetime="2012-12-21T19:14:41Z">about a minute ago</time> on 12/21/2012 11:14:41 (UTC-08:00) Pacific Time (US & Canada) (19:14 GMT) <br>Last Found: Never<br><span class="Warning">This cache has not been published yet.</span><br>Rendered From:Unknown<br>Coordinates are in the WGS84 datum + </small> + </p> + + + </div> + <script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl"> + <tr class="log-row" data-encoded="${IsEncoded}" > + <td> + <div class="FloatLeft LogDisplayLeft" > + <p class="logOwnerProfileName"> + <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong></p> + <p class="logOwnerBadge"> + <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle} + </p> + <p class="logOwnerAvatar"> + <a href="/profile/?guid=${AccountGuid}"> + {{if includeAvatars && AvatarImage}} + <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}"> + {{else includeAvatars }} + <img width="48" height="48" src="/images/default_avatar.jpg"> + {{/if}} + </a></p> + <p class="logOwnerStats"> + + {{if GeocacheFindCount > 0 }} + <img title="Caches Found" src="/images/icons/icon_smile.png"> ${GeocacheFindCount} + {{/if}} + + </p> + </div> + <div class="FloatLeft LogDisplayRight"> + <div class="HalfLeft LogType"> + <strong> + <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong></div> + <div class="HalfRight AlignRight"> + <span class="minorDetails LogDate">${Visited}</span></div> + <div class="Clear LogContent"> + {{if LatLonString.length > 0}} + <strong>${LatLonString}</strong> + {{/if}} + <p class="LogText">{{html LogText}}</p> + {{if Images.length > 0}} + <table cellspacing="0" cellpadding="3" class="LogImagesTable"> + {{tmpl(Images) "tmplCacheLogImages"}} + </table> + {{/if}} + + <div class="AlignRight"> + <small><a title="View Log" href="log.aspx?LUID=${LogGuid}" target="_blank"> + {{if (userInfo.ID==AccountID)}} + View / Edit Log / Images + {{else}} + View Log + {{/if}} + </a></small> + {{if (userInfo.ID==AccountID)}} + <small><a title="Upload Image" href="upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small> + {{/if}} + </div> + </div> + </div> + </td> + </tr> + </script> + <script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl"> + <tr> + <td> + <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}"> + <img title="Photo" alt="Photo" src="/images/icons/16/photo.png"> + <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span> + </a> + </td> + </tr> + </script> + <script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl"> + <span class="LogImgTitle"> ${ $('<div />').text($('<div />').text($('<div />').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink"> + + <a target="_blank" href="log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a> + + <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span> + + {{if (Descr && Descr.length > 0) }} + <br /><p class="LogImgDescription">${ $('<div />').text($('<div />').text($('<div />').html($item.data.Descr).text()).html()).html() }</p> + {{/if}} + </script> + <script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl"> + <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}"> + <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4> + <dl> + <dt>Original:</dt> + <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd> + </dl> + <dl class="ccu-parse"> + <dt>Change To:</dt> + <dd> + <input type="text" max="40" size="35" class="cc-parse-text"> + <button class="ccu-button ccu-parse">Submit</button> + </dd> + </dl> + <dl class="ccu-parseverify" style="display:none;"> + <dt>Change To:</dt> + <dd> + <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span> + + <button class="ccu-button ccu-parseverify-accept">Accept</button> <button class="ccu-button ccu-parseverify-cancel">Cancel</button> + </dd> + </dl> + </div> + <div class="Clear"></div> + + </script> + + <script type="text/javascript"> + <!-- + var dh, lat, lng, guid; + + dh = 'true'; + + lat=58.80035; lng=17.81005; guid='fee1ad5a-d3df-46b7-9fe0-32eb0d452b68'; + + + function s2gps(guid) { + var w = window.open('sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no'); + w.focus(); + } + + function s2phone(wpid) { + window.location.href='sendtophone.aspx?gc=' + wpid; + } + + function pl(lc) { + document.location.href='cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n'); + } + function setNotification(id) { + //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'}); + //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'}); + } + function cmo(id) { + //new Effect.Fade(id); + Cookie.set('sn', true); + } + function pp(img) { + var w = window.open(img); + w.focus(); + } + + //--> + </script> + <script language="javascript" type="text/javascript"> + var map, bounds; + var canUpdateFavoriteStatus = true; + var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false; + var logInitialLoaded = false; + var $tfoot = $("#cache_logs_table").find("tfoot"); + var currentPageIdx = 1, totalPages = 1, pageSize = 10; + var isBusy = false; + + var locString = { + decrypt: 'Decrypt', + encrypt: 'Encrypt' + }; + + $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle"); + $("#tmpl_CacheLogImages").template("tmplCacheLogImages"); + $("#tmpl_CacheLogRow").template("tmplCacheLogRow"); + + $(".EncryptDecrypt") + .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} }) + .click(function (e) { + e.preventDefault(); + $("tr.log-row").each(function (i, obj) { + var $obj = $(obj); + if ($obj.data("encoded") == true) { + var lt = $obj.find("p.LogText"); + //var ltDecoded = $('<div />').html(lt.html()).text(); + lt.html(convertROTStringWithBrackets(lt.html())); + } + }); + + decryptLogs = !decryptLogs; + + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); + + return false; + }); + + function appendNewLogs(obj) { + + totalPages = obj.pageInfo.totalPages; + + var $newBody = $(document.createElement("TBODY")); + + $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody); + + $newBody.find("a.tb_images").each(function() + { + var $this = $(this); + $this.fancybox({ + 'type': 'image', + 'titlePosition': 'inside', + 'padding': 10, + titleFormat: function() { return $this.data('title'); } + }); + }); + + $("#cache_logs_table") + .append($newBody.children()); + + currentPageIdx = obj.pageInfo.idx + 1; + pageSize = obj.pageInfo.size; + } + + function callLogLoad(hideFooter) { + $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs }, + function (response) { + if (response.status == "success") { + appendNewLogs(response); + if( hideFooter || (totalPages < currentPageIdx) ) { + $tfoot.hide(); + } + } else if (response.status == "error" && response.value == "1") { + // reload the page since the data had expired. + window.location.reload(); + } + isBusy = false; + }); + } + + $("#add_to_favorites").click(function () { + + if (canUpdateFavoriteStatus) { + canUpdateFavoriteStatus = false; + + var fv = parseInt($(".favorite-value").text()); + fv++; + $(".favorite-value").text(fv); + + var fr = parseInt($(".favorite-rank").text()); + fr--; + $(".favorite-rank").text(fr); + + $("#pnlNonfavoriteCache").fadeOut("fast", function () { + $("#pnlFavoriteCache").fadeIn("fast"); + }); + + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true', + success: function () { + canUpdateFavoriteStatus = true; + gotScore = false; + showFavoriteScore(); + } + }); + + return false; + } + }); + + $("#remove_from_favorites").click(function () { + + if (canUpdateFavoriteStatus) { + canUpdateFavoriteStatus = false; + + var fv = parseInt($(".favorite-value").text()); + fv--; + $(".favorite-value").text(fv); + + var fr = parseInt($(".favorite-rank").text()); + fr++; + $(".favorite-rank").text(fr); + + $("#pnlFavoriteCache").fadeOut("fast", function () { + $("#pnlNonfavoriteCache").fadeIn("fast"); + }); + + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false', + success: function () { + canUpdateFavoriteStatus = true; + gotScore = false; + showFavoriteScore(); + } + }); + + return false; + } + }); + + $(function () { + + // CSP Section + if ($("#cspMessage").length) { + + var editLink = $('a[href*="report.aspx"]').attr('href'); + + $("#cspMessage").prepend('<P>Please take a moment to check the listing and ensure it is ready to enable. Clicking "Submit for Review" will enable your cache page.</P>'); + $("#cspMessage").prepend('<P>Once it is enabled, you will receive a confirmation email that it was successfully submitted. It is peak season for cache placement. Your volunteer reviewer will strive to begin the review process within the next 7 days.</P>'); + $("#cspMessage").prepend('<P>Your cache page has not been reviewed yet. It will not appear in the review queue until you enable it.</P>'); + + $("#cspGoBack").click(function (e) { + e.preventDefault(); + window.location = editLink; + return false; + }); + + $("#cspSubmit").click(function (e) { + e.preventDefault(); + $.pageMethod("EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.success == true) { + window.location = '/seek/cache_details.aspx?guid=' + r.guid; + } else { + alert("There was an error enabling your cache."); + } + }); + return false; + }); + + $("#cspConfirm").change(function() { + if ($("#cspConfirm").is(":checked")) { + $("#cspSubmit").removeAttr('disabled'); + $("#cspGoBack").attr('disabled', true); + } else { + $("#cspSubmit").attr('disabled', true); + $("#cspGoBack").removeAttr('disabled'); + } + }); + } + + + //override coords + if (typeof(userDefinedCoords) != "undefined") { + if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) { + mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data); + $("#uxLatLon") + .data("isOverridden", true) + .addClass("myLatLon"); + } else if (userDefinedCoords.status == "success") { + mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data); + } else { + $("#uxLatLonLink").contents().unwrap(); + } + } else { + $("#uxLatLonLink").contents().unwrap(); + } + + + var cacheNoteText = { + DefaultText: 'Click to enter a note', + ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.', + SavingText: 'Please wait, saving your note...' + }; + + + + $("time.timeago").timeago(); + + $(".button").button(); + + var sn = Cookie.get('sn'); + + if ($('#trNotPM').length > 0) { + $('#trNotPM').toggle(!sn); + } + + $("#cache_note").editInPlace({ + callback: function (unused, enteredText) { + var me = $(this); + + var et = $.trim(enteredText); + if (et.length > 500) + et = et.substr(0, 500); + + $.pageMethod("SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) { + var r = JSON.parse(r.d); + if (r.success == true) { + if ($.trim(r.note) == "") { + $("#cache_note").text(cacheNoteText.DefaultText); + } else { + $("#cache_note").text(r.note); + } + + me.effect('highlight', { color: '#ffb84c' }, 'slow'); + } else { + alert(cacheNoteText.ErrorInSaving); + $("#cache_note").text(cacheNoteText.DefaultText); + } + + }); + + return cacheNoteText.SavingText; + } + , default_text: cacheNoteText.DefaultText + , field_type: "textarea" + , textarea_rows: "7" + , textarea_cols: "65" + , show_buttons: true + , bg_over: "#FDEBBB" + //, callback_skip_dom_reset: true + + }); + + $("#lnk_slippyMap").click(function(e) { + e.preventDefault(); + loadDynamicMap(); + return false; + }); + + $(".inplace_field").live("focus", function () { + if ($(this).data("created") == null) { + $(this).data("created", true) + $(this).countable({ + maxLength: 500 + }); + } + }); + + $("#pcn_help").tipTip({ activation: 'hover', content: 'Enter your own notes here. No other user will be able to access them.' }); + + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); + + if ($("#cache_logs_container").length > 0) { + + appendNewLogs(initalLogs); + + if (DetectMobileQuick()) { + $("#pnlButtonLoad") + .show() + .find("a.MobileButton") + .click(function (e) { + e.preventDefault(); + callLogLoad(false); + return false; + }) + .button(); + if(!DetectTierTablet()){ + $("a.MobileButton").addClass("Phone"); + } + } else { + $("#pnlLazyLoad").show(); + + $(window).endlessScroll({ + fireOnce: true, + fireDelay: 500, + bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50, + ceaseFire: function(){ + // stop the scrolling if the last page is reached. + return (isLoggedIn == false) || (totalPages < currentPageIdx); + }, + callback: function() { + if (!isBusy) { + + isBusy = true; + $tfoot.show(); + callLogLoad(true); + } + } + }); + } + } + + if (!isLoggedIn) { + $("#cache_logs_table").find("tfoot").hide(); + } + + if (mapLatLng != null) { + + $("#uxLatLonLink").qtip({ + suppress:false, + content: buildCacheCoordMenu(), + position: { + my: 'left top', + at: 'right top', + adjust: { + x: 10, y: -10 + } + }, + show: { + ready: false, + event: "click", + solo: true + }, hide: { + event: 'unfocus' + }, + style: { + tip: { + corner: false + }, + classes: 'ui-tooltip-widget' + }, + events: { + show: function () { + if ($("#uxLatLon").data("isOverridden")) { + $("a.ccu-restore").show(); + } else { + $("a.ccu-restore").hide(); + } + + if (userDefinedCoords.status != "success") { + $("div.ccu-update").hide(); + } else { + $("div.ccu-update").show(); + } + } + } + }).click(function (e) { + e.preventDefault(); + return false; + }); + + setStaticMaps(); + //$("#staticMap").lazyload(); + } + }); + + function setStaticMaps() { + + var map = new L.Map('map_preview_canvas', { + center: new L.LatLng(mapLatLng.lat, mapLatLng.lng), + zoom: 10, + doubleClickZoom: false, + dragging: false, + touchZoom: false, + scrollWheelZoom: false, + attributionControl: false + }) + .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })); + + + var mapLarge = new L.Map('map_canvas', { + center: new L.LatLng(mapLatLng.lat, mapLatLng.lng), + zoom: 14, + doubleClickZoom: true, + dragging: true, + touchZoom: false, + scrollWheelZoom: false, + zoomControl: true, + attributionControl: false + }) + .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })) + .addControl(new L.Control.Scale()); + + var tileOptions = { + tileUrl: "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg", + name: "mpqosm", + alt: "MapQuest", + //attribution: "Tiles Courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='http://developer.mapquest.com/content/osm/mq_logo.png'>, Map and map data © 2012 <a href=\"http://www.openstreetmap.org\" target='_blank'>OpenStreetMap</a> and contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>. ", + subdomains: "1234", + tileSize: 256, + minZoom: 0, + maxZoom: 18 + }; + + map.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions)); + mapLarge.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions)); + + var pinIcon = L.Icon.extend({ + iconSize: new L.Point(20, 23), + iconAnchor: new L.Point(10,23), + shadowUrl: null + }); + + var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), + { + icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}), + title: mapLatLng.name + }) + .on("click", function () { + document.getElementById("uxlrgMap").scrollIntoView(true); + return false; + }); + + var mkA2 = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), { + icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}), + clickable: false, zIndexOffset:99, title: mapLatLng.name + }); + + map.addLayer(mkA); + mapLarge.addLayer(mkA2); + + $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({ + overlayShow: false + }); + + + if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) { + var llBounds = new L.LatLngBounds(); + + for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) { + var item = cmapAdditionalWaypoints[x], + ll = new L.LatLng(item.lat, item.lng), + marker = new L.Marker(ll, { + icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + item.type + '.png', iconAnchor: new L.Point(10,23)}), + title: item.name, + clickable:false + }); + + llBounds.extend(ll); + mapLarge.addLayer(marker); + } + var bz = mapLarge.getBoundsZoom(llBounds); + + mapLarge.setView(new L.LatLng(mapLatLng.lat, mapLatLng.lng), bz); + } + } + + + + function dht() { + try { + $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html())); + var linkText = (($('#ctl00_ContentBody_lnkDH').attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt'); + $('#ctl00_ContentBody_lnkDH').text(linkText); + $('#ctl00_ContentBody_lnkDH').attr('title', linkText); + } catch (e) { + alert(e); + return false; + } + return false; + } + + function buildCacheCoordMenu() { + var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng) + $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" ); + + var $menu = $("<div></div>"); + + $( "#tmpl_CacheCoordinateUpdate" ).tmpl( { + ll: [mapLatLng.lat, mapLatLng.lng], + ll_formatted: mapLatLng.oldLatLngDisplay + } ).appendTo( $menu ); + + $menu.find("button.ccu-button").button(); + + $menu.delegate("button.ccu-parse", "click", function (e) { + e.preventDefault(); + var $this = $(e.target), + $parse =$this.closest('dd').find(".cc-parse-text"), + parseCoords = $.trim($parse.val()); + + if (parseCoords.length == 0) { + alert('Please provide valid coordinates.'); + } else { + $.getJSON("/api/geocode", { parse: parseCoords}, function (response) { + if (response.status == "success") { + var newLatLng = new LatLon(response.data.lat, response.data.lng); + + // update the displayed coords + var dist = curLatLng.rhumbDistanceTo(newLatLng); + var bearingTo = curLatLng.rhumbBearingTo(newLatLng); + var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N"; + + var formats = response.data.formats; + // all these finds, make me feel dirty + $menu + .find("span.ccu-parseverify-coords").text(formats.DM).end() + .find("dl.ccu-parse").hide().end() + .find("dl.ccu-parseverify").show().end() + .find("button.ccu-parseverify-accept") + .data("utm", '') + .data("dm", formats.DM) + .data("lat", response.data.lat) + .data("lng", response.data.lng) + .end(); + } else { + alert("Sorry unable to parse the coordinates you entered."); + } + }); + } + + return false; + }); + + $menu.delegate("button.ccu-parseverify-accept", "click", function (e) { + e.preventDefault(); + var $this = $(this); + // update to webmethod + $.pageMethod("SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.status == "success") { + window.location.reload(); + } else { + $("#uxLatLonLink").qtip('hide'); + } + + }); + + return false; + }); + + $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) { + e.preventDefault(); + $menu + .find("input.cc-parse-text").val('').end() + .find("dl.ccu-parse").show().end() + .find("dl.ccu-parseverify").hide().end(); + return false; + }); + + $menu.delegate("a.ccu-restore", "click", function (e) { + e.preventDefault(); + + $.pageMethod("ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.status == "success") { + window.location.reload(); + } + }); + + return false; + }); + + return $menu; + } + + GSPK = window.GSPK || {}; + GSPK.Selector = {}; + GSPK.Selector.getSelected = function(){ + var t = null; + if ( window.getSelection ){ + t = window.getSelection(); + }else if(document.getSelection){ + t = document.getSelection(); + }else if(document.selection){ + t = document.selection.createRange().text; + } + return t; + } + + try { _gaq.push(['_trackEvent', 'Geocaching', 'CacheDetailsMemberType', 'Premium', null, true]); } catch(err) { } + </script> + + + + </div> + + + + + </div> + + + </section> + + <footer> + + <div class="container"> + + <div class="span-24 last FooterTop"> + + + +<div class="LocaleText"> + + <strong>Choose Your Language:</strong> + +</div> +<div class="LocaleList"> + + <div class="selected-language"> + + <a href="#">English▼</a> + + </div> + <ul class="language-list"> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Svenska</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Español</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Italiano</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Nederlands</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Català</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">Polski</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">Eesti</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">Norsk, Bokmål</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">한국어</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Magyar</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Română</a></li> + + </ul> + +</div> +<script type="text/javascript"> + + jQuery(document).ready(function () { + jQuery(".selected-language a").click(function (e) { + e.preventDefault(); + var $loc = jQuery(this).parent().next(); + jQuery($loc).show().position({ + of: $loc.parent(), + my: "left top", + at: "left bottom", + offset: "0 0", + collision: "fit fit" + }); + jQuery(this).addClass("Expanded"); + jQuery(document).click(function () { + jQuery(".language-list").fadeOut("fast"); + jQuery(".selected-language a").removeClass("Expanded"); + }); + return false; + }); + }); +</script> + + </div> + + <div class="span-4"> + + <p class="FooterHeader"> + <strong> + About</strong></p> + <ul class="FooterLinks"> + <li> + <a id="ctl00_hlFooterGlossary" title="Glossary of Terms" href="http://www.geocaching.com/about/glossary.aspx">Glossary of Terms</a></li> + <li> + <a id="ctl00_hlFooterBrochures" title="Brochures" href="http://www.geocaching.com/tools/#Guide">Brochures</a></li> + <li> + <a id="ctl00_hlFooterAbout" title="About Groundspeak" href="http://www.geocaching.com/about/groundspeak.aspx">About Groundspeak</a></li> + <li> + <a id="ctl00_hlFooterVolunteers" title="About Our Volunteers" href="http://www.geocaching.com/volunteers/">About Our Volunteers</a></li> + <li> + <a id="ctl00_hlFooterHistory" title="History" href="http://www.geocaching.com/about/history.aspx">History</a></li> + </ul> + + </div> + + <div class="span-4"> + + <p class="FooterHeader"> + <strong> + Press</strong></p> + <ul class="FooterLinks"> + <li> + <a id="ctl00_hlFooterNews" title="News Articles" href="http://www.geocaching.com/press/">News Articles</a></li> + <li> + <a id="ctl00_hlFooterMediaFAQs" title="Media FAQs" rel="document" href="http://www.geocaching.com/articles/Brochures/footer/FAQ_Media.pdf">Media FAQs</a></li> + <li> + <a id="ctl00_hlFooterMediaInquiries" title="Media Inquiries" rel="external" href="http://support.groundspeak.com/index.php?pg=request&xCategory=11">Media Inquiries</a></li> + </ul> + + </div> + + <div class="span-5"> + + <p class="FooterHeader"> + <strong> + Questions & Suggestions</strong></p> + <ul class="FooterLinks"> + <li> + <a id="ctl00_hlFooterHelpCenterLink" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li> + <li> + <a id="ctl00_hlFooterDiscussionForums" accesskey="f" title="Discussion Forums" href="http://www.geocaching.com/forums/">Discussion Forums</a></li> + <li> + <a id="ctl00_hlFooterParksPoliceLink" title="Land Management and Law Enforcement" href="http://www.geocaching.com/parksandpolice/">Land Management and Law Enforcement</a></li> + <li> + <a id="ctl00_hlFooterContactUs" title="Contact Us" href="http://www.geocaching.com/contact/">Contact Us</a></li> + </ul> + + </div> + + <div class="span-4"> + + <p class="FooterHeader"> + <strong> + Resources</strong></p> + <ul class="FooterLinks"> + <li> + <a id="ctl00_hlFooterTools" accesskey="o" title="Tools and Downloads" href="http://www.geocaching.com/tools/">Tools and Downloads</a></li> + <li> + <a id="ctl00_hlFooterAPIProgram" title="API Program" href="http://www.geocaching.com/live/">API Program</a></li> + <li> + <a id="ctl00_hlFooterBenchmarks" title="Find a Benchmark" href="http://www.geocaching.com/mark/">Find a Benchmark</a></li> + </ul> + + </div> + <div class="span-4 append-3 last"> + + <p class="FooterHeader"> + <strong> + Follow Us</strong></p> + <ul class="FooterLinks FollowUsLinks"> + <li><a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts"><img id="ctl00_imgFacebook" title="Facebook" src="gc433yc_files/icon_facebook.png" alt="Facebook" style="border-width:0px;"></a></li> + <li><a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"><img id="ctl00_imgTwitter" title="Twitter" src="gc433yc_files/twitter_icon_white_22.png" alt="Twitter" style="border-width:0px;"></a></li> + <li><a id="ctl00_hlFlickr" title=" Flickr" href="http://www.flickr.com/photos/geocaching_com/"><img id="ctl00_imgFlickr" title="Flickr" src="gc433yc_files/icon_flickr.png" alt="Flickr" style="border-width:0px;"></a></li> + <li><a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"><img id="ctl00_imgYouTube" title="YouTube" src="gc433yc_files/icon_youtube.png" alt="YouTube" style="border-width:0px;"></a></li> + </ul> + + </div> + + <p class="span-24 last FooterBottom"> + Copyright + © 2000-2012 + <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a> + All Rights Reserved.<br> + <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="http://www.geocaching.com/about/termsofuse.aspx">Groundspeak Terms of Use</a> + | + <a id="ctl00_hlFooterPrivacy" accesskey="x" title="Privacy Policy" href="http://www.geocaching.com/about/privacypolicy.aspx">Privacy Policy</a> + | + <a id="ctl00_hlFooterLogo" accesskey="l" title="Geocaching Logo Usage Guidelines" href="http://www.geocaching.com/about/logousage.aspx">Geocaching Logo Usage Guidelines</a> + | + <a id="ctl00_hlFooterAPI" accesskey="`" title="API License Agreement" href="http://www.geocaching.com/live/api_license_agreement.aspx">API License Agreement</a> + | + <a id="ctl00_HlFooterStatus" accesskey="`" title="Current Service Status" href="http://status.geocaching.com/">Service Status</a></p> + + </div> + + + </footer> + <div class="SkipLinks"> + + <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a> + + </div> + + + + +<script type="text/javascript"> +//<![CDATA[ +var uvtoken = 'eQoxbEsq2D0GKwApaTf6ye1uohqqSH9uBN58l8RKNQR8LIUjzbsrLb35KciGi63NpSiOeI%2bbWi%2f2TK4A7hs18eGBxRDQY0Zdteyw6JOTSnSn4usk0Adoik1Hroz5IVJb%2fZ2YYVAP1zIGCPXp2qNQJvRKrkJIEPUsjSMaDRtfTlWoJrj2CHNs%2blb1Gqo3Rg3iLL0MtaX54CezHnyjaw9diMDzKpLHNEp3BQ3%2bYKGSSDiHgKb1By9RwqflB4CwsGJSNgnF813K%2b4WkJ67Heid%2bwMyNcUkK77xwHvPHZykAsUIYz%2fABtMMd5CsIOqqOuTqA';var isLoggedIn = true; +var userDefinedCoords = {"status":"fail","data":{"isUserDefined":false,"oldLatLngDisplay":"N 58° 48.021' E 017° 48.603'"}}; +mapLatLng = {"lat":58.80035,"lng":17.81005,"type":137,"name":"Stenarna"}; +var ccConversions = [{"t":"Decimal","k":"DD","d":"WGS84","v":"58.800350, 017.810050"},{"t":"DDD MM SS.SSS","k":"DMS","d":"WGS84","v":"N 58° 48' 01.260\" E 017° 48' 36.180\""},{"t":"UTM","k":"UTM","d":"WGS84","v":"33V E 662347 N 6521227"}]; +userInfo = {ID: 1750448}; +userToken = 'FOUTFKOKLELXO6UEFIAQZWR6FG2ZEQLSILWLDKKY2HLEBIZYVHL44E2A27ZQQEK3WKH5JLPDQY24MBCNITG7FIJDSON6YYQ2FJXQVAEE5X7543VDICPKLCBGI53CYFJMR2S4JRHE4URPVORDQTHYRGYK5AJWDE63UP7VC5M2XKK4WREFITXQFRBJD46T4JDBPNENTZ3U4GVXK7NFUZWAPM3UX74XVRXHWYHNTKZ47HR72BTNMCBA'; +includeAvatars = false; +initalLogs = {"status":"success", "data": [{"LogID":284810941,"CacheID":3376131,"LogGuid":"c5548283-9e9b-4dfd-bee3-bc4a2b17e1db","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Post Reviewer Note","LogTypeImage":"18.png","LogText":"test","Created":"12/21/2012","Visited":"12/21/2012","UserName":"ra_sch","MembershipLevel":3,"AccountID":1750448,"AccountGuid":"dfd444d0-537a-49ff-90f1-d7ef9b89360b","Email":"","AvatarImage":"","GeocacheFindCount":957,"GeocacheHideCount":3,"ChallengesCompleted":1,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 1, "rows": 1 } }; +//]]> +</script> +</form> + <script type="text/javascript"> + var browserType = { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, + MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) + }; + + $(function () { + // Make the menu system play nice with all browsers: + $('ul.Menu li').hover(function () { + $(this).addClass('hover'); + $('ul:first', this).css('visibility', 'visible'); + }, function () { + $(this).removeClass('hover'); + $('ul:first', this).css('visibility', 'hidden'); + }); + if (!isiOS()) { + // Constructing a Twitter-esque Login: + $(".SignInLink").click(function (e) { + e.preventDefault(); + $("#SignInWidget").toggle(); + $(".ProfileWidget").toggleClass("WidgetOpen"); + $(this).blur(); + $("#ctl00_tbUsername").focus(); + }); + $(".SignInCloseLink").click(function () { + $("#SignInWidget").toggle(); + $(".ProfileWidget").toggleClass("WidgetOpen"); + }); + } + $('.SignedInProfileLink').truncate({ + width: 120, + after: '&hellip;', + center: false, + addclass: false, + addtitle: false + }); + + // Hide the warning message if the user closed it already + if ($.cookie('hide_warning') != null) { + $(".WarningMessage").hide(); + } else { + $("#warningCloseButton").click(function () { + $('.WarningMessage').hide('blind'); + $.cookie('hide_warning', 'true', { expires: 1 }); + }); + } + + function isiOS() { + return ( + (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i)) + ); + } + }); + </script> + + + <script id="loc_favPointsScoreDesc" type="text/html"> + Favorites/Premium Logs + </script> + <script type="text/javascript" language="javascript"> + <!-- + + + + var gotScore = false; + var favDropDown = $('.favorite-dropdown'); + var favContainer = $('.favorite-container'); + + function showFavoriteScore() { + $('#imgFavoriteScore').attr('src', '/images/loading3.gif'); + + $('#uxFavoriteScore').parent().fadeTo(200, .001, function () { + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/score?u=' + userToken, + success: function (scoreResult) { + gotScore = true; + + var score = 0; + + if(scoreResult) + score = scoreResult; + + if(score > 100) + score = 100; + + $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png'); + var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim(); + $('#imgFavoriteScore').attr('alt', pieDesc); + $('#imgFavoriteScore').attr('title', pieDesc); + + $('#uxFavoriteScore').parent().fadeTo(1000, 1); + $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html()); + } + }); + }); + } + + + + $(document).bind('mouseup', function (e) { + var $clicked = $(e.target); + + + if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) { + favDropDown.hide(1, function () { + favContainer.addClass('favorite-container'); + favContainer.removeClass('favorite-container-open'); + $('#imgFavoriteArrow').attr('src', '/images/arrow-down.png'); + }); + } + }); + + $('#uxFavContainerLink').click(function () { + if ($(favDropDown).is(':visible')) { + favDropDown.hide(1, function(){ + favContainer.addClass('favorite-container'); + favContainer.removeClass('favorite-container-open'); + $('#imgFavoriteArrow').attr('src', '/images/arrow-down.png'); + }); + } + else { + if (!gotScore) { + showFavoriteScore(); + } + + favContainer.addClass('favorite-container-open'); + favContainer.removeClass('favorite-container'); + $('#imgFavoriteArrow').attr('src', '/images/arrow-up.png'); + favDropDown.show(1); + } + }); + // End --> + </script> + + + <script type="text/javascript"> + var _gaq = _gaq || []; + _gaq.push(['_setAccount', 'UA-2020240-1']); + _gaq.push(['_trackPageview']); + (function () { + var ga = document.createElement('script'); + ga.src = ('https:' == document.location.protocol ? + 'https://ssl' : 'http://www') + + '.google-analytics.com/ga.js'; + ga.setAttribute('async', 'true'); + document.documentElement.firstChild.appendChild(ga); + })(); + $(function () { + $("a.language").click(function (e) { + e.preventDefault(); + window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang")); + }); + }); + </script> + + + <!-- Quantcast Tag --> + <div id="Quantcast"> + <script type="text/javascript"> + var _qevents = _qevents || []; + + (function () { + var elem = document.createElement('script'); + + elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js"; + elem.async = true; + elem.type = "text/javascript"; + var scpt = document.getElementsByTagName('script')[0]; + scpt.parentNode.insertBefore(elem, scpt); + })(); + </script> + <script type="text/javascript"> + _qevents.push({ qacct: "p-f6VPrfmR4cujU" }); + </script> + <noscript> + <div style="display: none;"> + <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1" + alt="Quantcast" /></div> + </noscript> + </div> + <!-- End Quantcast tag --> + + <!-- Server: WEB13; Build: Web.HotFix_20121211.1 --> + + +<div class="header gctour-grand-default" id="gctourButtonWrapper"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDGQg7CZXhIq0AAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAD30lEQVQ4yy3M2W8UBRwH8O9vjj2ms92rpUsPutClLdjVQi0WS%2BHBNCq2QCKJhoemLxhr9QlTEhIjPIgxKiRINKSiQEKEBINIsVpSSRpQMLZKCU3tfQBdeyzda3Z3ZnZ%2Bvvj5Az5kWZaLiOwAFAAeZl6z%2BNevNRM%2FnGoB4JEUl5ReeuRNRaY9joKSZFnT%2Fpny5rYRu7tgEsA%2FAMaImSsBuP5P8mb7L25%2BfPvqzuo3D8%2F5qupVQ0sUyoqLLNPgse9Pls%2FevFCua3E5tOedBxWtHX2ykn9HAlDFM39uIFESkjZveuH367X1Xed%2FkZ15%2Fid3e8omrp1%2Brul47z1BklPVb3TFK%2FZ0LE799HVo%2BMz729jQ9eoDR2YkTixtxc3PX%2BP2s7cfnuiorDvUfUNyKGlmThc3tDy5d%2FzAbiLKAkgBEGWnyxXa%2B%2B5TpaAUeYGgJYhSoUBDVxqxMh2MR6MVzoISu%2Bx0qUTkJCKZmaXSptdnouNDfmZWcnpG1RNR1UhEHe4NYcHQ4r6ckQ2Q9UnjAoVeNEesYi0QbpzyVdWPA0gDUAEEsvGVwgfdh4Nrt7dGVifv58dnR%2FypyJRLj6%2BIejrFzWeGr0mIRVQE65%2Fqg4MeW76%2FAIDAc0OO5G%2BXS1aXI66Et9LKrC45kyMDtuJsxFa2721NKgpZDn%2BxOH%2BqzS5c%2F2CrBLaAlVkHBMkm2hyF030XSsa%2F6ija5taENTvbk4H9h%2BKr44P68qUjHq8tKiDPyXD7BZxvz1s3elk2fEESEN49hzvfuFQzJqXmR92e0BZ74KX2jHpiftn27KuWfLS6SFFdtmTx85wmhVASlhAZdfAfl2RiE5RNigL2fnSLFa9W8fCcU%2FiuU%2FUaS1K483RW8pWKqN1ngS2SVa%2FIVk7U3OsIfZ8pfOsLG1kGMjnAbO6akEhx3%2Bf3eon%2BvvqCMnCu0jz5ikuq3GFy01smhm%2FI8Ach%2B0ul4vUbybaQIP75Y5GMDHIWMO8OZ8sb26eImRuYOQSgiixz8%2FjFYw3ywJeBYD4IWpwgiIBdZTZ1gpEBLBNEQEwHzLZv53y72vqJmQPMXARgIxHVAtgy1tNdZ%2FR%2BWrCJZ0XkTBAIAMMCYAl2XvDWZO2ymCtSZY2D9UPEzA4AbgBBAHVs6ttJT4ZTpuB3HK1aG9vUkhB0zQDYyNjcmccJy%2FLW7Fhab08amLwro%2FXYFQmAwcwZIkrC1OP48cMAj%2FSVKU0Hl1BYHvMdPNuvJVZXQMKKR81PBACdmU0iymJXZ4yZ%2F5WYmYnIYGYNorwI1TeGZ142UBKOoLMnAuCRU3VHAESZWQNgEpHFzCYAnYhS%2FwF8odAV4EB4aAAAAABJRU5ErkJggg%3D%3D"></div><div style="left: -210px; height: 828px;" id="gctourContainer"><div style="height: 40px; cursor: pointer; -moz-user-select: none;" class="header gctour-grand-default" id="gctour_header"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIcAAAAYCAYAAADQ1%2B6cAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oIGQo6LQ%2FxwecAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAEBBJREFUaN7tW2tUVFeW%2Fu6jHlRB8S5eIo8SRFAQFaKxfSW2qBgjMmpixkfSJplMllkaku6OkzG2vZJxTDR20tMmrCahk8YsO3REDGjHFyrYohGiRsQSQZRnBSwKq6iqW3Xrzo%2Bcq8ebinavNT8GV%2B5aZ91bt86rzv7O3t%2Fe%2BxQDckmSxODOxQDgAKgAqAFoAGjJsxoAT75nSX0RgADABcBJ7m7yTgQgMQwjUf0rx%2FvBpax%2Fvzb%2FF%2F3%2FdCnWSLGQDBE4RwCgAaADoCclgAKJDBCGAscQADuAQQC3yGc3AK8MEMVY9P22XBX3H8z3n2hzL4BIPwHl3hdPhEWDQgaGmoBBDyDw1JtP5vdfOvVzdVConeVVrMdhCx%2F6riOJ5VWCPia5ZcTUxX9Pe%2BLX5xiOsxFAqUi%2FPrlIkkQDkC4MJTAfuYvkLinaMD%2FSRllfWY8GhUTNS5IkifkJIH52oiRJLAGDijIbKlI0AHRfPZe5Xh0UJjy0YdeRgPBY2cxwouDmzH%2Fdnta2v%2BQRR%2FfV0dqw6I7Uf3nls9FLik4D6AXQA%2BAmAAfRHrLAeGoc2jzJQvaQ%2Bl5K2Dw1T568k4Xspdr4KLOoNH%2ByCaTHEClA%2FlMmyJ%2FpepBAxkiSpFKYDy0lNO7o%2BmlLw9Ieupb1%2FDtXARiuH%2F1s9K0Oc0zGijeayOICAH%2F1yw%2FGXCp783FnX0ecccLsAzP%2B%2B%2BBOAJ0EJINEGBylkWgTxVGC8xDO4qI4C0fxHnp%2BEqnvJlzHTc1JBrGGApNP0b%2BTfJYB4s80SfcyyT9mrh4EkLBkoQMABAOIxMUDY%2FDJLxYCCDOXb09X6YOdWc%2B%2Fc44somegpTH86t7%2FWUgtsgOA07Tg38x5HzUVB8aOumZpODSv%2FXDZGACBFABkAIYAiAQQDSAOQJwgCPGCIMSTz7EAYgAYAYSTEgkginwXByDO5XLFezweum4kgFAABqqEkfcxVL9yvSAyHy0FIo0f7UlzK4bSShylyeh6HNl0zP1I8f97zkHKHaH9ZX0RHl1XBSDkRs3uvFm%2Fqy0mu8ELwGta%2BGLTlYr3g31eQWJ5tUjeswB8qoAgccrG8orrRz%2BLGzGtUOYeOgIiiTyHAQi5fPlyfHl5eUFHR8ckl8tlBACtVmuJi4trWLRo0d6xY8feIO188hzPnj2buG%2FfvkU9PT3j3W53KACfXq%2B%2FkZCQcGzlypXlUVFRfYQE%2BwCo1q5dWyyKYgTDMCxD2LAkST6DwdC4ZcuWN8i8XRRf8fm5eynzIykIuz%2BT6KW0kTTcwSFrDgOOf5iNXnMucp7cfe3gJxkBEXF2llNpyI%2FkAHD6qAQh1JTd0Fm7Jz5%2B5rI2SvvwADjDyDGu2MkLer67cDw%2BeuKcfmKqPKQPA4DwL7744mfV1dXrQkND22bNmrU7MzOzjed578WLF0eePn16xo4dO3bk5eX9YcmSJV%2BTdvyuXbsePnz48Jro6Ohz%2Bfn5Jenp6ddcLhfT0NCQfObMmQWbNm16dNWqVa9Onjy5lZgjdvr06R%2FxPB%2Fe39%2BfXFdXt2rJkiXveDyeIZ1O1000h1pBZH2KQpssgbzjKG0je23y5nETsDGySZQkadiaGP4ul%2FXUp7MQZLQgwKC9fmTX1JRFaw8S0yDzAh0AbfrKN05c%2B1tpZvzMZRar%2BWxga3Vx5kDr%2BVRHT9tIwdYXLvlEVmcc2Z5f1n6FtPcQEIXU1dWNq6qqenXChAl7XnjhhS9ZlnWQhZRGjRrV8fjjjzcUFxfn7d%2B%2Ff21iYuKbOTk5lhMnTiQfOnTouenTp5etXr36IHGX3QDEjIyMK0uXLj20cePG9aWlpb9NT09fYTAYvADEJUuWNAKIqK2tZevq6jB%2F%2FvwW0tZOwBFImQp%2F3pKL1LUR8%2Bkja6GnzJKa1HcR932Q0iK%2B4aw9%2BLtsZ0%2FzGESP7gagGeptT4jOmSsQM%2BDFd616BEcz8Lj0hoQMceBq45ivnh9v4hhIQRExAyHJmZbIzBm9nCYAnErraan8fa6rtzVCG5U8SHkqQRUVFStHjBhx9sUXX6wiiz5IdqYkg%2FS5556rioiI6Jd3aWVl5eLk5OT61atXHwZgJUUWFqvRaFQvvfTS5urq6rTu7m6vwWAYojiVSxRFjyK4FwBAe%2F78eWN5eXlhb2%2FvWFEUA%2FR6fU9GRsaxZ5555jjP8%2BK6deteXbx48dvTp0%2F%2FhjIxAVu3bl1qt9uzNm%2FevPvll1%2FePGXKlL0nT57MY1m2e9u2bS%2BT38PeJ84yLMBxJ%2FbAMAxC4gYBqCXRq2VYLhCA1nNqV8zA0Y8noevbUb1OlrkZnnEjMHbUTXVQ2FBuSswtXK4ZhcK3ziM%2B2wmAh3OQMx77r1nMe3OfxZvm3xBhMC0tLcb%2B%2Fv6MwsLC31C7cpDiJLdV9%2BLFixsAGNra2mL6%2BvqSly9f%2FikBhBVAH3mWPRlVXFwc9%2Byzz3bKxJkyd4IkSSIFFjUArra2Nqm0tLQoJibmXEFBQXFERMTghQsXRtfX1y%2Fu6uoat3HjxjKbzZYhCEIExZtYABqXyzXSbrenAgixWq1jDh48ODI%2BPv7o%2BPHj9yi00LDnHHfsLcP60NU0AoBKkny85PMFXvrsrdTmXW%2FlZxlc2oRglSd01ppj%2FNJt57w%2BH75akfiMqMu9yvW1xmLQ8r35%2BNMzD6G%2BLCfMJ%2FBuZ4CDsstobm5OYFnWnZub26Egej6K1NGBLO7KlSsxHMcJWVlZXZR35FCAg1e4w%2FJ7D7H7Eg0OURSZ3bt3%2F8JkMp167bXXPpWJ76RJkzpyc3Ovvvvuu69XVlZOBACO4%2BiUAQCoOY7jWZZlCegxevTo40VFRX8C0PWPxk6GCzjk2IKAxJyz%2BPbAPBzaYdKEGG%2FdNJ%2BJDEudZA9OzmwPmfpIG5%2B%2FzowvXpuA10et4tdW7dHGploua9MG0vlvRGTk2WC9ocPFA2kQBR4AOMGuozSTJIoiyzCM%2BP26fi%2F87du3z7NarZEMwzAsy3JqtVqj0WgC1Gp1gEqlCtDpdD6GYXwsyzL3iT3cKxIqXxwAtr6%2BPt5ut8esWrVqGwHGIFmHgIyMjE6TyXSmoaFhPACwLMtT7i0LQMNxHM8wjKyZkJWVdYEioy6ynsMeHCwVr7BjxR8roAvpx%2BcvF07RdIYO%2FnVTTnTOXOuj75%2FaH%2F7EW5cQZBTx5O8b4HFq0N8eFJY6qaf73IkkMCxQ91EizlfFwtYdKnfuSp19ilLzYnJycocoirrm5mYjYfwBLpdrpMvlSnU6nSlOpzPF4XCYbDZbQk9PT1p9ff2CiIgIh9fr1VJtdFSeR0dIpRzXCCLfqanYhBJAbHd3d7hGo7kVGxt76%2FbGoJKFRqOx69atW6FEcyiDhDqO41QEHCwAqNXqIQocbipSO6yDYTxZHAcAG4Kju%2FHGhY344%2FJ%2F1ZmPTU0avBEl%2FWpELDPz389gzi9bwPES9r0xFiwvImthX6wUJF0%2Fsisbr2w7is%2BLZsH%2BnUHuuMWh8iQ99d4hatHYcePGdQUHB7fu27dvRlpa2ucAxA0bNuyXXU8ihEAAhp07dy6w2%2B1ReXl55gMHDli%2B%2FPLLmWlpaddJAEsi4PDJYX5RFPn6%2BvqwpKSkzpiYmH7SJ6PQND4ACAkJuSUIgs5ut6sDAwNld17WLIzdbg%2FSaDRDLMv6vF5vAJmT7N7qJEkKIuDgSRjdR8YTFDERPAiaY4gQPQuCY9pRdPRDbLq4YcA0p85t6zOg4j%2Fm49cjVuDzoiycKH4IQUY7vt1vNPIubnxach%2F2vv4zGhj9YoD7Zubyo1x4vI0wd6fME2bPnl126dKlR%2Fbu3ZtNFj2YCDyEPOtrampSvv7669lz5szZx3Gcffbs2dVNTU0zKysrJxHvKUoR9YzasmXL2tLS0hKn0xlMhdcZkliTBeUFIEyePLmF53nX7t27pxCQBZGxAx0Oh85sNk80mUzNer2%2Bv7W1NYHMM5REa0MsFstowjk4Ag7RD9eQhnsIXeYcTmqHfR%2F4iRnjDvnl3%2F58%2FsOiHt%2BpP8%2FKFFwa9tD2mQAAp02P9%2BcvBYCRfkx%2Fv6h2T3h6099h7%2FciMNxFwCcBQH5%2B%2Fpne3t6SysrKZ5ubm2see%2ByxI%2Bnp6X0A0NnZadizZ8%2F0xsbGednZ2ZX5%2BfknAYgLFy480d7ebqioqHjBbDYnFxQUfGUymfoBSGfOnImtqKhY1NvbO76goGBDcnKyg%2BIbIgCRcmWdALx6vZ6ZNm1aWU1NzdMMw4hPPPFEnU6nE8xmc3hJSckKhmHEZcuW1bjdbpw%2BfXpuWlpa28MPP9w6NDTEl5SUzLVarUlGo7FNzuOQ%2FkVKuzwwiTc6gynb9GAq%2FxHVWlU88fIn%2F7lwaoSgMngHAv32xKm8Xaq474asluCECTMaVH3mcCTmHsGaXWXE9fSQ%2FkMBhB4%2FfnxsdXX1UovFksXzvIthGFEQBENwcHDrjBkzygsKCk7LwpTD53v37p147NixQqvVmqJSqQYlSWJFUdQZjcazhYWFH%2BXk5JgB9BMt6CZmKqyqqmpyeXn5Bx9%2F%2FHEBlenVlJWVTa2trX3K7XaHqVQqhyAIQdHR0Y1r1qwpNZlMNrfbrX777beXt7a2zuJ53i6KoiYkJKQ9Kiqqra%2BvL37r1q3vPf30039YtmzZS3Pnzq0FYCGxGzcA33DXHHRyiKWipYEAIm4nutyOGC%2BYoBvFL05N%2BrZ0qoUNHdRqtG6OESFIvKdP4MTrNi%2BrMU26NNkUfZO%2FejwNLGfDUx%2B8h5RpZkpYHCF1MoHUWa1W%2FYULF2IFQeBTUlIsCQkJVsoMDZEdyRP1HwhA29nZabh8%2BXI0y7K%2BjIyMrsjISBupayPFTkCgIeOEEGDKsRRJzg6LoqhtbGyMs1qtgSkpKT2JiYlWilByAFSdnZ2GpqammLCwMEd2draFZVmaw7jImP1UcE54EMyK8iSY7J7pAYRD9Mah69tUHP%2FwETy18yKGBrQoinxF2GrZ1NtwKMjrsnsCwmJtoaMn9WsM4e7bUcShAREttTwyF7SSBRukhKL1k7JnFSl1OgVPp%2BzlNjxpI7uqAqk%2FhDunz2SyqiPt1FSUU6L6VKb0vRQ4WCrFwCpC7LQZdhJAOqg5PxjgoADCULs0FDe%2BScJf1q%2FB1ZMFSJh4FppAJ9x2FX51skSxGN57JKwclO8v4e6TZjwlGIbiCbL7qxSSSkk2cfcBIQ91BgSKsVhFck1Or6sU4KRPldEn5FiKy9BCF6lx5TlLD8J5Dv42Sr7PaNOpZwHx4%2FuQMLEeEUmdMI4axLwNTZTA7WSXCpQQ7yKClMA8ioSWl3JfWT%2FBK3%2FH%2FgRKSMr4hU8hWCiA4KXA9GNHD3%2Fg8lIbiFGMKfmZr%2B9BcWH9RhWJ9mApdRxEipYIRs5UOnH3ySufQtX6S4Hf64CxUjjSPaKgyvYS7n0oGfdJgNH9%2BevH33jwA5QH5gTYDzSH4seKVDLMTal%2B%2BjCLQGkI6Ud21A8WTb7fCT34F%2BiP%2FDXhXgC411lPv3UIUO8nzH9I2A%2FiAeX%2FBUPhQRLDQ08NAAAAAElFTkSuQmCC" style="margin: 6px 0 0 6px;"><img id="gcTourPin" style="float:right;margin: 6px 2px 0 0;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89%2BbN%2FrXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz%2FSMBAPh%2BPDwrIsAHvgABeNMLCADATZvAMByH%2Fw%2FqQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf%2BbTAICd%2BJl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA%2Fg88wAAKCRFRHgg%2FP9eM4Ors7ONo62Dl8t6r8G%2FyJiYuP%2B5c%2BrcEAAAOF0ftH%2BLC%2BzGoA7BoBt%2FqIl7gRoXgugdfeLZrIPQLUAoOnaV%2FNw%2BH48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl%2FAV%2F1s%2BX48%2FPf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H%2FLcL%2F%2Fwd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s%2BwM%2B3zUAsGo%2BAXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93%2F%2B8%2F%2FUegJQCAZkmScQAAXkQkLlTKsz%2FHCAAARKCBKrBBG%2FTBGCzABhzBBdzBC%2FxgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD%2FphCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8%2BQ8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8%2BxdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR%2BcQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI%2BksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG%2BQh8lsKnWJAcaT4U%2BIoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr%2Bh0uhHdlR5Ol9BX0svpR%2BiX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK%2BYTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI%2BpXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q%2FpH5Z%2FYkGWcNMw09DpFGgsV%2FjvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY%2FR27iz2qqaE5QzNKM1ezUvOUZj8H45hx%2BJx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4%2FOBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up%2B6Ynr5egJ5Mb6feeb3n%2Bhx9L%2F1U%2FW36p%2FVHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm%2Beb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw%2B6TvZN9un2N%2FT0HDYfZDqsdWh1%2Bc7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc%2BLpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26%2FuNu5p7ofcn8w0nymeWTNz0MPIQ%2BBR5dE%2FC5%2BVMGvfrH5PQ0%2BBZ7XnIy9jL5FXrdewt6V3qvdh7xc%2B9j5yn%2BM%2B4zw33jLeWV%2FMN8C3yLfLT8Nvnl%2BF30N%2FI%2F9k%2F3r%2F0QCngCUBZwOJgUGBWwL7%2BHp8Ib%2BOPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo%2Bqi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt%2F87fOH4p3iC%2BN7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi%2FRNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z%2Bpn5mZ2y6xlhbL%2BxW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a%2FzYnKOZarnivN7cyzytuQN5zvn%2F%2FtEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1%2B1dT1gvWd%2B1YfqGnRs%2BFYmKrhTbF5cVf9go3HjlG4dvyr%2BZ3JS0qavEuWTPZtJm6ebeLZ5bDpaql%2BaXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO%2FPLi8ZafJzs07P1SkVPRU%2BlQ27tLdtWHX%2BG7R7ht7vPY07NXbW7z3%2FT7JvttVAVVN1WbVZftJ%2B7P3P66Jqun4lvttXa1ObXHtxwPSA%2F0HIw6217nU1R3SPVRSj9Yr60cOxx%2B%2B%2Fp3vdy0NNg1VjZzG4iNwRHnk6fcJ3%2FceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w%2B0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb%2B%2B6EHTh0kX%2Fi%2Bc7vDvOXPK4dPKy2%2BUTV7hXmq86X23qdOo8%2FpPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb%2F1tWeOT3dvfN6b%2FfF9%2FXfFt1%2Bcif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v%2B3Njv3H9qwHeg89HcR%2FcGhYPP%2FpH1jw9DBY%2BZj8uGDYbrnjg%2BOTniP3L96fynQ89kzyaeF%2F6i%2FsuuFxYvfvjV69fO0ZjRoZfyl5O%2FbXyl%2FerA6xmv28bCxh6%2ByXgzMV70VvvtwXfcdx3vo98PT%2BR8IH8o%2F2j5sfVT0Kf7kxmTk%2F8EA5jz%2FGMzLdsAAAAGYktHRAD%2FAP8A%2F6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfbBQcMJyOQosv2AAAD4UlEQVRYw8WXzU9cVRiHn3PuvXOH%2BWLK8FmhkDZltEAqdeHCnbGbmqgJqfEvcOMsTFyw6ca4mhgTE9HEhf9BiV8JqyZGo4AYDCpCIY0x6IAQmDIznZl758651wUXuWmwDJQpJ3lzc3PevOc5v%2Fc9X3DGTRzHeXAsG9E0%2BZ6uaa8p1015HniAEGLHVeq253nvrk6OV5oCMDiW7WwJh%2B4%2B%2B8xA4vLFPq2ORqFSp1Cpky9W%2BGd9QxV2NsuqXr%2B8Ojm%2B1WhcvVFHTZPLAz1t525ef45CVVGoOBiGg6bXkbqBGYlp24ab2NjY%2FBp4vtG4smFSTeb%2B%2BHubuYUVUlHJhY4Il7pjpJ%2BKMdIboVVts76xiRBi%2FjgpaFgBIdixanW%2B%2Bn6JL7%2F7HV3XEAKkAM%2F1qNoOSrkgZakpAHhsADiuIHVpiO4L%2FVzrj%2FFCH6hiiTezn6NJiXLd6nEAGk6Bo9wNKQ9qNhRuIRqL0tYaPQgmhQ0UmgKglLula7J%2BRJoU0BwFgLw%2Fw0esaeE2E6AoEMYRCoQA1RQAwzDeDptGKB4xD%2B1vT0aJtZghAR8OjmWTp7oKht744JNUZ%2BdQSNdIhBQXB2K0dxn0JjQcq8J2sUo8YrK5XcSQJBXiG2D0VLbiwbHs1Ugs9u2LN260SilZWfyNrfUcxUIJ8AjpGoYmcewauq9nte4VFXy0cnv81mMrEDaNt4bTA1Ep96Knh0cYuTZKe3sc6SpWfl3k55mf8ALJjIS0RM0TrwC3HrsGLNt5Z35hyes2ykTNPfdarU7%2Bfhl0jfTVYa6Mjvzn33EuxoXzKQdYbOiMOcphZ%2FlOre3plz69e2%2FtZVW%2BH073Js3z7XHCGkR0SUfCZHCgi85kC8loiJ2SXfhrq7hg1eo3d5bvOKd6H7jy%2BvvZSEvo1dIDKx2PHqyGUtnGNI2SFOLHilX7eHVy%2FIumXEj228TExG5rqqe15jjYtoVrP1jLZDL9J4klOVmbT0R0OpIRYnt1MXPSK9lJAeYcx8E0TTzPOxOAedu2MU0Tx3HOBGChWq1iGAaWZVWBhScKkMlk7lmWlbdtG2Auk8nUnrQCAPPlchlg7qSr6aitWPgblQyY2DfLshZLpdL13d3dX4A4e0%2BEh831j2fXt4YB9gcPAWH%2FawSBcrncn%2FF4nKmpqTWgJzCQB9R9s32rBaCOBWACUd%2FCPoQOyJmZmc2%2Bvr7c9PS0DnQFABTgABaw%2F0pSvnmN1oAX%2BD4sqQt4s7Oz6%2Fl8%2FofArIP9buCfwwZupAaUL5%2FwZxRMgQDk0tLSZ8B6YLBg3oMpUP8HIY4oQnlIERIoxsMU4xA13EepcKbtX%2BRcieZqbkRNAAAAAElFTkSuQmCC"></div><div style="height: 20px; -moz-user-select: none;" id="gctour_toolbar"><img alt="New Tour" title="New Tour" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABmJLR0QA%2FADpAE8017ENAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QISDiYc07YZKQAAAWpJREFUOMutkE9LW1EQxX9z741WJH0lgtDKWxbc1O5cZqkb8w2ycVm%2FRd6y3XcjBMSC38BNN90qhVJKslJKSVqEEP9FYpved8eFJsYYk1R6NjMMc%2BacM1Iul7drtVqREZid%2FcvcXJtn0W%2Fyy5%2Ff5aJvH%2BHPvmTDGaVSScfh%2FHhTL0%2FfaOe8oJcnK52LxuKutrLr2jIzrqvSbDYJIQAgIj31jNlj2n4h474iZgnrTCbY9mrHt1tTzld7BwbJ3WrkCGvqiHmFuAJgMSpG01%2BL4F66%2FqyD5OtebzoLTIE4EAuCABduNFkIOk%2FQ59hQRdNpQNC0ot6besamFffQ57uHAq%2Fx4SfgsVoBFO9f6OlZ69PM%2FPeDkRFEBOUpHV1DdYE0%2FQE8YWvn0GxsbL8FcKPItzWL1zwiQhRFNBpJT9QwIfp%2F0497EYY5eIh8x8GwpcHZsB0zqd2xEXK5HI%2BBi%2BP4Q5IkxX8hxXH8nv%2BFK8w9mWB7rBTJAAAAAElFTkSuQmCC" class="tourImage"><img alt="Load a tour" title="Load a tour" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABmJLR0QA%2FwD%2FAP%2BgvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH1QsVETINEBVQCwAAAaZJREFUOMulkb9PU1EUxz8vfajv0QYLDE1MNxlgc0ITIwODfwAIRgYkDBIQHNwMBAYXBxY2E34OBNQwA9FBRwYTEgxshGhMhCZtbeC95%2B279zi0aa15TTF%2BcpN7T8493%2FO951oPBvtmU6nUHH%2BhlCrtv9TYyvLaa%2BpgTT6bkJHh0chkEPgsrSxSKBQevXuztREpMP50TAb6Bzk8OgTAboqRSMRpRC6ffTn%2BZGrG1lrjOC7XW5IlxZjh4cBQQ4HNt%2BvTwIytlML3PfI%2FcwAkW1sA8LyLusWu21w522EY1jgAU0kelZ%2F1J52dXTWxDUQ6iLocxaUdxOMJ0ul0tIDve7z%2Fcs5BxgVg%2FsN6nX6fa6LeiSWxARzH5SDjsvD8PoHSXIZrV2JMze9WZwDwIxdwfHbRsFhrQ7rdrQ7RcUqBACKCZVmICCJgRNBGCLVQ1AYVGkIttCWu1v7CzaRP9lzxPeuDWBiE8kIEBEGkLAwERVMVOM2ccevOXfZP8uWiUncRMAiCBSIVV90drexu75AMvq1a9x6%2F%2Bug13ejhH2kuft37tPriNv%2FLbzdmyosZb3GLAAAAAElFTkSuQmCC" class="tourImage"><img alt="Download Tour" title="Download Tour" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9oIGQorAW7wjhQAAAMSSURBVDjLnZNNaFxlFIaf797v3tvMTOd%2FJjOZ%2FHSGhAyZmh%2FIlEhjSS00gihxoUatQqXqxoWFRkHBlVTcCi5ciBFLXQiiq0oRQw0qpoS0IaFiiyGJSabJOBPNZO783s%2BFaDBLHzibw%2Fs%2BiwNHcIjJ16dfAV7WpexTYCnH2VeKOU3Xrly9fO7jw3nxb%2FGNTwZNXfu6JxlrHenvIpkI4bIsiiWbe%2Bs7zC%2Bvc3dt%2B6YQ4sLVy%2BcW%2FyN46uJHWbe35aeJ0wNioCdKsWSzs7mG9EShJQDlHRKtIeaWN7g2u%2Fw7Qjz8j0QChEKeb86ezIgHUkEK%2BRzhzgy%2BcJxypU5u%2FVekU0Nr2pzJpmg6KnT9hzsfAg8CaC%2B%2B9ek7sWjAezrbjaE5NKQHNIEhJaYhcVmS1tBR4tEIEb%2BbbKadrrbgyLNvXjkPoHl9rgvDmU52i3nuV11E246hFDgKEBrCqbFV2OfLG0tcn53HZyn6utsAngSQe%2BV6pCsWYO7uNqmeKI46uGxpt8CJwQxCCJRSbGzdp2LbxCM%2BgGEAWak1NMsy0TxRdksVmo7CY%2Bk0m01qpR2ECANwa3wczeNh5aVXiXT0AgQBpK5rzh%2F7Fc1d2cQjLbb3w%2BQNk0bToVJoMFivc2t0FO%2FwMPbKCscSEbbtGkABQBqallv5Ld821B0j1RFndX2D2Xt%2FUsPErrn5dmSE9nSaowMDqGoV%2B%2BJrRAyDKdOMTE1MKH3ooSeSpWr9RKY7Qdjvxu%2Fz0hHQmVncou3tp0l1dhI4dYrq5ibuvj48x4%2F%2FPZkMpcVF9IXvvrjWnX3sktB10%2Bc2aDF1fpxfojb1Av3xOIGxMSqrqzTLZRrFIvVCgUaxiBEMsnf7NjpAsm%2FsztauPekgkVLj8%2B%2FX%2BaX%2FcZwbn9Fq27jTaZxKhSPt7UifDyMYBKXYW1g4%2BIVHz7%2F3TGeqY9rr85vpVIxY2ItlGSxNnuVkMol%2FdJTizAxr%2BTxHNA0JeKQ8EAD4g0lz%2FPlL07rlegRd%2BkEIpZzGma%2FelUOJBD%2Fncjy3tCT4P7zf26s%2BSKfV4f1fpUgaHTdq5X0AAAAASUVORK5CYII%3D" class="tourImage"><img alt="autoTour" title="autoTour" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAFMAIwADJfKnZwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9kKEg8hB1Dip48AAAJvSURBVDjLjdNLSFVBHMfx73%2FOued4r14wpSLQNj0JokUtFIKCgqIXPQgikqSijUrqoqA21lIkywoiCAqyRUZRFBGFoIEkFdHGoPcLF75S79Nz7sy0UK6kIf03s5j%2FfGZ%2BzIwwR7UecLYrl91a0yOiuxpu82Vmj8wFXDzopPedeRrtf98V9r24lRsf%2BpkRpbpzob43tlK3NzVhBODK0ZILYSZRa612ZiI1NzMEqRGUDciO%2FmDwUw8f3z7na9%2BLz3U3s0tdgCAzXlfV%2Bk3F4vPwPD%2B%2F%2BFKVB0B65DvhyAeYGKE4HqNy23E%2BvutcAuACYI1y%2FRjZbIZsNjOdTzlYnaMgXoprFhEMjRIM90GYAGuZBgCbHsCEKbBmatKwbN0ueu%2BcpGxFJb5fgHKL8OML0clf%2BU3yAAMvMalB%2FPmriC1aizgRNh1upvPaETrfPCOdGsOGKUoXLGbL9j0UFcWBsWlATyTo%2F9DL4KtuhpPwO4gxmnWpPtTAhtIyQAhTAwTj%2FSCQTCZmRLCa4iKX4rjHcnEQ16Oh%2FjqvO9r%2FupXmlmpiC1fPjqBzOYJsCqNDrMlhTI6zp9ajdci5ll5On1iD0SFDX3ooceOzAQuIAjGKx9eeA7D12EYcNfnWnIiP47oYrXFcfzagRCGiUI6ws2YHVmseXX3CtuObAYh4UazRWNf8G0AEpSIYDA%2Fb7k03RKKTo1%2BItQZrNK4XnQ2ICCKKB2132duwHwvcb%2B3A8QsmT%2BAXIlNRI35sBiBickFaxcorOHS%2BgluNjfmGwrJKoIPC8sopQNBhGkRM%2FjdeqY5eCIOg1lrr8B8lIjrieZdrbmTq%2FwA8AAC7ufHXbAAAAABJRU5ErkJggg%3D%3D" class="tourImage"><img alt="Show settings" title="Show settings" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABmJLR0QA%2FwD%2FAP%2BgvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QkaDBM5i2PCSAAAAfBJREFUOMulkktoE2EUhb%2BZ%2BEyKTRQKgkqwzMaFtt1FrC40FGJm60JwIVSkqLUtElICFQNDQqBrQXRlQIriwomN0GJXgtI2iUkXFYJVadOXhiBERDozbmaGMR3rwrP7ueece%2B%2B5P%2FwnBOcjnVGigArI8Vgi9xdNNJ1RbI7YUlT7r%2FYDqKaZq%2Fj6tQHNbLQd6YxiNBp1I51RDPdaw6pFAcR0RolaZKur19vmZhwFePDwPvFYQgZyACKgDt4cMp4%2BmzAA9fatETbX15A6Jer1r%2Fdas4ndGRUsMYBgFW8MDBqatiXoum7oukZhfk4ovC8CyDsFK7R0sBHpu0i5UmG59gUgGY8l7v7zjE68yr80SpUS3Sd7KJYLmBNMArqrQTCSOgzUrPeVkE7XCYmjR47RbDZ5N%2FcWtzU8TvH4cJi%2BUCcdAS%2FZmU2Ot39LLn1eOtd9qoeAP8BKbfnyhfD5%2Bemp11XAABCDkVQXUHs0JjNbXmS2vEjHQR8A5t5yLv8CSZI4e7rX%2BmR2HiJQHB8OM%2FWmxJamI%2B7zs1Fv2iOaI8vZJ4850O7nTKgXYMxpAMDuXR72%2BA7x88cvsvkFgHCrSS6vUv1Y%2FSNsEWBl4zv7fQHa9np4PvMBIPxpcnTaSTRNkmvrqwtA0r5CMJK6BEw4uNvEO%2BE3N%2BLV9uq8VLwAAAAASUVORK5CYII%3D" class="tourImage"><img alt="Send a message to the author." title="Send a message to the author." src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKLSURBVDiNfZPNbxNXFMV%2Fd2bMjDtYiZMYJRhivgoxiRtACV8SXXRLhdQdUrsICzb9D5DYVwWxqopYtkLdFLGBVt1WbVWh7mhiywgFMFEkKLKdEI8%2F5uPdLpwEVTE90tu8d9%2B595zznqgqg9BqncqJRCcskmlgHEbVUK84sf2nO7S4vFUngwiC4KMSxlwU0QNgJrq16iUAt1D8TdA1FetH3y%2F%2FAODs7Dw7I8bkxTJvgdlurXo2e7yDiEejLB97halVUd0TbMyk%2FMzSd%2F%2BZoNmcG3JTncvdWuXO1t7Q1F9q2%2FMCoLqmzUpWts52FYolVHV7tVrTJ%2BpLaBz%2B%2FMyY0Oj%2FIImfhPUl7smNWzc%2BtYW7URwNFyZXye99zfTIfbLHI0R2KNxGoyxE2flHjkmi7xeuXB3OjeUIw19Q85hg%2BT5h7zq73K8QkR2Xk6TSN7vjzVnGmBHPdXn40wNsywdsvAOfEyx%2FjZrmwO7r1WncQokg8BzLsiw%2B8H0OHTrMr78vYVkZRDL9jK3MeyUIWV79k8MCEBH25fPkxk7yePEltjXeL5IUqh0aZaFRFkzy5h2BTPCilt98Bwq2Y7M3f4SVlZNUqn9QnLpGo9zX7xVKQMRadQ8A7uSXWM4nNBpP%2BgSqSpzE9LodOt1xDk5%2Bxt%2BL99jtf4HrbuDUOwwP%2BcRjR0mlRuhF53DTl4CbmwQo7aBFc73J%2BTMXaLcDPG8%2FIk%2Bx5DnQwLY9RvwPefrMJZ0%2BQmbTnj6BUZLEMFOc5e3GOiZJQLIop0l0vh9dDL0IisdGeV5bRtX0CZyUU0%2BSeHT%2FvgJRFJL20ttG7fxmShj2OFg4TLvTxkk5dccYWfj29jd34yQefm9mA%2BDYzppBFv4FO4Au%2FTAT%2FmYAAAAASUVORK5CYII%3D" class="tourImage"></div><div id="gctour_tourHeader"><img id="inconsistentTour" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIwSURBVDiNjdO9T5NRHMXx7%2B%2Fe573tU%2FoUCpTy1kjlTTExIRol0ZiY4OTE0iZuuhgHIxvRuGhcUAeMcXNwcwH%2FARcHjUpYTExUEsWQ6CAEWiiFXhc1QYvhLHc593OXc8UYQ6MsXJACyn4mZqdcM%2FXzRx%2Bbz416quFtQDnBk47j431to%2BdGHMt5uGev4eslORvrOTIUtmQk2ZpRXnbw1EJRRvcHiIhOJGda%2BoZ98SOUl6Tl4CFPfP%2FBvoC3RSYSPSNZ11WojiFUtp%2FAtyWWGxiYL8n4f4Hnp8Vy48l7UbY9EMtBpbKo5jxYFs1dXYH2%2FRluitoTaOrgYjzXFzpSRbUXmJyeZXJ6Ft3ej6drxNvymfmPFBsCby5JoILErSgdBOIGqGQLzaFNpslBRR2I45LOhDFl%2B9Mfroj7D6A2uNaUydh2vYLuHMRsb5BN2WQjG7Ozie4cxmWDMJ32yytc3gW8m5DIcrzJVIJAEhESC2G7QnezTb7Vhe0KEqYRSxM5qzED11%2BWJPwD1DxuJELXsswGunsQamWorjHWH3CsV8P6EpS%2FojsL2PU1wgDLF6YAZKFIzmje53Nu4OQK2IfP%2FB4E%2BuRdAHZeXAVjwNTZej3H1vIin5ap7BgOWGjuNMWxtami23upb64iokAUS09LgGCq64DBmDq6awDr2yKpOPrHGrctYCzuYQNsvZrbNZLUr7P693qAwMNdKXPCMoZHX74zZQxug97eETaV4b7s9Z33m5%2BP5JF%2FA6jokgAAAABJRU5ErkJggg%3D%3D" style="float:right;padding:3px;display:none"><u id="tourName">Tour 2</u> <span style="font-size: 66%; background-color: rgb(255, 247, 193);" id="cachecount">(0)</span><span id="webcode" style="display:none;"><br>Webcode: <b><a href="http://gctourdev.madd.in/tour/" title="View on map" target="_blank">undefined</a></b> </span><br><img style="opacity: 0.5;" alt="Rename" title="Rename" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAKQ2lDQ1BJQ0MgcHJvZmlsZQAAeNqdU3dYk%2FcWPt%2F3ZQ9WQtjwsZdsgQAiI6wIyBBZohCSAGGEEBJAxYWIClYUFRGcSFXEgtUKSJ2I4qAouGdBiohai1VcOO4f3Ke1fXrv7e371%2Fu855zn%2FM55zw%2BAERImkeaiagA5UoU8Otgfj09IxMm9gAIVSOAEIBDmy8JnBcUAAPADeXh%2BdLA%2F%2FAGvbwACAHDVLiQSx%2BH%2Fg7pQJlcAIJEA4CIS5wsBkFIAyC5UyBQAyBgAsFOzZAoAlAAAbHl8QiIAqg0A7PRJPgUA2KmT3BcA2KIcqQgAjQEAmShHJAJAuwBgVYFSLALAwgCgrEAiLgTArgGAWbYyRwKAvQUAdo5YkA9AYACAmUIszAAgOAIAQx4TzQMgTAOgMNK%2F4KlfcIW4SAEAwMuVzZdL0jMUuJXQGnfy8ODiIeLCbLFCYRcpEGYJ5CKcl5sjE0jnA0zODAAAGvnRwf44P5Dn5uTh5mbnbO%2F0xaL%2Ba%2FBvIj4h8d%2F%2BvIwCBAAQTs%2Fv2l%2Fl5dYDcMcBsHW%2Fa6lbANpWAGjf%2BV0z2wmgWgrQevmLeTj8QB6eoVDIPB0cCgsL7SViob0w44s%2B%2FzPhb%2BCLfvb8QB7%2B23rwAHGaQJmtwKOD%2FXFhbnauUo7nywRCMW735yP%2Bx4V%2F%2FY4p0eI0sVwsFYrxWIm4UCJNx3m5UpFEIcmV4hLpfzLxH5b9CZN3DQCshk%2FATrYHtctswH7uAQKLDljSdgBAfvMtjBoLkQAQZzQyefcAAJO%2F%2BY9AKwEAzZek4wAAvOgYXKiUF0zGCAAARKCBKrBBBwzBFKzADpzBHbzAFwJhBkRADCTAPBBCBuSAHAqhGJZBGVTAOtgEtbADGqARmuEQtMExOA3n4BJcgetwFwZgGJ7CGLyGCQRByAgTYSE6iBFijtgizggXmY4EImFINJKApCDpiBRRIsXIcqQCqUJqkV1II%2FItchQ5jVxA%2BpDbyCAyivyKvEcxlIGyUQPUAnVAuagfGorGoHPRdDQPXYCWomvRGrQePYC2oqfRS%2Bh1dAB9io5jgNExDmaM2WFcjIdFYIlYGibHFmPlWDVWjzVjHVg3dhUbwJ5h7wgkAouAE%2BwIXoQQwmyCkJBHWExYQ6gl7CO0EroIVwmDhDHCJyKTqE%2B0JXoS%2BcR4YjqxkFhGrCbuIR4hniVeJw4TX5NIJA7JkuROCiElkDJJC0lrSNtILaRTpD7SEGmcTCbrkG3J3uQIsoCsIJeRt5APkE%2BS%2B8nD5LcUOsWI4kwJoiRSpJQSSjVlP%2BUEpZ8yQpmgqlHNqZ7UCKqIOp9aSW2gdlAvU4epEzR1miXNmxZDy6Qto9XQmmlnafdoL%2Bl0ugndgx5Fl9CX0mvoB%2Bnn6YP0dwwNhg2Dx0hiKBlrGXsZpxi3GS%2BZTKYF05eZyFQw1zIbmWeYD5hvVVgq9ip8FZHKEpU6lVaVfpXnqlRVc1U%2F1XmqC1SrVQ%2BrXlZ9pkZVs1DjqQnUFqvVqR1Vu6k2rs5Sd1KPUM9RX6O%2BX%2F2C%2BmMNsoaFRqCGSKNUY7fGGY0hFsYyZfFYQtZyVgPrLGuYTWJbsvnsTHYF%2Bxt2L3tMU0NzqmasZpFmneZxzQEOxrHg8DnZnErOIc4NznstAy0%2FLbHWaq1mrX6tN9p62r7aYu1y7Rbt69rvdXCdQJ0snfU6bTr3dQm6NrpRuoW623XP6j7TY%2Bt56Qn1yvUO6d3RR%2FVt9KP1F%2Brv1u%2FRHzcwNAg2kBlsMThj8MyQY%2BhrmGm40fCE4agRy2i6kcRoo9FJoye4Ju6HZ%2BM1eBc%2BZqxvHGKsNN5l3Gs8YWJpMtukxKTF5L4pzZRrmma60bTTdMzMyCzcrNisyeyOOdWca55hvtm82%2FyNhaVFnMVKizaLx5balnzLBZZNlvesmFY%2BVnlW9VbXrEnWXOss623WV2xQG1ebDJs6m8u2qK2brcR2m23fFOIUjynSKfVTbtox7PzsCuya7AbtOfZh9iX2bfbPHcwcEh3WO3Q7fHJ0dcx2bHC866ThNMOpxKnD6VdnG2ehc53zNRemS5DLEpd2lxdTbaeKp26fesuV5RruutK10%2FWjm7ub3K3ZbdTdzD3Ffav7TS6bG8ldwz3vQfTw91jicczjnaebp8LzkOcvXnZeWV77vR5Ps5wmntYwbcjbxFvgvct7YDo%2BPWX6zukDPsY%2BAp96n4e%2Bpr4i3z2%2BI37Wfpl%2BB%2Fye%2Bzv6y%2F2P%2BL%2FhefIW8U4FYAHBAeUBvYEagbMDawMfBJkEpQc1BY0FuwYvDD4VQgwJDVkfcpNvwBfyG%2FljM9xnLJrRFcoInRVaG%2FowzCZMHtYRjobPCN8Qfm%2Bm%2BUzpzLYIiOBHbIi4H2kZmRf5fRQpKjKqLupRtFN0cXT3LNas5Fn7Z72O8Y%2BpjLk722q2cnZnrGpsUmxj7Ju4gLiquIF4h%2FhF8ZcSdBMkCe2J5MTYxD2J43MC52yaM5zkmlSWdGOu5dyiuRfm6c7Lnnc8WTVZkHw4hZgSl7I%2F5YMgQlAvGE%2Flp25NHRPyhJuFT0W%2Boo2iUbG3uEo8kuadVpX2ON07fUP6aIZPRnXGMwlPUit5kRmSuSPzTVZE1t6sz9lx2S05lJyUnKNSDWmWtCvXMLcot09mKyuTDeR55m3KG5OHyvfkI%2Flz89sVbIVM0aO0Uq5QDhZML6greFsYW3i4SL1IWtQz32b%2B6vkjC4IWfL2QsFC4sLPYuHhZ8eAiv0W7FiOLUxd3LjFdUrpkeGnw0n3LaMuylv1Q4lhSVfJqedzyjlKD0qWlQyuCVzSVqZTJy26u9Fq5YxVhlWRV72qX1VtWfyoXlV%2BscKyorviwRrjm4ldOX9V89Xlt2treSrfK7etI66Trbqz3Wb%2BvSr1qQdXQhvANrRvxjeUbX21K3nShemr1js20zcrNAzVhNe1bzLas2%2FKhNqP2ep1%2FXctW%2Fa2rt77ZJtrWv913e%2FMOgx0VO97vlOy8tSt4V2u9RX31btLugt2PGmIbur%2Fmft24R3dPxZ6Pe6V7B%2FZF7%2BtqdG9s3K%2B%2Fv7IJbVI2jR5IOnDlm4Bv2pvtmne1cFoqDsJB5cEn36Z8e%2BNQ6KHOw9zDzd%2BZf7f1COtIeSvSOr91rC2jbaA9ob3v6IyjnR1eHUe%2Bt%2F9%2B7zHjY3XHNY9XnqCdKD3x%2BeSCk%2BOnZKeenU4%2FPdSZ3Hn3TPyZa11RXb1nQ8%2BePxd07ky3X%2FfJ897nj13wvHD0Ivdi2yW3S609rj1HfnD94UivW2%2FrZffL7Vc8rnT0Tes70e%2FTf%2FpqwNVz1%2FjXLl2feb3vxuwbt24m3Ry4Jbr1%2BHb27Rd3Cu5M3F16j3iv%2FL7a%2FeoH%2Bg%2Fqf7T%2BsWXAbeD4YMBgz8NZD%2B8OCYee%2FpT%2F04fh0kfMR9UjRiONj50fHxsNGr3yZM6T4aeypxPPyn5W%2F3nrc6vn3%2F3i%2B0vPWPzY8Av5i8%2B%2Frnmp83Lvq6mvOscjxx%2B8znk98ab8rc7bfe%2B477rfx70fmSj8QP5Q89H6Y8en0E%2F3Pud8%2Fvwv94Tz%2B4A5JREAAAAGYktHRADVAJ8AvxXHGoYAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfZBwcIASdkENZ8AAABgUlEQVQ4y5VTvUtCURT%2FmUmSWCqaSUtbEA1R4GRfFARBNfV%2FRNYUjY1JTY0N4VAiDdEgSNIQTUVDtgZBiPmBVkrq8%2FwaHj6VZ6%2B8cOGcc%2Fl9nHPvBbpckeAWW%2FOebsHjE6ttJKZGcH4WphHYVn3EqLKi5c9Pl9g4CJk0MEmKkPV6nYqisFarslqpsFL55tXpDpXXMJMnCSZPEmx10NvUINLplE75IX6I5blJpLNFjC0CF0f3CGwHgYNQO4EI4fEMgUKQ6o5H9jSw1z2I2M0j6J9GxyEKBZnMO7K5DHL5bEdwYH1X57B5C0K4XG44nS7V9oK%2FHby2C4p%2Bzs0WSOTzWe0g%2FZ6B1zuM2PUdppY2US6XYO2zGhCIwOFwQkhEo7dqMfmiKpMgBWLkABQUigUAwP5xRCuXyyUttlgsvxOQhN0%2BoN0AKZBGLKLVDVogPr8%2BDJ%2By2Ww2ciCw9dtUVaiqQgKi5oqigCI6gn%2F%2FhcaamZ2Hzzdi0hEAQCr19idJKxgAfgDG6PPJecMc5gAAAABJRU5ErkJggg%3D%3D" class="tourImage"><img style="opacity: 0.5;" alt="Printview" title="Printview" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9oIGQopDsx58QcAAAHySURBVDjLpZNNaxNRFIafuWYRQRCLoCnTQIsfFAwxGFGQLBVRXPqJQfFHCEqd2iIupK6q7lwIfiVZ6EKrVkRGjQUDlRJQIVqoRd0Ixk7aTGbm3uuqTYbUVPDC4XIOnOe897xc%2BM9jtCb5Qm4IsP6hb%2FjI4aODbdV8IacbjUbHcF1X5ws5vdgTWQ5fKpX%2BOjqdTofyZQGJRKL5RsMI3VrrzgClFOVyGQAhRBsolUqtrMA0TYQQGIbRFisq0Fpj2%2FbSRCEEmUyGkddZ6t4co8cn2m28YA0MAVY0GmXL5q0opULyAZ7PX6W7q5cP3yZJ%2Fsriui7A8KICa9C6iJQS3%2FcBOP9wP1oFeCrAkwHd6zbRH9uF487zsj7K7TNTXL9xzYq0LqlSqRCLxbBtm0B57N12CqkVUkkUmu%2FVWRI9e6h5dQ7ejHOAs80dOI6DW69TrVZJJpM8sj2kVsz8rOCrgED5%2BNJnruGwvSdDzV%2Fg7vSlJkAIwZzjMD7%2BjFqthtvrEsiADWvjBFIiteLH7690rdnI5GyR4uci2VUDYReklOxI7wTg45cct96O4CkPN%2FDpW9%2FP7r59lGbe8OLTK3KHJhh78rgJ8DwP0zSX7LscHwu5cOJBGkOs5t30FE9PvkcpFbLxHnCs0%2Fe7o67gK8npyLnW8v0%2F5Gb7fMJoZowAAAAASUVORK5CYII%3D" class="tourImage"><img style="opacity: 0.5;" alt="Send to GPS" title="Send to GPS" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9oIGQooOW3fZUkAAAFtSURBVDjLrZPLK0RhGMZ%2Fx62UEimSo0wihSxphhXKwsLGdsrextKt2fAnsJGVlX%2FAwqXIIRPCSpHLjEjJdcJ857vYOBhzjhRPfX3f4n1%2Bve%2FT%2B1l8ynx5W%2FxSOfxRQQDzHx38CmJ9L3aTXQDk24tBtf4Az%2Bind5gvIM%2BnMEM%2FgbMAALHxGJG2MACdPZ%2FmwbkO8yIemRnYs34M0TN%2FV1oKqsoa6J%2BuN4EZ5NuLxMZjANzWLWG0RGiJUJLKklqa7Qjx0xX2L7ZYGrq2fEeItIVZ33SQWtDVGEUZjdIKjeHyPkmTHSYlXribWDU7I8LKAnhzD8y2oIzm%2FOYIV0ukdnGVy2P6iRa7nZT7zP2YY%2FKCEo8uJJFKUl5cjVQKZTRXDwlKiyrYTTo4xw5nE1hZGXh331QNr0IgtOBVuoTKGmgNdbOd2GD5cI3EZDozA8%2Fsab63NmM3nicPsHIKiZ%2Fsf5j9dj%2FoEBotMPZwbtb%2FeAM%2Bw7BUpUnjdQAAAABJRU5ErkJggg%3D%3D" class="tourImage"><img style="opacity: 0.5;" alt="Download GPX" title="Download GPX" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9oIGQotDqgVNAMAAAG4SURBVDjLlZPPaxNBFMc%2Fs41CD1oMlVp1FUIPBhR6UxCPestucvIiqPtn%2BAOyET2I5yoUAmL%2FgMwS9OTBH%2FGgqHgT%2FAF1QTwYLG01yezsjKeN3TS25J3mveH74715I5rN5qM4ji8xQbiuSxAEAoAwDO2kEYahzcgK2aHb7WKMAUAIMVRzHCenXiwWc%2FmQwBhDu90eXnieRxRFw9z3%2FbHtOKOFSqWC53m7ArcRZLaFEDllKeWOBIXRQgbOCHdzkCPIrI8D15%2FU6Kl1lq%2B%2B%2F38LURQhhEBKmXsJgIFWHJ0tc%2FHBiZ0dSCnxfZ%2F6Yw9rNMpoVKo5fGCB8vxpNvq%2FedFbGk%2BwdZDaKM6fvExqDalJMVi%2Br8Wccs%2ByqXr8uv3Mvr2uRGErWEpJtVql1WrRR5Faw%2BrPTyRGo01CkiasDzZYdM%2Bxmfxh7WbH5vYgG1qtVqOv%2B%2BhUMzdzjEP7jzM%2FU2LP1DQH9x3hXdyh87nDl1v8czC6oj094OGreyij6OuE0myZM6ULvFl9ydOPz%2Fl2BwFQcF13pdFobPuNi1zJ5a0fdxHONK%2B%2FfqC%2BcH8pIGCiKN3Ya91rU3a0%2FheAk99ghKc72QAAAABJRU5ErkJggg%3D%3D" class="tourImage"><img style="opacity: 0.5;" alt="View on map" title="View on map" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9sBEQ0rMteXYLwAAAKiSURBVDjLlZPLaxRBEIe%2F3Z11N%2FvMxpFoXgfRQDBCRGIEEQQfIOJBEERRFG8eQvCg%2FgMiHjzpQcQHBvTiTRAVMSpqVAxEgxoMxmiMT5KY7EzPTM9Mz4yHmCwqItalmh%2FFr7%2FqroqtWrsqam5dipZI8L8xOPAarbl1KedOnftnsaOcP7TOg51oszfHgsuIW88o9diMH2kim88xNPSIQXGWrxMG2Vyeb5MGCS2JYUn2bYlIaSnis25GeZJyq4YhBPaNQYT4gmkKYm4%2Fjm1gCRPPETiOQElrjkKbPRSK84kin0yXDsf6SW3Xqa2rI%2BO%2FxVHN5Et50sk4WnIewpYkEhKgQlCe%2Fo6wppnSFUZJ4VwZhiAksh%2FguwJpOfiujSOm8Vz7T4Jidf3PXINxQFI6PYlat4iU7tLkTpDMN5LWYiRTSUzLA4wZgkRsxkNKF0vYGOVJzGzAVDPI7pGZIu86115s5fbIFqQQhF7lDeZaqKqqRq%2FWKRQbyOcWkNzTRtWoRtqrpV7%2FhKs8GvQWrg5vpq3%2BPMl4%2FNcWzLKFISQ6U%2FR9%2BsrNV31EGxTe42G8QFFXWkLLog5MaXG4p5uTO3b%2B9gvVCzGUy2Nh895No0KPja17CaKQIAwIifg8PcbyxjUIz2HPxQ7a2F0xeDL2jr6PQxRyGSxbIJVHEIWMTrzBDxUq9PEDH8M1aWtci%2FBt7skLMwaOchgPfLKpLKV0AS%2BjkEqiAkVtsQkVBARRyJfyB2pyC%2Bkf66V3uJf1xv4KQZ4CTsomEWXJxFwc5dL96ARe6CGVz2K9hdWLN9E3%2BpCe1%2Ffp6XrO8aMn0YJIAdBQs5KGmsqidCzZ9svi7DrTTixexdORAe4cGpjTY%2B1r2qNlK1qYnYe%2Fxd3iJfwwYJO5d057%2BewFPwAsnUE8ZPBqbQAAAABJRU5ErkJggg%3D%3D" class="tourImage"><img style="opacity: 0.5;" alt="Upload tour" title="Upload tour" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9oIGQoqEWpcrzEAAAMVSURBVDjLlZPfa1t1AMU%2F33tvE5pmSZvfSZfWXlNnF7sfsrjqnqq4OUUQRFHZkJWhD4ooDIXpg4gWhPkH%2BCBWHJtPUwYyGSpspdN1raOyYqWlW5N2bZqmTdsk9%2Fbm3vv1ycn65ufxcM55OHAE23jl%2FaE3gTdUTdstwStdtyYlo4qqnD03eOzr7X5xL%2FjBN%2Fs8qvJTd1ci3renk672MD6vl7WqwUyhxPhkgen88g0hxMlzg8f%2BvK%2Fg5fe%2ByrUEmq%2B%2F0L9X7O2OsVY1KN3No%2Flj0NwG9RLt8TCjkwtcGp4sI8ST%2F5ZoAOGw%2F%2BfDh7KiVw%2BxurJEpCNLMJKkbjZYKsyiuRaKY%2FBUTsdxZfjytb%2B%2BBB4HUAY%2B%2FPbTRKwt0J%2FL0KS42JofFEGTpuFp0vB5NeLhHSRjUaKtLeSyO%2BlMhfpeO332BIASCPpOHsh2UFlbobjlI5Z6ACnBlYBQEK7F4mqNH67c4vLwOEGvZHcmBfASgLZZb0Q7E22MTi%2Bjd8dw5X%2FLViurPLYvixACKSULi0VMwyAZDQIcANBMy1a8Xg%2BKP0alauK4Er9XxXEcrGoJISIAvHu%2BH8Pa4Nn4GaLpXQAhAEVVFXe9ZtJizuM38iyX1rhT3OB2cZO5so3VaLBZrbFlW%2ByM9PBd%2Fi1qhgWwCqA1KcrS7fmV1P5MAj2dZK6wwPDMBmOLA0jX5tfzNpZjk2rL0JM8yKZZ48zIE8T4YgxAk45z4ebU%2FNtZPQZAZ7qdwI51fl%2BwePqR13Gki%2BM6uEjuVgr0pg9RtQzGjIGjAOrNqxcuZXLPnxKq6gm2NNHsUflt%2FBYTqxfJxPcztzJNuVaiXC1St6psmBs8GO2lbhvU9xQ%2B1gAqyyvHr9xwv3ddeHRXnB8n1jF9JrZjEw92YDsOjnRZXM8T8if4ozDCyMwIdz5D3PvCcyc%2Bf7VDTw8Fgq2eh%2FUEF%2FMvYloWlmth2g30SA99%2BmHG8tf4Zeoq%2BcEtcd%2BZAFpDXZ4jx08NqV7fM6haKwghpWtLuzH7d%2Bidh3pTBxmdnWDqk7Lg%2F6J%2F5JHp06rcrv8D001PzAwk7SYAAAAASUVORK5CYII%3D" class="tourImage"><img style="opacity: 0.5;" alt="Add own waypoint" title="Add own waypoint" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAFQSURBVDiNpZM7SwNBFIXPTB47TYioMAErLSz9BYJFIJ2FheA%2FEO2CTTB1go2ktrMSxFIQjFgIgkU6SxtthAyIGC0yz10LzSaz7AYlt7pzOXzcc7hDoijCLJVPG9aa5b5zIZ%2Bc5XJUdFuDyp8AzoW8tXvszZonBzxNmwoAAGMVnt%2FuAQDLi%2BtZsikAp2CdjfupgNphue%2FCsWcWBNIYxZx1PwCjwIJAVhulOPEcpaLbHlTyAODCkNd36pNgltxgb2ufAQB%2BEZ3zDvcsGKPw%2Bv6YuuaL6Hnvpfk13wIAaCNhrc30OlnayBSAlVgorXhC8fEEAOBzqz7AJgCUEnF6dRaHWCwU5PbG5jhELXFxdym1MWykoZSIGHDT%2FvQurNooRcqOQ1RWQRvDbo%2B%2BSNJO5h1oPcRoA62HWbJsgDJDsGI57v8FoISI694DT87StGTW7%2FwNezmaY41c7QEAAAAASUVORK5CYII%3D" class="tourImage"><img style="display: inline; opacity: 0.5;" alt="Delete this tour" title="Delete this tour" src="data:image/gif;base64,R0lGODlhEgASANUlAJaWluXl5dfX197e3pSUlNnZ2aampre3t3p6eubm5qioqLW1taenp9zc3LOzs7a2toGBgdra2t3d3YuLi3x8fKSkpHV1dc%2FPz%2BHh4ZiYmH5%2BfpeXl4qKioyMjMXFxaKior%2B%2Fv8vLy9DQ0LS0tDs7OwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACUALAAAAAASABIAAAZ4wJJwSCwaj8gjaZkcLp9QJOkhGHgACM2EQzJCv9EiaQSKBEQGAiHT9Y5IGFKBpCAB2uJ3gNQgOUgfeEQkCyR7EmN0gk4PJAl8iQyLQiQHjnKRkyWEhiQCfiQbmiQVJAMkFyQGJBSjCAAHISMAHRAWmptgTE28vUdBADs%3D" class="tourImage" id="gctourDeleteButton"></div><div style="overflow: auto; height: 713px; width: 100%;" id="gctour_geocacheList"><ul style="" class="cachelist ui-sortable" id="cacheList">The list is empty.</ul></div><div style="position: absolute; bottom: 0px; font-size: 75%; width: 100%; height: 14px;" id="gctour_footer"><div style="width: 100%;"><a title="http://gctour.madd.in" href="http://gctour.madd.in/" style="padding-left: 5px;">http://gctour.madd.in</a><div style="float: right; margin-right: 5px;">v 2.3.12356</div></div></div></div><div id="fancybox-tmp"></div><div id="fancybox-loading"><div></div></div><div id="fancybox-overlay"></div><div id="fancybox-wrap"><div id="fancybox-outer"><div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div><div id="fancybox-content"></div><a id="fancybox-close"></a><div id="fancybox-title"></div><a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a><a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a></div></div><div id="tiptip_holder" style="max-width:200px;"><div id="tiptip_arrow"><div id="tiptip_arrow_inner"></div></div><div id="tiptip_content"></div></div><div style="display: block;"></div></body></html>
\ No newline at end of file diff --git a/tests/res/raw/map1.png b/tests/res/raw/map1.png Binary files differnew file mode 100644 index 0000000..e97be77 --- /dev/null +++ b/tests/res/raw/map1.png diff --git a/tests/res/raw/map11.png b/tests/res/raw/map11.png Binary files differnew file mode 100644 index 0000000..414da1d --- /dev/null +++ b/tests/res/raw/map11.png diff --git a/tests/res/raw/map2.png b/tests/res/raw/map2.png Binary files differnew file mode 100644 index 0000000..3f9d88e --- /dev/null +++ b/tests/res/raw/map2.png diff --git a/tests/res/raw/map3.png b/tests/res/raw/map3.png Binary files differnew file mode 100644 index 0000000..212627c --- /dev/null +++ b/tests/res/raw/map3.png diff --git a/tests/res/raw/map4.png b/tests/res/raw/map4.png Binary files differnew file mode 100644 index 0000000..51364a8 --- /dev/null +++ b/tests/res/raw/map4.png diff --git a/tests/res/raw/map5.png b/tests/res/raw/map5.png Binary files differnew file mode 100644 index 0000000..219e2c6 --- /dev/null +++ b/tests/res/raw/map5.png diff --git a/tests/res/raw/map_all14.png b/tests/res/raw/map_all14.png Binary files differnew file mode 100644 index 0000000..7c701d9 --- /dev/null +++ b/tests/res/raw/map_all14.png diff --git a/tests/res/raw/tb29ggq.htm b/tests/res/raw/tb29ggq.htm new file mode 100644 index 0000000..4baba57 --- /dev/null +++ b/tests/res/raw/tb29ggq.htm @@ -0,0 +1,1173 @@ +
+<!DOCTYPE html>
+<html lang="en" class="no-js">
+<head id="ctl00_Head1"><meta charset="utf-8" />
+ <!--[if IE]><![endif]-->
+ <title>
+ (TB29GGQ) Travel Bug Dog Tag - Courageous Carrot
+</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta name="author" content="Groundspeak, Inc." /><meta name="DC.creator" content="Groundspeak, Inc." /><meta name="Copyright" content="Copyright (c) 2000-2012 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2012 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><meta http-equiv="X-UA-Compatible" content="IE=8" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/reset.css" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/typography.css" /><link rel="stylesheet" type="text/css" media="screen,projection" href="../css/blueprint/src/grid.css" />
+ <!--[if lt IE 8]>
+ <link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/ie.css" />
+ <![endif]-->
+ <link id="uxCssMaster" rel="stylesheet" type="text/css" media="screen,projection" href="../css/tlnMasterScreen.css?r=1" /><link id="uxCssMain" rel="stylesheet" type="text/css" media="all" href="../css/tlnMain.css?r=1" /><link rel="Stylesheet" type="text/css" media="all" href="../css/jqueryui1810/jquery-ui-1.8.10.custom.css" /><link rel="stylesheet" type="text/css" media="all" href="/js/jquery_plugins/jquery.jgrowl.css" /><link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" />
+ <script type="text/javascript" src="/js/modernizr-1.7.min.js"></script>
+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.min.js"></script>
+ <script type="text/javascript" src="/js/jquery.truncate.min.js"></script>
+
+ <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" />
+ <style type="text/css" media="screen">
+ .MasterPageAds{
+ margin-top:0;
+ }
+ .CoordInfoLinkWidget{
+ margin-right:-175px;
+ }
+ * + html .CoordInfoLinkWidget{ /* IE7 Hack */
+ margin-right:0;
+ position:relative;
+ right:-165px;
+ }
+ ul.imagelist li, ul.log_images li
+ {
+ list-style-image: none !important;
+ list-style-position: outside !important;
+ list-style-type: none !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ }
+ ul.log_images li
+ {
+ float: left;
+ margin-right: 5px !important;
+ }
+ ul.pager
+ {
+ padding: 0 !important;
+ margin: 5px 0 !important;
+ width: 100%;
+ overflow: hidden;
+ }
+ ul.pager li
+ {
+ display: inline;
+ float: left;
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ margin: 0 !important;
+ padding: 0 !important;
+ }
+ ul.pager li.pager-info
+ {
+ margin: 2px 5px 0 0 !important;
+ }
+ ul.pager li.pager-current
+ {
+ border: 1px solid #003F7E;
+ color: #c00;
+ float: left;
+ font-weight: bold;
+ margin: 0 5px 0 0 !important;
+ padding: 1px 5px !important;
+ }
+ ul.pager li a
+ {
+ background-image: none;
+ border: 1px solid #ccc;
+ display: block;
+ float: left;
+ margin: 0 5px 0 0;
+ padding: 1px 5px;
+ text-decoration: none;
+ }
+ ul.pager li a:hover
+ {
+ border: 1px solid #003F7E;
+ }
+ .LogImgTitle, .LogImgDescription
+ {
+ text-align: center !important;
+ width: 100%;
+ }
+ .TrackableItemOptionsTable
+ {
+ clear:both;
+ }
+ </style>
+<meta name="og:site_name" content="Geocaching.com" property="og:site_name" /><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:url" content="http://www.geocaching.com/track/details.aspx?tracker=tb29ggq" property="og:url" /><meta name="og:description" content="I am part of a gang of vegetables (see pic)
+I want to travel and have adventures. Please help me! I love pics of my exploits too!
+Move me on far and fast and help me have FUN!" property="og:description" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/14.png" property="og:image" /><meta name="og:title" content="Courageous Carrot" property="og:title" /></head>
+<body >
+ <form name="aspnetForm" method="post" action="details.aspx?tracker=tb29ggq" id="aspnetForm">
+<div>
+<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
+<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
+<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="3" />
+<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTM3NDI4MjQ0OA8WAh4MVEJEZXRhaWxzLklEKClZU3lzdGVtLkludDY0LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkHMTcxOTkzNhYCZg9kFgZmD2QWCgIGDxYCHgRUZXh0BWI8bWV0YSBuYW1lPSJDb3B5cmlnaHQiIGNvbnRlbnQ9IkNvcHlyaWdodCAoYykgMjAwMC0yMDEyIEdyb3VuZHNwZWFrLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuIiAvPmQCBw8WAh8BBUc8IS0tIENvcHlyaWdodCAoYykgMjAwMC0yMDEyIEdyb3VuZHNwZWFrLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuIC0tPmQCGg8WAh4EaHJlZgUdfi9jc3MvdGxuTWFzdGVyU2NyZWVuLmNzcz9yPTFkAhsPFgIfAgUVfi9jc3MvdGxuTWFpbi5jc3M/cj0xZAIgDxYCHgdWaXNpYmxlaGQCAQ9kFhACBQ8WAh8BZGQCCA8WAh8DZxYIAgEPDxYCHghJbWFnZVVybAVOaHR0cDovL2ltZy5nZW9jYWNoaW5nLmNvbS91c2VyL2F2YXRhci82NDJkMjc3MS00MjRlLTRlZTYtYmViNi1lZmVjZGUzNDA2ZmMuanBnZGQCAw8WAh8BBXRIZWxsbywgPGEgaHJlZj0iL215L2RlZmF1bHQuYXNweCIgdGl0bGU9IlZpZXcgUHJvZmlsZSBmb3IgQmFuYW5ld2VpemVuIiBjbGFzcz0iU2lnbmVkSW5Qcm9maWxlTGluayI+QmFuYW5ld2VpemVuPC9hPmQCBQ8PFgIeC05hdmlnYXRlVXJsBYYBaHR0cHM6Ly93d3cuZ2VvY2FjaGluZy5jb20vbG9naW4vZGVmYXVsdC5hc3B4P1JFU0VUPVkmcmVkaXI9aHR0cCUzYSUyZiUyZnd3dy5nZW9jYWNoaW5nLmNvbSUyZnRyYWNrJTJmZGV0YWlscy5hc3B4JTNmdHJhY2tlciUzZHRiMjlnZ3FkZAILDxYCHwEFEDMyOCBDYWNoZXMgRm91bmRkAg0PFgIfA2cWAgINDw8WAh8FBUB+L3RyYWNrL3NlYXJjaC5hc3B4P289MSZ1aWQ9MzE4OTI2NzgtMTExNy00NmViLWFhM2ItMTkxYzIwYmQ2NjA3ZGQCEA8PFgIfA2dkZAIsD2QWBAIDDxYCHwEFB0VuZ2xpc2hkAgUPFgIeC18hSXRlbUNvdW50AhAWIGYPZBYCAgEPDxYIHg9Db21tYW5kQXJndW1lbnQFBWVuLVVTHgtDb21tYW5kTmFtZQUNU2V0VGVtcExvY2FsZR8BBQdFbmdsaXNoHhBDYXVzZXNWYWxpZGF0aW9uaGRkAgEPZBYCAgEPDxYIHwcFBWRlLURFHwgFDVNldFRlbXBMb2NhbGUfAQUHRGV1dHNjaB8JaGRkAgIPZBYCAgEPDxYIHwcFBWZyLUZSHwgFDVNldFRlbXBMb2NhbGUfAQUJRnJhbsOnYWlzHwloZGQCAw9kFgICAQ8PFggfBwUFcHQtUFQfCAUNU2V0VGVtcExvY2FsZR8BBQpQb3J0dWd1w6pzHwloZGQCBA9kFgICAQ8PFggfBwUFY3MtQ1ofCAUNU2V0VGVtcExvY2FsZR8BBQnEjGXFoXRpbmEfCWhkZAIFD2QWAgIBDw8WCB8HBQVzdi1TRR8IBQ1TZXRUZW1wTG9jYWxlHwEFB1N2ZW5za2EfCWhkZAIGD2QWAgIBDw8WCB8HBQVlcy1FUx8IBQ1TZXRUZW1wTG9jYWxlHwEFCEVzcGHDsW9sHwloZGQCBw9kFgICAQ8PFggfBwUFaXQtSVQfCAUNU2V0VGVtcExvY2FsZR8BBQhJdGFsaWFubx8JaGRkAggPZBYCAgEPDxYIHwcFBW5sLU5MHwgFDVNldFRlbXBMb2NhbGUfAQUKTmVkZXJsYW5kcx8JaGRkAgkPZBYCAgEPDxYIHwcFBWNhLUVTHwgFDVNldFRlbXBMb2NhbGUfAQUHQ2F0YWzDoB8JaGRkAgoPZBYCAgEPDxYIHwcFBXBsLVBMHwgFDVNldFRlbXBMb2NhbGUfAQUGUG9sc2tpHwloZGQCCw9kFgICAQ8PFggfBwUFZXQtRUUfCAUNU2V0VGVtcExvY2FsZR8BBQVFZXN0aR8JaGRkAgwPZBYCAgEPDxYIHwcFBW5iLU5PHwgFDVNldFRlbXBMb2NhbGUfAQUOTm9yc2ssIEJva23DpWwfCWhkZAIND2QWAgIBDw8WCB8HBQVrby1LUh8IBQ1TZXRUZW1wTG9jYWxlHwEFCe2VnOq1reyWtB8JaGRkAg4PZBYCAgEPDxYIHwcFBWh1LUhVHwgFDVNldFRlbXBMb2NhbGUfAQUGTWFneWFyHwloZGQCDw9kFgICAQ8PFggfBwUFcm8tUk8fCAUNU2V0VGVtcExvY2FsZR8BBQhSb23Dom7Egx8JaGRkAi8PFgIeBWNsYXNzBQdzcGFuLTIwFgICAQ9kFg4CAw9kFgJmD2QWAgIBDw8WAh8BBQdUQjI5R0dRZGQCBQ8PFgQfBAUwaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9pbWFnZXMvd3B0dHlwZXMvMjEuZ2lmHg1BbHRlcm5hdGVUZXh0BRJUcmF2ZWwgQnVnIERvZyBUYWdkZAIHDw8WAh8BBRFDb3VyYWdlb3VzIENhcnJvdGRkAg0PZBYcZg9kFgJmDw8WAh8BBSI8c3Ryb25nPlRyYWNrYWJsZSBPcHRpb25zPC9zdHJvbmc+ZGQCAQ9kFgJmD2QWAmYPDxYCHwUFMWxvZy5hc3B4P3dpZD1iMWFkOWU1ZC0xN2JkLTRkMTctOGYxMS1iOTQ4ZmQ3YjliOTdkZAICDw8WAh8DaGRkAgMPDxYCHwNnZBYCZg9kFgJmDw8WAh8FBRwvbXkvd2F0Y2hsaXN0LmFzcHg/Yj0xNzE5OTM2ZGQCBA8PFgIfA2hkZAIFDw8WAh8DaGRkAgYPZBYCZg9kFgJmDw8WAh8FBTx+L3RyYWNrL3NoZWV0LmFzcHg/Z3VpZD1iMWFkOWU1ZC0xN2JkLTRkMTctOGYxMS1iOTQ4ZmQ3YjliOTdkZAIHDw8WAh8DZ2QWAmYPZBYCZg8PFgIfBQU7L2ttbC90YmttbC5hc3B4P3RiZ3VpZD1iMWFkOWU1ZC0xN2JkLTRkMTctOGYxMS1iOTQ4ZmQ3YjliOTdkZAIIDw8WAh8DaGRkAgkPZBYCZg9kFgJmDw8WAh8BBTlUaGVyZSBhcmUgPHN0cm9uZz41PC9zdHJvbmc+IHVzZXJzIHdhdGNoaW5nIHRoaXMgbGlzdGluZy5kZAIKDw8WAh8DaGRkAgsPDxYCHwNoZGQCDA8PFgIfA2hkZAINDw8WAh8DaGQWAmYPZBYCZg8QZGQWAGQCDw8PFgIeC0J1Z1BhbmVsLklEKCsEBzE3MTk5MzZkFhYCAw8PFgYfAQUKVGVhbSBSb0tlVB8FBUxodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3Byb2ZpbGUvP2d1aWQ9OGM3MTBjZWMtNmNiNC00NDYwLTgyNzQtNWU1ZDAyMmY1YzY3HgdUb29sVGlwBRlWaXNpdCBUaGlzIFVzZXIncyBQcm9maWxlZGQCBQ9kFgICAw8PFgIfAQUaV2VkbmVzZGF5LCAwMSBPY3RvYmVyIDIwMDhkZAIHD2QWAgIDDw8WAh8BBSFOb3J0aHdlc3QgRW5nbGFuZCwgVW5pdGVkIEtpbmdkb21kZAILDw8WBh8BBTNJbiBJaHIgWmllbCBiZWZpbmRldCBzaWNoIHJlY2h0cyAoQWlycG9ydCBUQi1Ib3RlbCkfBQVbaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9zZWVrL2NhY2hlX2RldGFpbHMuYXNweD9ndWlkPTVmODU1Y2JjLTQzMzctNDIxOS05YmY0LTkwYzJmZmUwMzQ5NB8NBQ1WaXNpdCBMaXN0aW5nZGQCDQ8WAh8DaGQCDw8WAh8BBTJUaGUgb3duZXIgaGFzbid0IHNldCB0aGVpciBjb2xsZWN0aWJsZSBwcmVmZXJlbmNlLmQCEQ8PFgIfAQU0VXNlIDxzdHJvbmc+VEIyOUdHUTwvc3Ryb25nPiB0byByZWZlcmVuY2UgdGhpcyBpdGVtLmRkAhcPFgIfAQW5AUkgYW0gcGFydCBvZiBhIGdhbmcgb2YgdmVnZXRhYmxlcyAoc2VlIHBpYyk8YnIgLz5JIHdhbnQgdG8gdHJhdmVsIGFuZCBoYXZlIGFkdmVudHVyZXMuIFBsZWFzZSBoZWxwIG1lISBJIGxvdmUgcGljcyBvZiBteSBleHBsb2l0cyB0b28hPGJyIC8+TW92ZSBtZSBvbiBmYXIgYW5kIGZhc3QgYW5kIGhlbHAgbWUgaGF2ZSBGVU4hZAIcDw8WBh8EBVBodHRwOi8vaW1nLmdlb2NhY2hpbmcuY29tL3RyYWNrL2Rpc3BsYXkvYWFhMTdkNzMtYzNjOC00OTQwLTgxYTMtMTA3YjY0YWE4NmMwLmpwZx8LBQlUaGUgZ2FuZyEfA2dkZAIeDxYCHwEFEk1hZCBsb29raW5nIGNhcnJvdGQCIA9kFgICAQ9kFghmDxYCHwNoZAIBDw8WAh8DaGRkAgIPDxYCHwNoZGQCAw8WAh8DaGQCEQ8PFgQfAQWFAzxoMz5HYWxsZXJ5IEltYWdlcyByZWxhdGVkIHRvIENvdXJhZ2VvdXMgQ2Fycm90PC9oMz48dWwgY2xhc3M9ImltYWdlbGlzdCI+PGxpPjxhIGhyZWY9Imh0dHA6Ly9pbWcuZ2VvY2FjaGluZy5jb20vdHJhY2svbGFyZ2UvYWFhMTdkNzMtYzNjOC00OTQwLTgxYTMtMTA3YjY0YWE4NmMwLmpwZyIgY2xhc3M9InRiX2ltYWdlcyBsbmsiIHJlbD0idGJfaW1hZ2VzIj48aW1nIHNyYz0iL2ltYWdlcy9pY29ucy8x" />
+<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="Ni9waG90by5wbmciIGFsdD0iVGhlIGdhbmchIiAvPiZuYnNwOzxzcGFuPlRoZSBnYW5nITwvc3Bhbj48L2E+PC91bD48YSBocmVmPSJnYWxsZXJ5LmFzcHg/SUQ9MTcxOTkzNiIgdGl0bGU9J1ZpZXcgR2FsbGVyeSBJbWFnZXMnPlZpZXcgQWxsIDUgR2FsbGVyeSBJbWFnZXM8L2E+HwNnZGQCEw8PFgQeB1dwdEdVSUQFJGIxYWQ5ZTVkLTE3YmQtNGQxNy04ZjExLWI5NDhmZDdiOWI5Nx4FV3B0SUQoKwQHMTcxOTkzNmQWCAIBDxYCHwEFYFRyYWNraW5nIEhpc3RvcnkgKDU3NTMuOWttJm5ic3A7KSA8YSBocmVmPSJtYXBfZ20uYXNweD9JRD0xNzE5OTM2IiB0aXRsZT0nVmlldyBNYXAnPlZpZXcgTWFwPC9hPmQCAw8WAh8BBeEEPHVsIGNsYXNzPSJwYWdlciI+PGxpIGNsYXNzPSJwYWdlci1pbmZvIj4wMS0xMCBvZiAxNjcgcmVjb3JkcyAmbWlkZG90OzwvbGk+PGxpIGNsYXNzPSJwYWdlci1jdXJyZW50Ij4wMTwvbGk+PGxpPjxhIGhyZWY9Ii90cmFjay9kZXRhaWxzLmFzcHg/aWQ9MTcxOTkzNiZwYWdlPTIiPjAyPC9hPjwvbGk+PGxpPjxhIGhyZWY9Ii90cmFjay9kZXRhaWxzLmFzcHg/aWQ9MTcxOTkzNiZwYWdlPTMiPjAzPC9hPjwvbGk+PGxpPjxhIGhyZWY9Ii90cmFjay9kZXRhaWxzLmFzcHg/aWQ9MTcxOTkzNiZwYWdlPTQiPjA0PC9hPjwvbGk+PGxpPjxhIGhyZWY9Ii90cmFjay9kZXRhaWxzLmFzcHg/aWQ9MTcxOTkzNiZwYWdlPTUiPjA1PC9hPjwvbGk+PGxpPjxhIGhyZWY9Ii90cmFjay9kZXRhaWxzLmFzcHg/aWQ9MTcxOTkzNiZwYWdlPTYiPjA2PC9hPjwvbGk+PGxpIGNsYXNzPSJwYWdlci1uZXh0Ij48YSBocmVmPSIvdHJhY2svZGV0YWlscy5hc3B4P2lkPTE3MTk5MzYmcGFnZT0yIj5uZXh0IOKAujwvYT48L2xpPjxsaSBjbGFzcz0icGFnZXItbGFzdCBsYXN0Ij48YSBocmVmPSIvdHJhY2svZGV0YWlscy5hc3B4P2lkPTE3MTk5MzYmcGFnZT0xNyI+bGFzdCDCuzwvYT48L2xpPjwvdWw+ZAIHDxYCHwYCChYUAgEPZBYEZg8VCQAGMTQucG5nC0Ryb3BwZWQgT2ZmC0Ryb3BwZWQgT2ZmCjIwMTItMTItMjKLAjxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD02NWRmOTIyMi1lZWFiLTRlOTktODA2OC1iMjU2YTExOGJhZTMiPnIuYnVydG9uPC9hPiBwbGFjZWQgaXQgaW4gPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9zZWVrL2NhY2hlX2RldGFpbHMuYXNweD9ndWlkPTVmODU1Y2JjLTQzMzctNDIxOS05YmY0LTkwYzJmZmUwMzQ5NCI+SWhyIFppZWwgYmVmaW5kZXQgc2ljaCByZWNodHMgKEFpcnBvcnQgVEItSG90ZWwpPC9hPhxOb3JkcmhlaW4tV2VzdGZhbGVuLCBHZXJtYW55AFJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3RyYWNrL2xvZy5hc3B4P0xVSUQ9MzZmMWQwMWEtODczMC00OGRjLThjNmEtODY0Y2U4YzJiYjAxZAICDxUEAAAAAGQCAg9kFgRmDxUJDkFsdGVybmF0aW5nUm93BjEzLnBuZxhSZXRyaWV2ZSBJdCBmcm9tIGEgQ2FjaGUYUmV0cmlldmUgSXQgZnJvbSBhIENhY2hlCjIwMTItMTItMjKQAjxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD02NWRmOTIyMi1lZWFiLTRlOTktODA2OC1iMjU2YTExOGJhZTMiPnIuYnVydG9uPC9hPiByZXRyaWV2ZWQgaXQgZnJvbSA8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3NlZWsvY2FjaGVfZGV0YWlscy5hc3B4P2d1aWQ9NWY4NTVjYmMtNDMzNy00MjE5LTliZjQtOTBjMmZmZTAzNDk0Ij5JaHIgWmllbCBiZWZpbmRldCBzaWNoIHJlY2h0cyAoQWlycG9ydCBUQi1Ib3RlbCk8L2E+HE5vcmRyaGVpbi1XZXN0ZmFsZW4sIEdlcm1hbnkAUmh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vdHJhY2svbG9nLmFzcHg/TFVJRD00Zjk2NjI2Ny1jYWExLTRkNWUtODQ2OS02NGM1OTk5OGE3YWJkAgIPFQQOQWx0ZXJuYXRpbmdSb3czU2VlbiBhdCB0aGUgQWlycG9ydC1Ib3RlbCBpbiBEdXNzZWxkb3JmL0dlcm1hbnkuLi4hAABkAgMPZBYEZg8VCQAGMTQucG5nC0Ryb3BwZWQgT2ZmC0Ryb3BwZWQgT2ZmCjIwMTItMTItMjGNAjxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD1lNTcxYzkwNi1lNzVmLTRlMmEtOGRkNC04MzUxZTIxMjFmMDkiPnNpbGl6aXVzODM8L2E+IHBsYWNlZCBpdCBpbiA8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3NlZWsvY2FjaGVfZGV0YWlscy5hc3B4P2d1aWQ9NWY4NTVjYmMtNDMzNy00MjE5LTliZjQtOTBjMmZmZTAzNDk0Ij5JaHIgWmllbCBiZWZpbmRldCBzaWNoIHJlY2h0cyAoQWlycG9ydCBUQi1Ib3RlbCk8L2E+HE5vcmRyaGVpbi1XZXN0ZmFsZW4sIEdlcm1hbnkMIC0gNzg4LjE2IGttUmh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vdHJhY2svbG9nLmFzcHg/TFVJRD1jYzJiZGQxMi02NzQ1LTQyNzYtOTdlMy02YzdjMzAyNzIzNGZkAgIPFQQARURyb3BwZWQgaW4gSWhyIFppZWwgYmVmaW5kZXQgc2ljaCByZWNodHMgKEFpcnBvcnQgVEItSG90ZWwpIChHQzFYOUZSKQAAZAIED2QWBGYPFQkOQWx0ZXJuYXRpbmdSb3cGMTkucG5nGkdyYWIgSXQgKE5vdCBmcm9tIGEgQ2FjaGUpGkdyYWIgSXQgKE5vdCBmcm9tIGEgQ2FjaGUpCjIwMTItMTItMjBwPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9wcm9maWxlLz9ndWlkPWU1NzFjOTA2LWU3NWYtNGUyYS04ZGQ0LTgzNTFlMjEyMWYwOSI+c2lsaXppdXM4MzwvYT4gZ3JhYmJlZCBpdAAAUmh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vdHJhY2svbG9nLmFzcHg/TFVJRD0yMjcyMzBjZi04ZWUwLTQ1NGQtOTk3MC1hYjg5NWJlMTYwNjRkAgIPFQQOQWx0ZXJuYXRpbmdSb3c3SXQgdHVjIHNvbWUgdGltZSBidXQgbm93IGl0cyB0aW1lIHRvIHJlbGVhc2UgdGhpcyBvbmUsIAAAZAIFD2QWBGYPFQkABjE2LnBuZwxNYXJrIE1pc3NpbmcMTWFyayBNaXNzaW5nCjIwMTItMTEtMDR3PGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9wcm9maWxlLz9ndWlkPTk3ZGFiYmQ2LTNiZDQtNGIxOS1hNTMxLTAxZWIxZGNmOGU3NSI+aG9sbGVyMjwvYT4gbWFya2VkIGl0IGFzIG1pc3NpbmcAAFJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3RyYWNrL2xvZy5hc3B4P0xVSUQ9YzE0ZmU3ZDktOWRmNS00MmU4LTkyYTQtODIyYjRmOGM0Mzc4ZAICDxUEAPECVGhpcyBpcyBhbiBhdXRvbWF0ZWQgbWVzc2FnZS48YnIgLz5UaGlzIFRyYWNrYWJsZSBoYXMgYmVlbiBtYXJrZWQgJ21pc3NpbmcnIGJ5IGEgY2FjaGUgb3duZXIgb3Igc2l0ZSBhZG1pbmlzdHJhdG9yLiAgVHJhY2thYmxlcyBhcmUgbWFya2VkIG1pc3Npbmcgd2hlbiBpdCBpcyBkZXRlcm1pbmVkIHRoYXQgdGhleSBhcmUgbm8gbG9uZ2VyIGxvY2F0ZWQgaW4gdGhlIGNhY2hlIHRoZXkgYXJlIGxpc3RlZCBpbiBvciBpbiB0aGUgaGFuZHMgb2YgdGhlIGN1cnJlbnQgaG9sZGVyLiAgUmV2aWV3IHRoZSBtb3N0IHJlY2VudCBsb2dzIG9uIHRoaXMgVHJhY2thYmxlIHRvIGxlYXJuIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgaXRzIGN1cnJlbnQgc3RhdGUuAABkAgYPZBYEZg8VCQ5BbHRlcm5hdGluZ1JvdwU0LnBuZwpXcml0ZSBub3RlCldyaXRlIG5vdGUKMjAxMi0xMS0wNHc8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3Byb2ZpbGUvP2d1aWQ9MmJjMjY3MmEtN2E4ZC00N2Y0LTg2ZjgtMWE3ODdiZjBjYmU5Ij5jZXphbm5lPC9hPiBwb3N0ZWQgYSBub3RlIGZvciBpdAAAUmh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vdHJhY2svbG9nLmFzcHg/TFVJRD1mZmY3NmVhMS1lMzY1LTRiMWQtYTE3Zi00MDc2NzlhOTk2NWVkAgIPFQQOQWx0ZXJuYXRpbmdSb3fZAUFwcGFyZW50bHkgc29tZW9uZSB0b29rIHRo" />
+<input type="hidden" name="__VIEWSTATE2" id="__VIEWSTATE2" value="aXMgVEIgdG8gYW4gZXZlbnQgd2hpY2ggdG9vayBwbGFjZSBpbiBCdXJnZW5sYW5kIGFuZCBmb3Jnb3QgdG8gbG9nIGl0IG91dCBvZiB0aGlzIGNhY2hlLiBUaGUgVEIgd2FzIGFscmVhZHkgbWlzc2luZyBmcm9tIHRoaXMgY2FjaGUgb24gU2VwdGVtYmVyIDE2IHdoaWxlIHRoZSBldmVudCB0b29rIHBsYWNlIG9uIFNlcHRlbWJlciAyMi4AAGQCBw9kFgRmDxUJAAY0OC5wbmcNRGlzY292ZXJlZCBJdA1EaXNjb3ZlcmVkIEl0CjIwMTItMDktMjJ0PGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9wcm9maWxlLz9ndWlkPTg2MWJjNzk2LTIyMWQtNGFjNy04MmZjLWI0YTRmMDQ3MjRlNiI+Y2FjaGUtZGl2ZXI8L2E+IGRpc2NvdmVyZWQgaXQAAFJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3RyYWNrL2xvZy5hc3B4P0xVSUQ9ZTAzOWNiZDctZWYzZS00MDk1LWJmYmEtMmIzYTMyMjcyMDMwZAICDxUEADhCZWltIDguU3RhbW10aXNjaCBkZXIgUyYjeEZDO2RidXJnZW5sJiN4RTQ7bmRlciBnZXNlaGVuIQAAZAIID2QWBGYPFQkOQWx0ZXJuYXRpbmdSb3cGNDgucG5nDURpc2NvdmVyZWQgSXQNRGlzY292ZXJlZCBJdAoyMDEyLTA5LTIydTxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD0zYzYwMjg2Yi0wMWIzLTQ4YzQtYTI2Mi04ZjIzZmVhODdmMTAiPlN0ZWlyZXJwb3N0aTwvYT4gZGlzY292ZXJlZCBpdAAAUmh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vdHJhY2svbG9nLmFzcHg/TFVJRD0yMTE1Mzc3My02ODQ5LTQxMGUtYTk1OC1kYjYwODU3NGM0ZDhkAgIPFQQOQWx0ZXJuYXRpbmdSb3ctaGV1dGUgZ2VzZWhlbiBiZWltIFN0cmF1c3Nlbi1FdmVudCBkZXIgU0JMICEhAABkAgkPZBYEZg8VCQAGNDgucG5nDURpc2NvdmVyZWQgSXQNRGlzY292ZXJlZCBJdAoyMDEyLTA5LTIycjxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD04YTIwYTliMy1mOTNhLTQzYjgtYTFjOC04NTgyMjIyN2Q4NTIiPmNvc21vMTM1NTwvYT4gZGlzY292ZXJlZCBpdAAAUmh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vdHJhY2svbG9nLmFzcHg/TFVJRD1jMTIwNzk1Zi1jMTc0LTQ1OTctOWFiMy1iNWM2Mjc3NmNjOTBkAgIPFQQAG0dlc2VoZW4gYmVpbSBTdHJhdXNzZW5ldmVudAAAZAIKD2QWBGYPFQkOQWx0ZXJuYXRpbmdSb3cFNC5wbmcKV3JpdGUgbm90ZQpXcml0ZSBub3RlCjIwMTItMDktMTZ3PGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9wcm9maWxlLz9ndWlkPTVmNmFjOTg2LWQ0MzMtNDY3ZS1hNDFkLTk2OGJhOGI3N2Y2NiI+anVjaHV1dTwvYT4gcG9zdGVkIGEgbm90ZSBmb3IgaXQAAFJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3RyYWNrL2xvZy5hc3B4P0xVSUQ9MmFhYTBkNDgtM2Y1Zi00YmY3LTk1NTEtMjRjYjZhZjY5MGEwZAICDxUEDkFsdGVybmF0aW5nUm93Mk5pY2h0IG1laHIgaW0gQ2FjaGUgdm9yaGFuZGVuISEhISBOaWNodCBnZXNlaGVuISEhAABkAgsPFgIfAQXhBDx1bCBjbGFzcz0icGFnZXIiPjxsaSBjbGFzcz0icGFnZXItaW5mbyI+MDEtMTAgb2YgMTY3IHJlY29yZHMgJm1pZGRvdDs8L2xpPjxsaSBjbGFzcz0icGFnZXItY3VycmVudCI+MDE8L2xpPjxsaT48YSBocmVmPSIvdHJhY2svZGV0YWlscy5hc3B4P2lkPTE3MTk5MzYmcGFnZT0yIj4wMjwvYT48L2xpPjxsaT48YSBocmVmPSIvdHJhY2svZGV0YWlscy5hc3B4P2lkPTE3MTk5MzYmcGFnZT0zIj4wMzwvYT48L2xpPjxsaT48YSBocmVmPSIvdHJhY2svZGV0YWlscy5hc3B4P2lkPTE3MTk5MzYmcGFnZT00Ij4wNDwvYT48L2xpPjxsaT48YSBocmVmPSIvdHJhY2svZGV0YWlscy5hc3B4P2lkPTE3MTk5MzYmcGFnZT01Ij4wNTwvYT48L2xpPjxsaT48YSBocmVmPSIvdHJhY2svZGV0YWlscy5hc3B4P2lkPTE3MTk5MzYmcGFnZT02Ij4wNjwvYT48L2xpPjxsaSBjbGFzcz0icGFnZXItbmV4dCI+PGEgaHJlZj0iL3RyYWNrL2RldGFpbHMuYXNweD9pZD0xNzE5OTM2JnBhZ2U9MiI+bmV4dCDigLo8L2E+PC9saT48bGkgY2xhc3M9InBhZ2VyLWxhc3QgbGFzdCI+PGEgaHJlZj0iL3RyYWNrL2RldGFpbHMuYXNweD9pZD0xNzE5OTM2JnBhZ2U9MTciPmxhc3Qgwrs8L2E+PC9saT48L3VsPmQCMA8WAh8KBQtzcGFuLTQgbGFzdBYCAgEPZBYCAgEPDxYCHwEF/wM8aWZyYW1lIHR5cGU9ImlmcmFtZSIgc3JjPSJodHRwOi8vYWRzLmdyb3VuZHNwZWFrLmNvbS9hLmFzcHg/Wm9uZUlEPTkmVGFzaz1HZXQmU2l0ZUlEPTEmWD0nZGU1YzcyNmM1ZmU0NDU0MTk2MGY2ZmI3OGNlNzc1NGInIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjI0MCIgTWFyZ2lud2lkdGg9IjAiIE1hcmdpbmhlaWdodD0iMCIgSHNwYWNlPSIwIiBWc3BhY2U9IjAiIEZyYW1lYm9yZGVyPSIwIiBTY3JvbGxpbmc9Im5vIiBzdHlsZT0id2lkdGg6MTIwcHg7SGVpZ2h0OjI0MHB4OyI+PGEgaHJlZj0iaHR0cDovL2Fkcy5ncm91bmRzcGVhay5jb20vYS5hc3B4P1pvbmVJRD05JlRhc2s9Q2xpY2smO01vZGU9SFRNTCZTaXRlSUQ9MSIgdGFyZ2V0PSJfYmxhbmsiPjxpbWcgc3JjPSJodHRwOi8vYWRzLmdyb3VuZHNwZWFrLmNvbS9hLmFzcHg/Wm9uZUlEPTkmVGFzaz1HZXQmTW9kZT1IVE1MJlNpdGVJRD0xIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjI0MCIgYm9yZGVyPSIwIiBhbHQ9IiIgLz48L2E+PC9pZnJhbWU+ZGQCMQ9kFgQCAw8WAh8BBQdFbmdsaXNoZAIFDxYCHwYCEBYgZg9kFgICAQ8PFggfBwUFZW4tVVMfCAUNU2V0VGVtcExvY2FsZR8BBQdFbmdsaXNoHwloZGQCAQ9kFgICAQ8PFggfBwUFZGUtREUfCAUNU2V0VGVtcExvY2FsZR8BBQdEZXV0c2NoHwloZGQCAg9kFgICAQ8PFggfBwUFZnItRlIfCAUNU2V0VGVtcExvY2FsZR8BBQlGcmFuw6dhaXMfCWhkZAIDD2QWAgIBDw8WCB8HBQVwdC1QVB8IBQ1TZXRUZW1wTG9jYWxlHwEFClBvcnR1Z3XDqnMfCWhkZAIED2QWAgIBDw8WCB8HBQVjcy1DWh8IBQ1TZXRUZW1wTG9jYWxlHwEFCcSMZcWhdGluYR8JaGRkAgUPZBYCAgEPDxYIHwcFBXN2LVNFHwgFDVNldFRlbXBMb2NhbGUfAQUHU3ZlbnNrYR8JaGRkAgYPZBYCAgEPDxYIHwcFBWVzLUVTHwgFDVNldFRlbXBMb2NhbGUfAQUIRXNwYcOxb2wfCWhkZAIHD2QWAgIBDw8WCB8HBQVpdC1JVB8IBQ1TZXRUZW1wTG9jYWxlHwEFCEl0YWxpYW5vHwloZGQCCA9kFgICAQ8PFggfBwUFbmwtTkwfCAUNU2V0VGVtcExvY2FsZR8BBQpOZWRlcmxhbmRzHwloZGQCCQ9kFgICAQ8PFggfBwUFY2EtRVMfCAUNU2V0VGVtcExvY2FsZR8BBQdDYXRhbMOgHwloZGQCCg9kFgICAQ8PFggfBwUFcGwtUEwfCAUNU2V0VGVtcExvY2FsZR8BBQZQb2xza2kfCWhkZAILD2QWAgIBDw8WCB8HBQVldC1FRR8IBQ1TZXRUZW1wTG9jYWxlHwEFBUVlc3RpHwloZGQCDA9kFgICAQ8PFggfBwUFbmItTk8fCAUNU2V0VGVtcExvY2FsZR8BBQ5Ob3JzaywgQm9rbcOlbB8JaGRkAg0PZBYCAgEPDxYIHwcFBWtvLUtSHwgFDVNldFRlbXBMb2NhbGUfAQUJ7ZWc6rWt7Ja0HwloZGQCDg9kFgICAQ8PFggfBwUFaHUtSFUfCAUNU2V0VGVtcExvY2FsZR8BBQZNYWd5YXIfCWhkZAIPD2QWAgIBDw8WCB8HBQVyby1STx8IBQ1TZXRUZW1wTG9jYWxlHwEFCFJvbcOibsSDHwloZGQCAw8WAh8BBStTZXJ2ZXI6IFdFQjAxOyBCdWlsZDogV2ViLkhvdEZpeF8yMDEyMTIxMS4xZGT8K6IlAWC8dkt7tG/Bikvy2o0veQ==" />
+</div>
+
+<script type="text/javascript">
+//<![CDATA[
+var theForm = document.forms['aspnetForm'];
+if (!theForm) {
+ theForm = document.aspnetForm;
+}
+function __doPostBack(eventTarget, eventArgument) {
+ if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
+ theForm.__EVENTTARGET.value = eventTarget;
+ theForm.__EVENTARGUMENT.value = eventArgument;
+ theForm.submit();
+ }
+}
+//]]>
+</script>
+
+
+<script src="/WebResource.axd?d=Dh2VENdI9XyWNN0f7DnYfR8WWRCRIzdVqal2y0yjiQ5nC_eHhLchYgnQDHIk0d3RCcSUMVZ36ciRD0qmhXKmeu3S_RE1&t=634494454566271406" type="text/javascript"></script>
+
+
+<script src="/ScriptResource.axd?d=I9_m2Hb1Tv_B0qTMDG8bMbnkNSHUkv5oUaG9-V5NZ8qQ2VFlu60I8y8gfr3vPmZjbiPnu43MOQdFVDeYF-nDAEKBLmyxD3DCTGmes9NNbbvaDEHyEuuRWgccIkK3ik5TI48YGDxjHjqdn-gTK4Fkgd17LGw1&t=4edbeeee" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=8vNbe34dAujgZMPnfnacfjeoweX1vHgyns8KlAV4vpGpsZC9Cf3pro__lv8ekBa0NiCgXGMMolzOUNH__lrnEI_qjlNBIAuuLeemtAXV_i6E0QIMZa8nGSYmWGF5nQOJK3rmZzvTxsr2Mh4Ebdba_1ywGLUSH_U_XIe-jzecfRQwwvjZ0&t=4edbeeee" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=5MtKNiX-AvTiJAmD-CuAbj2i1O1w1_sqCit4yp-ml_oeLlcBDoI34c7xF66GuJL-Fr4hkU72euEoaMI_-eplvmaZxdGIWIsjLkQ5n7ejd9FRAjKQhEz6SgN4YSU_UT5tzAicclG3I_-1tdJN2lyb0uaG4hoFrGKe6sW49Qb-folwHAUC0Oym6UmLHCk48nZjPiZi8lnfQOJH3ew-CNb6UMEqX541" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=C5mECf6JWQUTGOEvqWYgiTd7aYAVrqQJZGCHcxc-cHLemvCwBGRB9iWo1t5hONDlOQ-QIl5aRWJNXbZpFfybfWd9YeQi9lUG0eecrYxZH-GH26aMEiCJLSkwvHh6BuhJ_fVd4g2" type="text/javascript"></script>
+ <script type="text/javascript">
+//<![CDATA[
+Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00');
+//]]>
+</script>
+
+ <div id="Top" class="SkipLinks">
+
+ <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
+ <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
+
+ </div>
+
+ <!--[if lte IE 6]>
+ <div class="WarningMessage PhaseOut">
+
+ <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
+
+ </div>
+ <![endif]-->
+
+
+
+ <div class="PrintOnly">
+
+ <p>
+ <img src="/images/logo_print_bw.png" alt="Geocaching.com" /></p>
+ <hr />
+
+ </div>
+
+ <header>
+
+ <div class="container">
+
+ <h1 class="Logo span-16">
+ <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">Geocaching</a></h1>
+ <div class="ProfileWidget span-8 last">
+
+
+
+ <div id="ctl00_divSignedIn">
+
+ <p class="Avatar NoBottomSpacing">
+ <a id="ctl00_hlHeaderAvatar" accesskey="p" title="Your Profile" href="../my/"><img title="Your Profile" src="http://img.geocaching.com/user/avatar/642d2771-424e-4ee6-beb6-efecde3406fc.jpg" alt="" style="border-width:0px;" /></a></p>
+ <p class="SignedInText">
+ <strong>
+ Hello, <a href="/my/default.aspx" title="View Profile for Bananeweizen" class="SignedInProfileLink">Bananeweizen</a></strong> (<a id="ctl00_hlSignOut" accesskey="s" title="Sign Out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2ftrack%2fdetails.aspx%3ftracker%3dtb29ggq">Sign Out</a>)<br />
+ <span id="ctl00_litPMLevel">Premium Member</span>
+
+ <strong style="display:block">
+ 328 Caches Found</strong>
+
+ </p>
+
+ </div>
+
+
+ </div>
+
+ <div class="NavContainer span-24 last">
+ <nav id="Navigation">
+
+ <ul class="Menu">
+ <li>
+ <a id="ctl00_hlNavLearn" accesskey="1" title="Learn" href="../guide/">Learn ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavGeocaching101" accesskey="i" title="Geocaching 101" href="../guide/">Geocaching 101</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeocaching2Minutes" title="Geocaching in 2 Minutes" href="../videos/#cat=cat:newbies&vid=-4VFeYZTTYs">Geocaching in 2 Minutes</a></li>
+ </ul>
+ </li>
+
+ <li id="ctl00_liNavProfile">
+ <a id="ctl00_hlNavProfile" accesskey="2" title="Your Profile" href="../my/">Your Profile ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavQuickView" accesskey="p" title="Quick View" href="../my/">Quick View</a></li>
+ <li>
+ <a id="ctl00_hlSubNavLists" accesskey="q" title="Lists" href="../my/lists.aspx">Lists</a></li>
+ <li class="ExtraText">
+ <a id="ctl00_hlSubNavGeocaches" accesskey="m" title="Geocaches" class="NoRightPadding" href="../my/geocaches.aspx">Geocaches</a>
+ (<a id="ctl00_hlSubNavGeocachesYours" accesskey="y" title="Yours" class="NoSidePadding" href="../my/owned.aspx">Yours</a>)</li>
+ <li class="ExtraText">
+ <a id="ctl00_hlSubNavProfileTrackables" title="Trackables" class="NoRightPadding" href="../my/travelbugs.aspx">Trackables</a>
+ (<a id="ctl00_hlSubNavTrackablesYours" accesskey="8" title="Yours" class="NoSidePadding" href="search.aspx?o=1&uid=31892678-1117-46eb-aa3b-191c20bd6607">Yours</a>)</li>
+ <li>
+ <a id="ctl00_hlSubNavPocketQueries" accesskey="9" title="Pocket Queries" href="../pocket/">Pocket Queries</a></li>
+ <li>
+ <a id="ctl00_hlSubNavFieldNotes" accesskey="0" title="Field Notes" href="../my/fieldnotes.aspx">Field Notes</a></li>
+ <li>
+ <a id="ctl00_hlSubNavAccount" accesskey="a" title="Account Details" href="../account/">Account Details</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavPlay" accesskey="3" title="Play" href="../seek/">Play ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavHide" accesskey="d" title="Hide & Seek a Cache" href="../seek/">Hide & Seek a Cache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavLogCache" title="Log a Cache" href="../my/recentlyviewedcaches.aspx">Log a Cache</a></li>
+ <li><a id="ctl00_hlSubNavMap" accesskey="/" title="View Geocache Map" href="../map/">View Geocache Map</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTrackables" accesskey="e" title="Find Trackables" href="./">Find Trackables</a></li>
+ <li>
+ <a id="ctl00_hlSubNavHelpCenter" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavCommunity" accesskey="6" title="Community" href="../forums/">Community ▼</a>
+ <ul class="SubMenu">
+
+ <li>
+ <a id="ctl00_hlSubNavTellaFriend" accesskey="-" title="Tell a Friend" href="../account/SendReferral.aspx">Tell a Friend</a></li>
+
+ <li><a id="ctl00_hlSubNavVolunteers" accesskey="+" title="Volunteers" href="../volunteers/">Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavLocal" accesskey="z" title="Local Organizations" href="../organizations/">Local Organizations</a></li>
+ <li>
+ <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBlog" accesskey="b" title="Blog" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEvents" accesskey="v" title="Events" href="../calendar/">Events</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavShop" accesskey="4" title="Shop" href="http://shop.geocaching.com/">Shop ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavShop" accesskey="j" title="Shop Geocaching" rel="external" href="http://shop.geocaching.com/">Shop Geocaching</a></li>
+ <li>
+ <a id="ctl00_hlSubNavIntlRetailers" title="International Retailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGPSReviews" accesskey="w" title="GPS Reviews" href="/reviews/gps">GPS Reviews</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGPSGuide" accesskey="k" title="Guide to Buying a GPS Device" href="../about/buying.aspx">Guide to Buying a GPS Device</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavPartnering" accesskey="5" title="Partnering" href="../travel/">Partnering ▼</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavTravel" title="Travel and GeoTourism" href="../travel/">Travel and GeoTourism</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBrandedPromotions" title="Branded Promotions" href="../brandedpromotions/">Branded Promotions</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEducation" title="Geocaching and Education" href="../education/">Geocaching and Education</a></li>
+ <li>
+ <a id="ctl00_hlSubNavAdvertisingWithUs" title="Advertising with Us" href="../about/advertising.aspx">Advertising with Us</a></li>
+ <li>
+ <a id="ctl00_hlSubNavAPIProgram" title="API Program" href="../live/apidevelopers/">API Program</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavVideos" accesskey="7" title="Videos" href="../videos/">Videos</a></li>
+ <li>
+ <a id="ctl00_hlNavFollowUs" title="Follow Us" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts">Follow Us ▼</a>
+ <ul class="SubMenu NavSocialMedia">
+ <li>
+ <a id="ctl00_hlSubNavFacebook" title="Facebook" class="SubNavFacebook" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts">Facebook</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTwitter" title="Twitter" class="SubNavTwitter" href="http://twitter.com/GoGeocaching">Twitter</a></li>
+ <li>
+ <a id="ctl00_hlSubNavFlickr" title="Flickr" class="SubNavFlickr" href="http://www.flickr.com/photos/geocaching_com/">Flickr</a></li>
+ <li>
+ <a id="ctl00_hlSubNavYouTube" title="YouTube" class="SubNavYouTube" href="http://www.youtube.com/user/GoGeocaching">YouTube</a></li>
+ </ul>
+ </li>
+ </ul>
+
+ </nav>
+ <div class="LanguageSelector">
+
+
+<div class="LocaleText">
+
+ <strong>Choose Your Language:</strong>
+
+</div>
+<div class="LocaleList">
+
+ <div class="selected-language">
+
+ <a href="#">English▼</a>
+
+ </div>
+ <ul class="language-list">
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl05$uxLocaleItem','')">Svenska</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl06$uxLocaleItem','')">Español</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl07$uxLocaleItem','')">Italiano</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl08$uxLocaleItem','')">Nederlands</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl09$uxLocaleItem','')">Català</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl10$uxLocaleItem','')">Polski</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl11$uxLocaleItem','')">Eesti</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl12$uxLocaleItem','')">Norsk, Bokmål</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl13$uxLocaleItem','')">한국어</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl14$uxLocaleItem','')">Magyar</a></li>
+
+ <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl15$uxLocaleItem','')">Română</a></li>
+
+ </ul>
+
+</div>
+<script type="text/javascript">
+
+ jQuery(document).ready(function () {
+ jQuery(".selected-language a").click(function (e) {
+ e.preventDefault();
+ var $loc = jQuery(this).parent().next();
+ jQuery($loc).show().position({
+ of: $loc.parent(),
+ my: "left top",
+ at: "left bottom",
+ offset: "0 0",
+ collision: "fit fit"
+ });
+ jQuery(this).addClass("Expanded");
+ jQuery(document).click(function () {
+ jQuery(".language-list").fadeOut("fast");
+ jQuery(".selected-language a").removeClass("Expanded");
+ });
+ return false;
+ });
+ });
+</script>
+ </div>
+ </div>
+
+
+ </div>
+
+
+ </header>
+ <section id="Content">
+
+
+ <div class="container">
+
+ <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
+
+ <p>
+ <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Trackables" href="/track/default.aspx">Trackables</a></span><span> > </span><span>Trackable Item Details</span></span>
+ </p>
+
+
+ </div>
+
+ <div id="ctl00_divContentMain" class="span-20">
+
+
+
+ <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
+
+ <p>
+ <a href="#" class="CoordInfoLink">
+ <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">TB29GGQ</span>
+ <span class="arrow">▼</span> </a>
+ </p>
+
+</div>
+<div id="dlgClipboard">
+ <input type="text" class="TextFormat" />
+ <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close">
+ x</a>
+</div>
+<script type="text/javascript">
+ $("a.CoordInfoLink").click(function (e) {
+ e.preventDefault();
+
+ $("#dlgClipboard")
+ .show()
+ .position({
+ of: $("a.CoordInfoLink"),
+ my: "right top",
+ at: "right bottom",
+ offset: "0 5"
+ })
+ .find("input")
+ .val('http://coord.info/' + $('.CoordInfoCode').text())
+ .focus()
+ .select();
+
+ $(document).mouseup(function (e) {
+ if ($(e.target).parent("div#dlgClipboard").length == 0) {
+ $(this).unbind(e);
+ $("div#dlgClipboard").hide();
+ }
+ });
+
+ return false;
+ });
+
+
+</script>
+
+ <h2 class="WrapFix">
+ <img id="ctl00_ContentBody_BugTypeImage" class="TravelBugHeaderIcon" src="http://www.geocaching.com/images/wpttypes/21.gif" alt="Travel Bug Dog Tag" style="border-width:0px;" />
+ <span id="ctl00_ContentBody_lbHeading">Courageous Carrot</span>
+ </h2>
+
+
+
+ <table id="ctl00_ContentBody_OptionTable" class="TrackableItemOptionsTable right" align="Right" border="0" style="width:240px;">
+ <tr id="ctl00_ContentBody_trHeader">
+ <td id="ctl00_ContentBody_tcTypeName" class="TableHeader"><strong>Trackable Options</strong></td>
+ </tr><tr id="ctl00_ContentBody_trLogIt">
+ <td>
+ <img src="/images/icons/16/write_log.png" width="16" height="16" alt="notebook"
+ title="Found it? Log it!" /> <a id="ctl00_ContentBody_LogLink" title="Found it? Log it!" href="log.aspx?wid=b1ad9e5d-17bd-4d17-8f11-b948fd7b9b97">Found it? Log it!</a></td>
+ </tr><tr id="ctl00_ContentBody_trWatchIt">
+ <td>
+ <img src="/images/icons/16/watch.png" width="16" height="16" alt="alert"
+ title="Watch This Trackable Item" /> <a id="ctl00_ContentBody_WatchLink" title="Watch This Trackable Item" href="/my/watchlist.aspx?b=1719936">Watch This Trackable Item</a></td>
+ </tr><tr id="ctl00_ContentBody_trPrintIt">
+ <td>
+ <img src="/images/icons/16/print.png" width="16" height="16" alt="printer"
+ title="Print Bug Sheet" /> <a id="ctl00_ContentBody_lnkPrint" title="Print Info Sheet" href="sheet.aspx?guid=b1ad9e5d-17bd-4d17-8f11-b948fd7b9b97">Print Info Sheet</a></td>
+ </tr><tr id="ctl00_ContentBody_trGoogleKML">
+ <td>
+ <img src="/images/icons/16/view_map.png" width="16" height="16" alt="map"
+ title="View in Google Earth"
+ class="lnk" /> <a id="ctl00_ContentBody_lnkGoogleKML" title="View in Google Earth" href="/kml/tbkml.aspx?tbguid=b1ad9e5d-17bd-4d17-8f11-b948fd7b9b97">View in Google Earth</a></td>
+ </tr><tr id="ctl00_ContentBody_trWatchList">
+ <td><span id="ctl00_ContentBody_WatchList">There are <strong>5</strong> users watching this listing.</span></td>
+ </tr>
+</table>
+
+<dl class="BugDetailsList">
+
+ <dt>
+ Owner:
+ </dt>
+
+ <dd>
+ <a id="ctl00_ContentBody_BugDetails_BugOwner" title="Visit This User's Profile" href="http://www.geocaching.com/profile/?guid=8c710cec-6cb4-4460-8274-5e5d022f5c67">Team RoKeT</a>
+ </dd>
+
+
+
+ <dt>
+ Released:
+ </dt>
+
+ <dd>
+ <span id="ctl00_ContentBody_BugDetails_BugReleaseDate">Wednesday, 01 October 2008</span>
+ </dd>
+
+
+
+
+ <dt>
+ Origin:
+ </dt>
+
+ <dd>
+ <span id="ctl00_ContentBody_BugDetails_BugOrigin">Northwest England, United Kingdom</span>
+ </dd>
+
+
+
+ <dt>
+ Recently Spotted:</dt>
+
+ <dd>
+ <a id="ctl00_ContentBody_BugDetails_BugLocation" title="Visit Listing" href="http://www.geocaching.com/seek/cache_details.aspx?guid=5f855cbc-4337-4219-9bf4-90c2ffe03494">In Ihr Ziel befindet sich rechts (Airport TB-Hotel)</a></dd>
+
+</dl>
+<p>
+
+</p>
+<p>
+ The owner hasn't set their collectible preference.
+</p>
+<p>
+ <span id="ctl00_ContentBody_BugDetails_BugTBNum" String="Use <strong>{0}</strong> to reference this item.">Use <strong>TB29GGQ</strong> to reference this item.</span>
+</p>
+<p>
+ <strong>
+ <a id="ctl00_ContentBody_BugDetails_uxFirstTime" title="First time logging a Trackable?" href="/track/default.aspx">First time logging a Trackable? Click here.</a>
+ </strong>
+</p>
+<h3>
+ Current GOAL
+</h3>
+<div id="TrackableGoal">
+<p>
+ I am part of a gang of vegetables (see pic)<br />I want to travel and have adventures. Please help me! I love pics of my exploits too!<br />Move me on far and fast and help me have FUN!
+</p>
+</div>
+<h3>
+ About This Item
+</h3>
+<div id="TrackableDetails">
+<p>
+ <img id="ctl00_ContentBody_BugDetails_BugImage" class="TrackableItemDetailsImage" src="http://img.geocaching.com/track/display/aaa17d73-c3c8-4940-81a3-107b64aa86c0.jpg" alt="The gang!" style="border-width:0px;" />
+</p>
+<p>
+ Mad looking carrot
+</p>
+</div>
+<div id="ctl00_ContentBody_BugDetails_uxAbuseReport">
+
+ <p>
+
+
+ </p>
+
+</div>
+
+ <div class="Clear">
+ </div>
+ <p>
+ <span id="ctl00_ContentBody_Images"><h3>Gallery Images related to Courageous Carrot</h3><ul class="imagelist"><li><a href="http://img.geocaching.com/track/large/aaa17d73-c3c8-4940-81a3-107b64aa86c0.jpg" class="tb_images lnk" rel="tb_images"><img src="/images/icons/16/photo.png" alt="The gang!" /> <span>The gang!</span></a></ul><a href="gallery.aspx?ID=1719936" title='View Gallery Images'>View All 5 Gallery Images</a></span></p>
+
+<h4 class="BottomSpacing">
+ Tracking History (5753.9km ) <a href="map_gm.aspx?ID=1719936" title='View Map'>View Map</a>
+</h4>
+<ul class="pager"><li class="pager-info">01-10 of 167 records ·</li><li class="pager-current">01</li><li><a href="/track/details.aspx?id=1719936&page=2">02</a></li><li><a href="/track/details.aspx?id=1719936&page=3">03</a></li><li><a href="/track/details.aspx?id=1719936&page=4">04</a></li><li><a href="/track/details.aspx?id=1719936&page=5">05</a></li><li><a href="/track/details.aspx?id=1719936&page=6">06</a></li><li class="pager-next"><a href="/track/details.aspx?id=1719936&page=2">next ›</a></li><li class="pager-last last"><a href="/track/details.aspx?id=1719936&page=17">last »</a></li></ul>
+
+
+ <table class="TrackableItemLogTable Table">
+
+ <tr class="Data BorderTop ">
+ <td width="105">
+ <img src="/images/logtypes/14.png" width="16" height="16" alt="Dropped Off" title="Dropped Off" /> 2012-12-22
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=65df9222-eeab-4e99-8068-b256a118bae3">r.burton</a> placed it in <a href="http://www.geocaching.com/seek/cache_details.aspx?guid=5f855cbc-4337-4219-9bf4-90c2ffe03494">Ihr Ziel befindet sich rechts (Airport TB-Hotel)</a>
+ </td>
+ <td>
+ Nordrhein-Westfalen, Germany
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=36f1d01a-8730-48dc-8c6a-864ce8c2bb01" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom ">
+ <td colspan="4">
+ <div></div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop AlternatingRow">
+ <td width="105">
+ <img src="/images/logtypes/13.png" width="16" height="16" alt="Retrieve It from a Cache" title="Retrieve It from a Cache" /> 2012-12-22
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=65df9222-eeab-4e99-8068-b256a118bae3">r.burton</a> retrieved it from <a href="http://www.geocaching.com/seek/cache_details.aspx?guid=5f855cbc-4337-4219-9bf4-90c2ffe03494">Ihr Ziel befindet sich rechts (Airport TB-Hotel)</a>
+ </td>
+ <td>
+ Nordrhein-Westfalen, Germany
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=4f966267-caa1-4d5e-8469-64c59998a7ab" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom AlternatingRow">
+ <td colspan="4">
+ <div>Seen at the Airport-Hotel in Dusseldorf/Germany...!</div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop ">
+ <td width="105">
+ <img src="/images/logtypes/14.png" width="16" height="16" alt="Dropped Off" title="Dropped Off" /> 2012-12-21
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=e571c906-e75f-4e2a-8dd4-8351e2121f09">silizius83</a> placed it in <a href="http://www.geocaching.com/seek/cache_details.aspx?guid=5f855cbc-4337-4219-9bf4-90c2ffe03494">Ihr Ziel befindet sich rechts (Airport TB-Hotel)</a>
+ </td>
+ <td>
+ Nordrhein-Westfalen, Germany
+ - 788.16 km
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=cc2bdd12-6745-4276-97e3-6c7c3027234f" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom ">
+ <td colspan="4">
+ <div>Dropped in Ihr Ziel befindet sich rechts (Airport TB-Hotel) (GC1X9FR)</div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop AlternatingRow">
+ <td width="105">
+ <img src="/images/logtypes/19.png" width="16" height="16" alt="Grab It (Not from a Cache)" title="Grab It (Not from a Cache)" /> 2012-12-20
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=e571c906-e75f-4e2a-8dd4-8351e2121f09">silizius83</a> grabbed it
+ </td>
+ <td>
+
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=227230cf-8ee0-454d-9970-ab895be16064" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom AlternatingRow">
+ <td colspan="4">
+ <div>It tuc some time but now its time to release this one, </div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop ">
+ <td width="105">
+ <img src="/images/logtypes/16.png" width="16" height="16" alt="Mark Missing" title="Mark Missing" /> 2012-11-04
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=97dabbd6-3bd4-4b19-a531-01eb1dcf8e75">holler2</a> marked it as missing
+ </td>
+ <td>
+
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=c14fe7d9-9df5-42e8-92a4-822b4f8c4378" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom ">
+ <td colspan="4">
+ <div>This is an automated message.<br />This Trackable has been marked 'missing' by a cache owner or site administrator. Trackables are marked missing when it is determined that they are no longer located in the cache they are listed in or in the hands of the current holder. Review the most recent logs on this Trackable to learn more information about its current state.</div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop AlternatingRow">
+ <td width="105">
+ <img src="/images/logtypes/4.png" width="16" height="16" alt="Write note" title="Write note" /> 2012-11-04
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=2bc2672a-7a8d-47f4-86f8-1a787bf0cbe9">cezanne</a> posted a note for it
+ </td>
+ <td>
+
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=fff76ea1-e365-4b1d-a17f-407679a9965e" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom AlternatingRow">
+ <td colspan="4">
+ <div>Apparently someone took this TB to an event which took place in Burgenland and forgot to log it out of this cache. The TB was already missing from this cache on September 16 while the event took place on September 22.</div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop ">
+ <td width="105">
+ <img src="/images/logtypes/48.png" width="16" height="16" alt="Discovered It" title="Discovered It" /> 2012-09-22
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=861bc796-221d-4ac7-82fc-b4a4f04724e6">cache-diver</a> discovered it
+ </td>
+ <td>
+
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=e039cbd7-ef3e-4095-bfba-2b3a32272030" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom ">
+ <td colspan="4">
+ <div>Beim 8.Stammtisch der Südburgenländer gesehen!</div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop AlternatingRow">
+ <td width="105">
+ <img src="/images/logtypes/48.png" width="16" height="16" alt="Discovered It" title="Discovered It" /> 2012-09-22
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=3c60286b-01b3-48c4-a262-8f23fea87f10">Steirerposti</a> discovered it
+ </td>
+ <td>
+
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=21153773-6849-410e-a958-db608574c4d8" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom AlternatingRow">
+ <td colspan="4">
+ <div>heute gesehen beim Straussen-Event der SBL !!</div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop ">
+ <td width="105">
+ <img src="/images/logtypes/48.png" width="16" height="16" alt="Discovered It" title="Discovered It" /> 2012-09-22
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=8a20a9b3-f93a-43b8-a1c8-85822227d852">cosmo1355</a> discovered it
+ </td>
+ <td>
+
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=c120795f-c174-4597-9ab3-b5c62776cc90" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom ">
+ <td colspan="4">
+ <div>Gesehen beim Straussenevent</div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data BorderTop AlternatingRow">
+ <td width="105">
+ <img src="/images/logtypes/4.png" width="16" height="16" alt="Write note" title="Write note" /> 2012-09-16
+ </td>
+ <td>
+ <a href="http://www.geocaching.com/profile/?guid=5f6ac986-d433-467e-a41d-968ba8b77f66">juchuuu</a> posted a note for it
+ </td>
+ <td>
+
+
+ </td>
+ <td width="70">
+ <a href="http://www.geocaching.com/track/log.aspx?LUID=2aaa0d48-3f5f-4bf7-9551-24cb6af690a0" title="Visit Log">Visit Log</a>
+ </td>
+ </tr>
+ <tr class="Data BorderBottom AlternatingRow">
+ <td colspan="4">
+ <div>Nicht mehr im Cache vorhanden!!!! Nicht gesehen!!!</div>
+
+
+ </td>
+ </tr>
+
+ <tr class="Data">
+ <td colspan="4" align="right">
+ <small>data on this page is cached for 3 mins</small>
+ </td>
+ </tr>
+ </table>
+
+
+<ul class="pager"><li class="pager-info">01-10 of 167 records ·</li><li class="pager-current">01</li><li><a href="/track/details.aspx?id=1719936&page=2">02</a></li><li><a href="/track/details.aspx?id=1719936&page=3">03</a></li><li><a href="/track/details.aspx?id=1719936&page=4">04</a></li><li><a href="/track/details.aspx?id=1719936&page=5">05</a></li><li><a href="/track/details.aspx?id=1719936&page=6">06</a></li><li class="pager-next"><a href="/track/details.aspx?id=1719936&page=2">next ›</a></li><li class="pager-last last"><a href="/track/details.aspx?id=1719936&page=17">last »</a></li></ul>
+<p>
+
+</p>
+
+
+
+
+
+ </div>
+
+ <div id="ctl00_divContentSide" class="span-4 last">
+
+ <div id="ctl00_uxBanManWidget" class="MasterPageAds">
+
+
+ <p class="NoBottomSpacing">
+ <span id="ctl00_ADModules_09"><iframe type="iframe" src="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Get&SiteID=1&X='de5c726c5fe44541960f6fb78ce7754b'" width="120" height="240" Marginwidth="0" Marginheight="0" Hspace="0" Vspace="0" Frameborder="0" Scrolling="no" style="width:120px;Height:240px;"><a href="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Click&;Mode=HTML&SiteID=1" target="_blank"><img src="http://ads.groundspeak.com/a.aspx?ZoneID=9&Task=Get&Mode=HTML&SiteID=1" width="120" height="240" border="0" alt="" /></a></iframe></span></p>
+ <p class="AlignCenter">
+ <small>
+ <a id="ctl00_hlAdvertiseWithUs" title="Advertising with Us" href="../about/advertising.aspx">Advertising with Us</a></small></p>
+
+
+</div>
+
+
+ </div>
+
+
+ </div>
+
+
+ </section>
+
+ <footer>
+
+ <div class="container">
+
+ <div class="span-24 last FooterTop">
+
+
+
+<div class="LocaleText">
+
+ <strong>Choose Your Language:</strong>
+
+</div>
+<div class="LocaleList">
+
+ <div class="selected-language">
+
+ <a href="#">English▼</a>
+
+ </div>
+ <ul class="language-list">
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Svenska</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Español</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Italiano</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Nederlands</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Català</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">Polski</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">Eesti</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">Norsk, Bokmål</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">한국어</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Magyar</a></li>
+
+ <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Română</a></li>
+
+ </ul>
+
+</div>
+<script type="text/javascript">
+
+ jQuery(document).ready(function () {
+ jQuery(".selected-language a").click(function (e) {
+ e.preventDefault();
+ var $loc = jQuery(this).parent().next();
+ jQuery($loc).show().position({
+ of: $loc.parent(),
+ my: "left top",
+ at: "left bottom",
+ offset: "0 0",
+ collision: "fit fit"
+ });
+ jQuery(this).addClass("Expanded");
+ jQuery(document).click(function () {
+ jQuery(".language-list").fadeOut("fast");
+ jQuery(".selected-language a").removeClass("Expanded");
+ });
+ return false;
+ });
+ });
+</script>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ About</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterGlossary" title="Glossary of Terms" href="../about/glossary.aspx">Glossary of Terms</a></li>
+ <li>
+ <a id="ctl00_hlFooterBrochures" title="Brochures" href="../tools/#Guide">Brochures</a></li>
+ <li>
+ <a id="ctl00_hlFooterAbout" title="About Groundspeak" href="../about/groundspeak.aspx">About Groundspeak</a></li>
+ <li>
+ <a id="ctl00_hlFooterVolunteers" title="About Our Volunteers" href="../volunteers/">About Our Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlFooterHistory" title="History" href="../about/history.aspx">History</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ Press</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterNews" title="News Articles" href="../press/">News Articles</a></li>
+ <li>
+ <a id="ctl00_hlFooterMediaFAQs" title="Media FAQs" rel="document" href="../articles/Brochures/footer/FAQ_Media.pdf">Media FAQs</a></li>
+ <li>
+ <a id="ctl00_hlFooterMediaInquiries" title="Media Inquiries" rel="external" href="http://support.groundspeak.com/index.php?pg=request&xCategory=11">Media Inquiries</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-5">
+
+ <p class="FooterHeader">
+ <strong>
+ Questions & Suggestions</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterHelpCenterLink" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
+ <li>
+ <a id="ctl00_hlFooterDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlFooterParksPoliceLink" title="Land Management and Law Enforcement" href="../parksandpolice/">Land Management and Law Enforcement</a></li>
+ <li>
+ <a id="ctl00_hlFooterContactUs" title="Contact Us" href="../contact/">Contact Us</a></li>
+ </ul>
+
+ </div>
+
+ <div class="span-4">
+
+ <p class="FooterHeader">
+ <strong>
+ Resources</strong></p>
+ <ul class="FooterLinks">
+ <li>
+ <a id="ctl00_hlFooterTools" accesskey="o" title="Tools and Downloads" href="../tools/">Tools and Downloads</a></li>
+ <li>
+ <a id="ctl00_hlFooterAPIProgram" title="API Program" href="../live/">API Program</a></li>
+ <li>
+ <a id="ctl00_hlFooterBenchmarks" title="Find a Benchmark" href="../mark/">Find a Benchmark</a></li>
+ </ul>
+
+ </div>
+ <div class="span-4 append-3 last">
+
+ <p class="FooterHeader">
+ <strong>
+ Follow Us</strong></p>
+ <ul class="FooterLinks FollowUsLinks">
+ <li><a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/pages/Geocachingcom/45625464679?ref=ts"><img id="ctl00_imgFacebook" title="Facebook" src="../images/home/icon_facebook.png" alt="Facebook" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"><img id="ctl00_imgTwitter" title="Twitter" src="../images/twitter/twitter_icon_white_22.png" alt="Twitter" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlFlickr" title=" Flickr" href="http://www.flickr.com/photos/geocaching_com/"><img id="ctl00_imgFlickr" title="Flickr" src="../images/home/icon_flickr.png" alt="Flickr" style="border-width:0px;" /></a></li>
+ <li><a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"><img id="ctl00_imgYouTube" title="YouTube" src="../images/home/icon_youtube.png" alt="YouTube" style="border-width:0px;" /></a></li>
+ </ul>
+
+ </div>
+
+ <p class="span-24 last FooterBottom">
+ Copyright
+ © 2000-2012
+ <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
+ All Rights Reserved.<br />
+ <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
+ |
+ <a id="ctl00_hlFooterPrivacy" accesskey="x" title="Privacy Policy" href="../about/privacypolicy.aspx">Privacy Policy</a>
+ |
+ <a id="ctl00_hlFooterLogo" accesskey="l" title="Geocaching Logo Usage Guidelines" href="../about/logousage.aspx">Geocaching Logo Usage Guidelines</a>
+ |
+ <a id="ctl00_hlFooterAPI" accesskey="`" title="API License Agreement" href="../live/api_license_agreement.aspx">API License Agreement</a>
+ |
+ <a id="ctl00_HlFooterStatus" accesskey="`" title="Current Service Status" href="http://status.geocaching.com">Service Status</a></p>
+
+ </div>
+
+
+ </footer>
+ <div class="SkipLinks">
+
+ <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
+
+ </div>
+
+
+
+
+<script type="text/javascript">
+//<![CDATA[
+var uvtoken = 'PsDnbhUAfZpYJ%2fVuS%2fA9U54ejcA9wXNPAxTP1Ko197xlyETGZCA7gbO9VXK21qNg7lQ3ibk684aNVDy6A1BKO84P1Va3E5xbf%2b7DRtbbX1yOzF%2fNsOv37varJ6Nrw%2fcdK8biwChd4qunTzxrggjFYLhlIgrQ3psgM0Ci3JA7GVX7OR5%2fQX2Cb%2b2pzF7hLYSxKlVJBkirhFswq4yxlji7chiCUy0J0DIk6rGk6uRulo2mu6MClssPsLn9bk4UD%2bNPUm3ml4HjoE64jm5vnvZKffpmPbgMjmGQs1Vbg8ih4BxAwhPGzD8Sh16hVS1tpWETN2CD6H5qHSAxn3Xdxw5cNJsxQ6YoTsPRR6zdDl7IkoWUoREMJ9mJj%2fjxRooGdh0XWQPJt7QGWh3e5V9HwhXQw%2bB6230Dn1CXPG282Rs81UGZMv0KPSrXJukMUmrqhNVl';//]]>
+</script>
+</form>
+ <script type="text/javascript">
+ var browserType = {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ };
+
+ $(function () {
+ // Make the menu system play nice with all browsers:
+ $('ul.Menu li').hover(function () {
+ $(this).addClass('hover');
+ $('ul:first', this).css('visibility', 'visible');
+ }, function () {
+ $(this).removeClass('hover');
+ $('ul:first', this).css('visibility', 'hidden');
+ });
+ if (!isiOS()) {
+ // Constructing a Twitter-esque Login:
+ $(".SignInLink").click(function (e) {
+ e.preventDefault();
+ $("#SignInWidget").toggle();
+ $(".ProfileWidget").toggleClass("WidgetOpen");
+ $(this).blur();
+ $("#ctl00_tbUsername").focus();
+ });
+ $(".SignInCloseLink").click(function () {
+ $("#SignInWidget").toggle();
+ $(".ProfileWidget").toggleClass("WidgetOpen");
+ });
+ }
+ $('.SignedInProfileLink').truncate({
+ width: 120,
+ after: '&hellip;',
+ center: false,
+ addclass: false,
+ addtitle: false
+ });
+
+ // Hide the warning message if the user closed it already
+ if ($.cookie('hide_warning') != null) {
+ $(".WarningMessage").hide();
+ } else {
+ $("#warningCloseButton").click(function () {
+ $('.WarningMessage').hide('blind');
+ $.cookie('hide_warning', 'true', { expires: 1 });
+ });
+ }
+
+ function isiOS() {
+ return (
+ (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
+ );
+ }
+ });
+ </script>
+
+ <script type="text/javascript" language="javascript">
+ $(function () {
+ $("a.tb_images").fancybox({ 'titlePosition': 'inside' });
+ });
+
+ $("#ctl00_ContentBody_btnLookupCode").click(function() {
+ if ($("#ctl00_ContentBody_txtTrackingNumber").val().length > 0) {
+ window.location = "/track/details.aspx?tracker=" + $("#ctl00_ContentBody_txtTrackingNumber").val();
+ } else {
+ alert("Please enter a tracking code to search for...");
+ window.setTimeout(hideModalSpinner(), 50);
+ }
+ });
+ </script>
+
+
+ <script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-2020240-1']);
+ _gaq.push(['_trackPageview']);
+ (function () {
+ var ga = document.createElement('script');
+ ga.src = ('https:' == document.location.protocol ?
+ 'https://ssl' : 'http://www') +
+ '.google-analytics.com/ga.js';
+ ga.setAttribute('async', 'true');
+ document.documentElement.firstChild.appendChild(ga);
+ })();
+ $(function () {
+ $("a.language").click(function (e) {
+ e.preventDefault();
+ window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang"));
+ });
+ });
+ </script>
+
+
+ <!-- Quantcast Tag -->
+ <div id="Quantcast">
+ <script type="text/javascript">
+ var _qevents = _qevents || [];
+
+ (function () {
+ var elem = document.createElement('script');
+
+ elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
+ elem.async = true;
+ elem.type = "text/javascript";
+ var scpt = document.getElementsByTagName('script')[0];
+ scpt.parentNode.insertBefore(elem, scpt);
+ })();
+ </script>
+ <script type="text/javascript">
+ _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
+ </script>
+ <noscript>
+ <div style="display: none;">
+ <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
+ alt="Quantcast" /></div>
+ </noscript>
+ </div>
+ <!-- End Quantcast tag -->
+
+ <!-- Server: WEB01; Build: Web.HotFix_20121211.1 -->
+</body>
+</html>
diff --git a/tests/res/raw/trackable_tbxatg.htm b/tests/res/raw/trackable_tbxatg.htm index 2f9139a..532cb4c 100644 --- a/tests/res/raw/trackable_tbxatg.htm +++ b/tests/res/raw/trackable_tbxatg.htm @@ -463,7 +463,7 @@ Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnet </tr><tr id="ctl00_ContentBody_trLogIt">
<td>
<img src="/images/icons/16/write_log.png" width="16" height="16" alt="notebook"
- title="Found it? Log it!" /> <a id="ctl00_ContentBody_LogLink" title="Found it? Log it!" href="log.aspx?wid=a80354bc-752e-44df-8732-159e5bbebd65">Found it? Log it!</a></td>
+ title="Found it? Log it!" /><a id="ctl00_ContentBody_LogLink" title="Found it? Log it!" href="log.aspx?wid=a80354bc-752e-44df-8732-159e5bbebd65">Found it? Log it!</a></td>
</tr><tr id="ctl00_ContentBody_trWatchIt">
<td>
<img src="/images/icons/16/watch.png" width="16" height="16" alt="alert"
diff --git a/tests/src/cgeo/geocaching/CacheTest.java b/tests/src/cgeo/geocaching/CacheTest.java index e1d6efb..905cab0 100644 --- a/tests/src/cgeo/geocaching/CacheTest.java +++ b/tests/src/cgeo/geocaching/CacheTest.java @@ -41,4 +41,10 @@ public class CacheTest extends AndroidTestCase { // different objects with same geocode shall be equal assertTrue(one.equals(two)); } + + public static void testGeocodeUppercase() { + cgCache cache = new cgCache(); + cache.setGeocode("gc1234"); + assertEquals("GC1234", cache.getGeocode()); + } } diff --git a/tests/src/cgeo/geocaching/SettingsTest.java b/tests/src/cgeo/geocaching/SettingsTest.java index 0d395f4..f113180 100644 --- a/tests/src/cgeo/geocaching/SettingsTest.java +++ b/tests/src/cgeo/geocaching/SettingsTest.java @@ -30,6 +30,6 @@ public class SettingsTest extends ActivityInstrumentationTestCase2<cgeo> { } public static void testSettings() { - assertEquals(Settings.getMemberStatus(), GCConstants.MEMBER_STATUS_PM); + assertEquals(GCConstants.MEMBER_STATUS_PM, Settings.getMemberStatus()); } } diff --git a/tests/src/cgeo/geocaching/StoredListTest.java b/tests/src/cgeo/geocaching/StoredListTest.java new file mode 100644 index 0000000..6d8fd64 --- /dev/null +++ b/tests/src/cgeo/geocaching/StoredListTest.java @@ -0,0 +1,18 @@ +package cgeo.geocaching; + +import junit.framework.TestCase; + +public class StoredListTest extends TestCase { + + public static void testStandardListExists() { + StoredList list = cgData.getList(StoredList.STANDARD_LIST_ID); + assertNotNull(list); + } + + public static void testEquals() { + StoredList list1 = cgData.getList(StoredList.STANDARD_LIST_ID); + StoredList list2 = cgData.getList(StoredList.STANDARD_LIST_ID); + assertEquals(list1, list2); + } + +} diff --git a/tests/src/cgeo/geocaching/TrackableTest.java b/tests/src/cgeo/geocaching/TrackableTest.java new file mode 100644 index 0000000..c18d1ea --- /dev/null +++ b/tests/src/cgeo/geocaching/TrackableTest.java @@ -0,0 +1,18 @@ +package cgeo.geocaching; + +import android.test.AndroidTestCase; + +public class TrackableTest extends AndroidTestCase { + + public static void testGetGeocode() { + Trackable trackable = new Trackable(); + trackable.setGeocode("tb1234"); + assertEquals("TB1234", trackable.getGeocode()); + } + + public static void testSetLogsNull() { + Trackable trackable = new Trackable(); + trackable.setLogs(null); + assertNotNull("Trackable logs must not be null!", trackable.getLogs()); + } +} diff --git a/tests/src/cgeo/geocaching/cgWaypointTest.java b/tests/src/cgeo/geocaching/WaypointTest.java index 324d562..273a3bf 100644 --- a/tests/src/cgeo/geocaching/cgWaypointTest.java +++ b/tests/src/cgeo/geocaching/WaypointTest.java @@ -4,15 +4,15 @@ import cgeo.geocaching.enumerations.WaypointType; import android.test.AndroidTestCase; -public class cgWaypointTest extends AndroidTestCase { +public class WaypointTest extends AndroidTestCase { public static void testOrder() { - final cgWaypoint cache = new cgWaypoint("Final", WaypointType.FINAL, false); - final cgWaypoint trailhead = new cgWaypoint("Trail head", WaypointType.TRAILHEAD, false); - final cgWaypoint stage = new cgWaypoint("stage", WaypointType.STAGE, false); - final cgWaypoint puzzle = new cgWaypoint("puzzle", WaypointType.PUZZLE, false); - final cgWaypoint own = new cgWaypoint("own", WaypointType.OWN, true); - final cgWaypoint parking = new cgWaypoint("parking", WaypointType.PARKING, false); + final Waypoint cache = new Waypoint("Final", WaypointType.FINAL, false); + final Waypoint trailhead = new Waypoint("Trail head", WaypointType.TRAILHEAD, false); + final Waypoint stage = new Waypoint("stage", WaypointType.STAGE, false); + final Waypoint puzzle = new Waypoint("puzzle", WaypointType.PUZZLE, false); + final Waypoint own = new Waypoint("own", WaypointType.OWN, true); + final Waypoint parking = new Waypoint("parking", WaypointType.PARKING, false); assertTrue(trailhead.compareTo(puzzle) < 0); assertTrue(trailhead.compareTo(stage) < 0); @@ -33,4 +33,9 @@ public class cgWaypointTest extends AndroidTestCase { assertTrue(parking.compareTo(trailhead) < 0); } + public static void testGeocode() { + Waypoint waypoint = new Waypoint("Test waypoint", WaypointType.PARKING, false); + waypoint.setGeocode("p1"); + assertEquals("P1", waypoint.getGeocode()); + } } diff --git a/tests/src/cgeo/geocaching/cgDataTest.java b/tests/src/cgeo/geocaching/cgDataTest.java index 3cee32f..1c8a0e0 100644 --- a/tests/src/cgeo/geocaching/cgDataTest.java +++ b/tests/src/cgeo/geocaching/cgDataTest.java @@ -18,7 +18,6 @@ public class cgDataTest extends CGeoTestCase { public static void testStoredLists() { - cgeoapplication app = cgeoapplication.getInstance(); int listId1 = StoredList.STANDARD_LIST_ID; int listId2 = StoredList.STANDARD_LIST_ID; @@ -32,11 +31,11 @@ public class cgDataTest extends CGeoTestCase { try { // create lists - listId1 = app.createList("cgData Test"); + listId1 = cgData.createList("cgData Test"); assertTrue(listId1 > StoredList.STANDARD_LIST_ID); - listId2 = app.createList("cgDataTest"); + listId2 = cgData.createList("cgDataTest"); assertTrue(listId2 > StoredList.STANDARD_LIST_ID); - assertTrue(app.getLists().size() >= 2); + assertTrue(cgData.getLists().size() >= 2); cache1.setDetailed(true); cache1.setListId(listId1); @@ -44,33 +43,33 @@ public class cgDataTest extends CGeoTestCase { cache2.setListId(listId1); // save caches to DB (cache1=listId1, cache2=listId1) - app.saveCache(cache1, LoadFlags.SAVE_ALL); - app.saveCache(cache2, LoadFlags.SAVE_ALL); - assertTrue(app.getAllStoredCachesCount(false, CacheType.ALL) >= 2); + cgData.saveCache(cache1, LoadFlags.SAVE_ALL); + cgData.saveCache(cache2, LoadFlags.SAVE_ALL); + assertTrue(cgData.getAllCachesCount() >= 2); // rename list (cache1=listId1, cache2=listId1) - assertEquals(1, app.renameList(listId1, "cgData Test (renamed)")); + assertEquals(1, cgData.renameList(listId1, "cgData Test (renamed)")); // get list - StoredList list1 = app.getList(listId1); + StoredList list1 = cgData.getList(listId1); assertEquals("cgData Test (renamed)", list1.title); // move to list (cache1=listId2, cache2=listId2) - app.moveToList(Collections.singletonList(cache1), listId2); - assertEquals(1, app.getAllStoredCachesCount(false, CacheType.ALL, listId2)); + cgData.moveToList(Collections.singletonList(cache1), listId2); + assertEquals(1, cgData.getAllStoredCachesCount(CacheType.ALL, listId2)); // remove list (cache1=listId2, cache2=listId2) - assertTrue(app.removeList(listId1)); + assertTrue(cgData.removeList(listId1)); // mark dropped (cache1=1, cache2=0) - app.markDropped(Collections.singletonList(cache2)); + cgData.markDropped(Collections.singletonList(cache2)); // mark stored (cache1=1, cache2=listId2) - app.markStored(Collections.singletonList(cache2), listId2); - assertEquals(2, app.getAllStoredCachesCount(false, CacheType.ALL, listId2)); + cgData.moveToList(Collections.singletonList(cache2), listId2); + assertEquals(2, cgData.getAllStoredCachesCount(CacheType.ALL, listId2)); // drop stored (cache1=0, cache2=0) - app.removeList(listId2); + cgData.removeList(listId2); } finally { @@ -78,61 +77,56 @@ public class cgDataTest extends CGeoTestCase { Set<String> geocodes = new HashSet<String>(); geocodes.add(cache1.getGeocode()); geocodes.add(cache2.getGeocode()); - app.removeCaches(geocodes, LoadFlags.REMOVE_ALL); + cgData.removeCaches(geocodes, LoadFlags.REMOVE_ALL); // remove list - app.removeList(listId1); - app.removeList(listId2); + cgData.removeList(listId1); + cgData.removeList(listId2); } } // Check that queries don't throw an exception (see issue #1429). public static void testLoadWaypoints() { final Viewport viewport = new Viewport(new Geopoint(-1, -2), new Geopoint(3, 4)); - final cgeoapplication app = cgeoapplication.getInstance(); - app.getWaypointsInViewport(viewport, false, false, CacheType.ALL); - app.getWaypointsInViewport(viewport, false, true, CacheType.ALL); - app.getWaypointsInViewport(viewport, true, false, CacheType.ALL); - app.getWaypointsInViewport(viewport, true, true, CacheType.ALL); - app.getWaypointsInViewport(viewport, false, false, CacheType.TRADITIONAL); - app.getWaypointsInViewport(viewport, false, true, CacheType.TRADITIONAL); - app.getWaypointsInViewport(viewport, true, false, CacheType.TRADITIONAL); - app.getWaypointsInViewport(viewport, true, true, CacheType.TRADITIONAL); + cgData.loadWaypoints(viewport, false, false, CacheType.ALL); + cgData.loadWaypoints(viewport, false, true, CacheType.ALL); + cgData.loadWaypoints(viewport, true, false, CacheType.ALL); + cgData.loadWaypoints(viewport, true, true, CacheType.ALL); + cgData.loadWaypoints(viewport, false, false, CacheType.TRADITIONAL); + cgData.loadWaypoints(viewport, false, true, CacheType.TRADITIONAL); + cgData.loadWaypoints(viewport, true, false, CacheType.TRADITIONAL); + cgData.loadWaypoints(viewport, true, true, CacheType.TRADITIONAL); } // Check that saving a cache and trackable without logs works (see #2199) public static void testSaveWithoutLogs() { - cgeoapplication app = cgeoapplication.getInstance(); - final String GEOCODE_CACHE = "TEST"; // create cache and trackable final cgCache cache = new cgCache(); cache.setGeocode(GEOCODE_CACHE); cache.setDetailed(true); - final cgTrackable trackable = new cgTrackable(); + final Trackable trackable = new Trackable(); trackable.setLogs(null); - final List<cgTrackable> inventory = new ArrayList<cgTrackable>(); + final List<Trackable> inventory = new ArrayList<Trackable>(); inventory.add(trackable); cache.setInventory(inventory); try { - app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); - final cgCache loadedCache = app.loadCache(GEOCODE_CACHE, LoadFlags.LOAD_ALL_DB_ONLY); + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + final cgCache loadedCache = cgData.loadCache(GEOCODE_CACHE, LoadFlags.LOAD_ALL_DB_ONLY); assertNotNull("Cache was not saved!", loadedCache); assertEquals(1, loadedCache.getInventory().size()); } finally { - app.removeCache(GEOCODE_CACHE, LoadFlags.REMOVE_ALL); + cgData.removeCache(GEOCODE_CACHE, LoadFlags.REMOVE_ALL); } } // Loading logs for an empty geocode should return an empty list, not null! public static void testLoadLogsFromEmptyGeocode() { - cgeoapplication app = cgeoapplication.getInstance(); - - List<LogEntry> logs = app.loadLogs(""); + List<LogEntry> logs = cgData.loadLogs(""); assertNotNull("Logs must not be null", logs); assertEquals("Logs from empty geocode must be empty", 0, logs.size()); diff --git a/tests/src/cgeo/geocaching/cgeoApplicationTest.java b/tests/src/cgeo/geocaching/cgeoApplicationTest.java index f7d3158..fbb860c 100644 --- a/tests/src/cgeo/geocaching/cgeoApplicationTest.java +++ b/tests/src/cgeo/geocaching/cgeoApplicationTest.java @@ -56,7 +56,7 @@ public class cgeoApplicationTest extends CGeoTestCase { */ @MediumTest public static void testSearchTrackableNotExisting() { - cgTrackable tb = GCParser.searchTrackable("123456", null, null); + Trackable tb = GCParser.searchTrackable("123456", null, null); assertNull(tb); } @@ -65,7 +65,7 @@ public class cgeoApplicationTest extends CGeoTestCase { */ @MediumTest public static void testSearchTrackable() { - final cgTrackable tb = GCParser.searchTrackable("TB2J1VZ", null, null); + final Trackable tb = GCParser.searchTrackable("TB2J1VZ", null, null); // fix data assertEquals("aefffb86-099f-444f-b132-605436163aa8", tb.getGuid()); assertEquals("TB2J1VZ", tb.getGeocode()); @@ -82,7 +82,7 @@ public class cgeoApplicationTest extends CGeoTestCase { // Following data can change over time assertTrue(tb.getDistance() >= 10617.8f); assertTrue(tb.getLogs().size() >= 10); - assertTrue(cgTrackable.SPOTTED_CACHE == tb.getSpottedType() || cgTrackable.SPOTTED_USER == tb.getSpottedType()); + assertTrue(Trackable.SPOTTED_CACHE == tb.getSpottedType() || Trackable.SPOTTED_USER == tb.getSpottedType()); // no assumption possible: assertEquals("faa2d47d-19ea-422f-bec8-318fc82c8063", tb.getSpottedGuid()); // no assumption possible: assertEquals("Nice place for a break cache", tb.getSpottedName()); @@ -109,7 +109,7 @@ public class cgeoApplicationTest extends CGeoTestCase { if (Settings.isPremiumMember() || search.getError() == null) { assertEquals(1, search.getGeocodes().size()); assertTrue(search.getGeocodes().contains(geocode)); - return cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + return cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); } assertEquals(0, search.getGeocodes().size()); return null; @@ -191,46 +191,60 @@ public class cgeoApplicationTest extends CGeoTestCase { } /** - * Test {@link cgBase#searchByCoords(AbstractSearchThread, Geopoint, String, int, boolean)} + * mock the "exclude disabled caches" and "exclude my caches" options for the execution of the runnable + * + * @param runnable */ - @MediumTest - public static void testSearchByCoords() { + private static void withMockedFilters(Runnable runnable) { // backup user settings final boolean excludeMine = Settings.isExcludeMyCaches(); + final boolean excludeDisabled = Settings.isExcludeDisabledCaches(); try { // set up settings required for test Settings.setExcludeMine(false); + Settings.setExcludeDisabledCaches(false); + + runnable.run(); - final SearchResult search = GCParser.searchByCoords(new Geopoint("N 52° 24.972 E 009° 35.647"), CacheType.MYSTERY, false); - assertNotNull(search); - assertTrue(20 <= search.getGeocodes().size()); - assertTrue(search.getGeocodes().contains("GC1RMM2")); } finally { // restore user settings Settings.setExcludeMine(excludeMine); + Settings.setExcludeDisabledCaches(excludeDisabled); } } /** + * Test {@link cgBase#searchByCoords(AbstractSearchThread, Geopoint, String, int, boolean)} + */ + @MediumTest + public static void testSearchByCoords() { + withMockedFilters(new Runnable() { + + @Override + public void run() { + final SearchResult search = GCParser.searchByCoords(new Geopoint("N 52° 24.972 E 009° 35.647"), CacheType.MYSTERY, false); + assertNotNull(search); + assertTrue(20 <= search.getGeocodes().size()); + assertTrue(search.getGeocodes().contains("GC1RMM2")); + } + }); + } + + /** * Test {@link cgBase#searchByOwner(String, String, int, boolean, CancellableHandler)} */ @MediumTest public static void testSearchByOwner() { - // backup user settings - final boolean excludeMine = Settings.isExcludeMyCaches(); - try { - // set up settings required for test - Settings.setExcludeMine(false); - - final SearchResult search = GCParser.searchByOwner("blafoo", CacheType.MYSTERY, false); - assertNotNull(search); - assertEquals(3, search.getGeocodes().size()); - assertTrue(search.getGeocodes().contains("GC36RT6")); - - } finally { - // restore user settings - Settings.setExcludeMine(excludeMine); - } + withMockedFilters(new Runnable() { + + @Override + public void run() { + final SearchResult search = GCParser.searchByOwner("blafoo", CacheType.MYSTERY, false); + assertNotNull(search); + assertEquals(3, search.getGeocodes().size()); + assertTrue(search.getGeocodes().contains("GC36RT6")); + } + }); } /** @@ -238,21 +252,16 @@ public class cgeoApplicationTest extends CGeoTestCase { */ @MediumTest public static void testSearchByUsername() { - // backup user settings - final boolean excludeMine = Settings.isExcludeMyCaches(); - try { - // set up settings required for test - Settings.setExcludeMine(false); - - final SearchResult search = GCParser.searchByUsername("blafoo", CacheType.WEBCAM, false); - assertNotNull(search); - assertEquals(3, search.getTotal()); - assertTrue(search.getGeocodes().contains("GCP0A9")); - - } finally { - // restore user settings - Settings.setExcludeMine(excludeMine); - } + withMockedFilters(new Runnable() { + + @Override + public void run() { + final SearchResult search = GCParser.searchByUsername("blafoo", CacheType.WEBCAM, false); + assertNotNull(search); + assertEquals(3, search.getTotal()); + assertTrue(search.getGeocodes().contains("GCP0A9")); + } + }); } /** @@ -260,49 +269,54 @@ public class cgeoApplicationTest extends CGeoTestCase { */ @MediumTest public static void testSearchByViewport() { - // backup user settings - final boolean excludeMine = Settings.isExcludeMyCaches(); - final Strategy strategy = Settings.getLiveMapStrategy(); - - try { - // set up settings required for test - Settings.setExcludeMine(false); - - final GC2CJPF mockedCache = new GC2CJPF(); - deleteCacheFromDB(mockedCache.getGeocode()); - - final String[] tokens = Login.getMapTokens(); - final Viewport viewport = new Viewport(mockedCache, 0.003, 0.003); - - // check coords for DETAILED - Settings.setLiveMapStrategy(Strategy.DETAILED); - SearchResult search = ConnectorFactory.searchByViewport(viewport, tokens); - assertNotNull(search); - assertTrue(search.getGeocodes().contains(mockedCache.getGeocode())); - - cgCache parsedCache = cgeoapplication.getInstance().loadCache(mockedCache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); - - assertEquals(Settings.isPremiumMember(), mockedCache.getCoords().equals(parsedCache.getCoords())); - assertEquals(Settings.isPremiumMember(), parsedCache.isReliableLatLon()); - - // check update after switch strategy to FAST - Settings.setLiveMapStrategy(Strategy.FAST); - Tile.Cache.removeFromTileCache(mockedCache); - - search = ConnectorFactory.searchByViewport(viewport, tokens); - assertNotNull(search); - assertTrue(search.getGeocodes().contains(mockedCache.getGeocode())); - - parsedCache = cgeoapplication.getInstance().loadCache(mockedCache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); - - assertEquals(Settings.isPremiumMember(), mockedCache.getCoords().equals(parsedCache.getCoords())); - assertEquals(Settings.isPremiumMember(), parsedCache.isReliableLatLon()); - - } finally { - // restore user settings - Settings.setExcludeMine(excludeMine); - Settings.setLiveMapStrategy(strategy); - } + withMockedFilters(new Runnable() { + + @Override + public void run() { + // backup user settings + final Strategy strategy = Settings.getLiveMapStrategy(); + final CacheType cacheType = Settings.getCacheType(); + + try { + // set up settings required for test + Settings.setExcludeMine(false); + Settings.setCacheType(CacheType.ALL); + + final GC2CJPF mockedCache = new GC2CJPF(); + deleteCacheFromDB(mockedCache.getGeocode()); + + final String[] tokens = Login.getMapTokens(); + final Viewport viewport = new Viewport(mockedCache, 0.003, 0.003); + + // check coords for DETAILED + Settings.setLiveMapStrategy(Strategy.DETAILED); + SearchResult search = ConnectorFactory.searchByViewport(viewport, tokens); + assertNotNull(search); + assertTrue(search.getGeocodes().contains(mockedCache.getGeocode())); + cgCache parsedCache = cgData.loadCache(mockedCache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); + + assertEquals(Settings.isPremiumMember(), mockedCache.getCoords().equals(parsedCache.getCoords())); + assertEquals(Settings.isPremiumMember(), parsedCache.isReliableLatLon()); + + // check update after switch strategy to FAST + Settings.setLiveMapStrategy(Strategy.FAST); + Tile.Cache.removeFromTileCache(mockedCache); + + search = ConnectorFactory.searchByViewport(viewport, tokens); + assertNotNull(search); + assertTrue(search.getGeocodes().contains(mockedCache.getGeocode())); + parsedCache = cgData.loadCache(mockedCache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); + + assertEquals(Settings.isPremiumMember(), mockedCache.getCoords().equals(parsedCache.getCoords())); + assertEquals(Settings.isPremiumMember(), parsedCache.isReliableLatLon()); + + } finally { + // restore user settings + Settings.setLiveMapStrategy(strategy); + Settings.setCacheType(cacheType); + } + } + }); } /** @@ -316,6 +330,7 @@ public class cgeoApplicationTest extends CGeoTestCase { Strategy strategy = Settings.getLiveMapStrategy(); Strategy testStrategy = Strategy.FAST; // FASTEST, FAST or DETAILED for tests Settings.setLiveMapStrategy(testStrategy); + final CacheType cacheType = Settings.getCacheType(); try { @@ -325,6 +340,7 @@ public class cgeoApplicationTest extends CGeoTestCase { MockedCache cache = new GC2CJPF(); deleteCacheFromDBAndLogout(cache.getGeocode()); Tile.Cache.removeFromTileCache(cache); + Settings.setCacheType(CacheType.ALL); Viewport viewport = new Viewport(cache, 0.003, 0.003); SearchResult search = ConnectorFactory.searchByViewport(viewport, tokens); @@ -332,7 +348,7 @@ public class cgeoApplicationTest extends CGeoTestCase { assertNotNull(search); assertTrue(search.getGeocodes().contains(cache.getGeocode())); // coords differ - cgCache cacheFromViewport = cgeoapplication.getInstance().loadCache(cache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); + cgCache cacheFromViewport = cgData.loadCache(cache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); Log.d("cgeoApplicationTest.testSearchByViewportNotLoggedIn: Coords expected = " + cache.getCoords()); Log.d("cgeoApplicationTest.testSearchByViewportNotLoggedIn: Coords actual = " + cacheFromViewport.getCoords()); assertFalse(cache.getCoords().isEqualTo(cacheFromViewport.getCoords(), 1e-3)); @@ -356,6 +372,7 @@ public class cgeoApplicationTest extends CGeoTestCase { Settings.setMemberStatus(memberStatus); Login.login(); Settings.setLiveMapStrategy(strategy); + Settings.setCacheType(cacheType); } } @@ -390,7 +407,7 @@ public class cgeoApplicationTest extends CGeoTestCase { /** Remove cache from DB and cache to ensure that the cache is not loaded from the database */ private static void deleteCacheFromDB(String geocode) { - cgeoapplication.getInstance().removeCache(geocode, LoadFlags.REMOVE_ALL); + cgData.removeCache(geocode, LoadFlags.REMOVE_ALL); } /** Remove cache from DB and cache to ensure that the cache is not loaded from the database */ diff --git a/tests/src/cgeo/geocaching/compatibility/CompatibilityTest.java b/tests/src/cgeo/geocaching/compatibility/CompatibilityTest.java index 03034f8..35baa8c 100644 --- a/tests/src/cgeo/geocaching/compatibility/CompatibilityTest.java +++ b/tests/src/cgeo/geocaching/compatibility/CompatibilityTest.java @@ -11,7 +11,7 @@ public class CompatibilityTest extends ActivityInstrumentationTestCase2<cgeo> { private cgeo activity; public CompatibilityTest() { - super(cgeo.class); + super("cgeo.geocaching", cgeo.class); } @Override diff --git a/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java b/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java index ea46bbe..ec5ebe2 100644 --- a/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java @@ -3,6 +3,7 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; @@ -12,9 +13,11 @@ public class GCConnectorTest extends AbstractResourceInstrumentationTestCase { public static void testGetViewport() { // backup user settings final boolean excludeMine = Settings.isExcludeMyCaches(); + final CacheType cacheType = Settings.getCacheType(); try { // set up settings required for test Settings.setExcludeMine(false); + Settings.setCacheType(CacheType.ALL); Login.login(); String[] tokens = Login.getMapTokens(); @@ -37,6 +40,7 @@ public class GCConnectorTest extends AbstractResourceInstrumentationTestCase { } finally { // restore user settings Settings.setExcludeMine(excludeMine); + Settings.setCacheType(cacheType); } } diff --git a/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java b/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java index c8cb8fb..6a49c95 100644 --- a/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java @@ -1,10 +1,10 @@ package cgeo.geocaching.connector.gc; +import cgeo.geocaching.Image; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgImage; -import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.geopoint.Geopoint; @@ -18,32 +18,61 @@ import cgeo.test.Compare; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import android.os.Handler; import android.test.suitebuilder.annotation.MediumTest; import java.util.ArrayList; public class GCParserTest extends AbstractResourceInstrumentationTestCase { - public void testUnpublishedCache() { - final String page = getFileContent(R.raw.cache_unpublished); + + public void testUnpublishedCacheNotOwner() { + final int cache = R.raw.cache_unpublished; + assertUnpublished(cache); + } + + public void testUnpublishedCacheOwner() { + final int cache = R.raw.gc433yc_owner_unpublished; + assertUnpublished(cache); + } + + private void assertUnpublished(final int cache) { + final String page = getFileContent(cache); SearchResult result = GCParser.parseCacheFromText(page, null); assertNotNull(result); assertTrue(result.isEmpty()); assertEquals(StatusCode.UNPUBLISHED_CACHE, result.getError()); } + public void testPublishedCacheWithUnpublishedInDescription1() { + assertPublishedCache(R.raw.gc430fm_published, "Cache is Unpublished"); + } + + public void testPublishedCacheWithUnpublishedInDescription2() { + assertPublishedCache(R.raw.gc431f2_published, "Needle in a Haystack"); + } + + private void assertPublishedCache(final int cachePage, final String cacheName) { + final String page = getFileContent(cachePage); + SearchResult result = GCParser.parseCacheFromText(page, null); + assertNotNull(result); + assertEquals(1, result.getCount()); + cgCache cache = result.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); + assertEquals(cacheName, cache.getName()); + } + public void testOwnCache() { final cgCache cache = parseCache(R.raw.own_cache); assertNotNull(cache); assertTrue(CollectionUtils.isNotEmpty(cache.getSpoilers())); assertEquals(1, cache.getSpoilers().size()); - final cgImage spoiler = cache.getSpoilers().get(0); + final Image spoiler = cache.getSpoilers().get(0); assertEquals("http://img.geocaching.com/cache/large/3f9365c3-f55c-4e55-9992-ee0e5175712c.jpg", spoiler.getUrl()); assertEquals("SPOILER", spoiler.getTitle()); assertNull(spoiler.getDescription()); } private static cgCache createCache(int index) { - final MockedCache mockedCache = RegExPerformanceTest.MOCKED_CACHES[index]; + final MockedCache mockedCache = RegExPerformanceTest.MOCKED_CACHES.get(index); // to get the same results we have to use the date format used when the mocked data was created String oldCustomDate = Settings.getGcCustomDate(); @@ -121,9 +150,28 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase { "Station3: N51 21.444 / E07 02.600\r\nStation4: N51 21.789 / E07 02.800\r\nStation5: N51 21.667 / E07 02.800\r\nStation6: N51 21.444 / E07 02.706\r\nStation7: N51 21.321 / E07 02.700\r\nStation8: N51 21.123 / E07 02.477\r\nStation9: N51 21.734 / E07 02.500\r\nStation10: N51 21.733 / E07 02.378\r\nFinal: N51 21.544 / E07 02.566"); } + @MediumTest + public static void testEditModifiedCoordinates() { + cgCache cache = new cgCache(); + cache.setGeocode("GC2ZN4G"); + // upload coordinates + GCParser.editModifiedCoordinates(cache, new Geopoint("N51 21.544", "E07 02.566")); + cache.drop(new Handler()); + String page = GCParser.requestHtmlPage(cache.getGeocode(), null, "n", "0"); + cgCache cache2 = GCParser.parseCacheFromText(page, null).getFirstCacheFromResult(LoadFlags.LOAD_CACHE_ONLY); + assertTrue(cache2.hasUserModifiedCoords()); + assertEquals(new Geopoint("N51 21.544", "E07 02.566"), cache2.getCoords()); + // delete coordinates + GCParser.deleteModifiedCoordinates(cache2); + cache2.drop(new Handler()); + String page2 = GCParser.requestHtmlPage(cache.getGeocode(), null, "n", "0"); + cgCache cache3 = GCParser.parseCacheFromText(page2, null).getFirstCacheFromResult(LoadFlags.LOAD_CACHE_ONLY); + assertFalse(cache3.hasUserModifiedCoords()); + } + private static void assertWaypointsFromNote(final cgCache cache, Geopoint[] expected, String note) { cache.setPersonalNote(note); - cache.setWaypoints(new ArrayList<cgWaypoint>(), false); + cache.setWaypoints(new ArrayList<Waypoint>(), false); cache.parseWaypointsFromNote(); assertEquals(expected.length, cache.getWaypoints().size()); for (int i = 0; i < expected.length; i++) { diff --git a/tests/src/cgeo/geocaching/connector/gc/IconDecoderTest.java b/tests/src/cgeo/geocaching/connector/gc/IconDecoderTest.java index 3fa17f8..af5d1bc 100644 --- a/tests/src/cgeo/geocaching/connector/gc/IconDecoderTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/IconDecoderTest.java @@ -15,10 +15,10 @@ public class IconDecoderTest extends AbstractResourceInstrumentationTestCase { final Bitmap bitmap = getBitmap(R.raw.tile14); Log.d("Bitmap=" + bitmap.getWidth() + "x" + bitmap.getHeight()); - assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 97, 136, 14).getType()); - assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 226, 104, 14).getType()); - assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 54, 97, 14).getType()); - assertTrue(parseMapPNG(bitmap, 119, 108, 14).isFound()); + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 88, 124, 14).getType()); + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 228, 104, 14).getType()); + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 52, 92, 14).getType()); + assertTrue(parseMapPNG(bitmap, 108, 112, 14).isFound()); } private Bitmap getBitmap(int resourceId) { @@ -58,7 +58,7 @@ public class IconDecoderTest extends AbstractResourceInstrumentationTestCase { int mystery = 0; mystery = parseMapPNG(bitmap, 37, 25, 12).getType() == CacheType.MYSTERY ? mystery + 1 : mystery; mystery = parseMapPNG(bitmap, 49, 183, 12).getType() == CacheType.MYSTERY ? mystery + 1 : mystery; - mystery = parseMapPNG(bitmap, 183, 181, 12).getType() == CacheType.MYSTERY ? mystery + 1 : mystery; + mystery = parseMapPNG(bitmap, 184, 181, 12).getType() == CacheType.MYSTERY ? mystery + 1 : mystery; mystery = parseMapPNG(bitmap, 176, 94, 12).getType() == CacheType.MYSTERY ? mystery + 1 : mystery; mystery = parseMapPNG(bitmap, 161, 124, 12).getType() == CacheType.MYSTERY ? mystery + 1 : mystery; mystery = parseMapPNG(bitmap, 168, 118, 12).getType() == CacheType.MYSTERY ? mystery + 1 : mystery; @@ -73,9 +73,351 @@ public class IconDecoderTest extends AbstractResourceInstrumentationTestCase { tradi = parseMapPNG(bitmap, 117, 225, 12).getType() == CacheType.TRADITIONAL ? tradi + 1 : tradi; tradi = parseMapPNG(bitmap, 90, 107, 12).getType() == CacheType.TRADITIONAL ? tradi + 1 : tradi; + int found = 0; + found = parseMapPNG(bitmap, 150, 124, 12).isFound() ? found + 1 : found; + found = parseMapPNG(bitmap, 176, 82, 12).isFound() ? found + 1 : found; + found = parseMapPNG(bitmap, 240, 140, 12).isFound() ? found + 1 : found; + found = parseMapPNG(bitmap, 211, 127, 12).isFound() ? found + 1 : found; + assertEquals(7, multi); assertEquals(7, mystery); assertEquals(7, tradi); + assertEquals(4, found); + } + + public void testParseExtraMap1() { + final Bitmap bitmap = getBitmap(R.raw.map1); + assertTrue(parseMapPNG(bitmap, 128, 168, 12).isFound()); // GC3AT8B + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 172, 164, 12).getType()); // GC39EXB + assertTrue(parseMapPNG(bitmap, 164, 156, 12).isFound()); // GC30M7M + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 204, 72, 12).getType()); // GC3AN5Z + assertTrue(parseMapPNG(bitmap, 188, 92, 12).isFound()); // GC37T3R + assertTrue(parseMapPNG(bitmap, 164, 132, 12).isFound()); // GC34JME + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 176, 148, 12).getType()); // GC37TCY + assertEquals(CacheType.EARTH, parseMapPNG(bitmap, 180, 136, 12).getType()); // GC3947Z + assertTrue(parseMapPNG(bitmap, 164, 100, 12).isFound()); // GC2ZY3X + assertTrue(parseMapPNG(bitmap, 52, 104, 12).isFound()); // GC29RCW + assertTrue(parseMapPNG(bitmap, 168, 88, 12).isFound()); // GC264JZ + assertTrue(parseMapPNG(bitmap, 168, 140, 12).isFound()); // GC37RRV + } + + public void testParseExtraMap2() { + final Bitmap bitmap = getBitmap(R.raw.map2); + + assertTrue(parseMapPNG(bitmap, 132, 136, 12).isFound()); // GC3JDBW + assertTrue(parseMapPNG(bitmap, 68, 24, 12).isFound()); // GC2T0AH + assertTrue(parseMapPNG(bitmap, 176, 232, 12).isOwn()); // GC2RPBX + assertTrue(parseMapPNG(bitmap, 148, 60, 12).isFound()); // GC31FY6 + assertTrue(parseMapPNG(bitmap, 216, 20, 12).isFound()); // GC2KP3M + assertTrue(parseMapPNG(bitmap, 212, 184, 12).isOwn()); // GC30W3K + assertTrue(parseMapPNG(bitmap, 148, 72, 12).isOwn()); // GC2RPAZ + assertTrue(parseMapPNG(bitmap, 216, 48, 12).isOwn()); // GC2RP8W + assertTrue(parseMapPNG(bitmap, 212, 60, 12).isFound()); // GC3CC97 + assertTrue(parseMapPNG(bitmap, 148, 100, 12).isOwn()); // GC2RPAT + assertTrue(parseMapPNG(bitmap, 104, 136, 12).isFound()); // GC3AE31 + assertTrue(parseMapPNG(bitmap, 52, 96, 12).isOwn()); // GC2RPCH + assertTrue(parseMapPNG(bitmap, 172, 156, 12).isOwn()); // GC2RQ07 + assertTrue(parseMapPNG(bitmap, 116, 56, 12).isFound()); // GC3AYR2 + assertTrue(parseMapPNG(bitmap, 208, 68, 12).isOwn()); // GC2RP93 + assertTrue(parseMapPNG(bitmap, 200, 52, 12).isOwn()); // GC2RPAA + assertTrue(parseMapPNG(bitmap, 208, 44, 12).isFound()); // GC3HE15 + assertTrue(parseMapPNG(bitmap, 112, 76, 12).isOwn()); // GC2RPBE + assertTrue(parseMapPNG(bitmap, 232, 192, 12).isOwn()); // GC2E1KF + assertTrue(parseMapPNG(bitmap, 184, 76, 12).isFound()); // GC2NK5R + assertTrue(parseMapPNG(bitmap, 132, 148, 12).isOwn()); // GC2RPBC + } + + public void testParseExtraMap3() { + final Bitmap bitmap = getBitmap(R.raw.map3); + + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 44, 0, 12).getType()); // GC1THF5 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 176, 100, 12).getType()); // GC29EGE + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 212, 128, 12).getType()); // GC1VR64 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 220, 56, 12).getType()); // GC1M13A + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 120, 80, 12).getType()); // GC1ZA2Z + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 148, 56, 12).getType()); // GC1MRD8 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 252, 8, 12).getType()); // GC3AGEX + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 76, 108, 12).getType()); // GC2C5RB + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 228, 188, 12).getType()); // GC33TWE + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 232, 128, 12).getType()); // GC38QDJ + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 228, 160, 12).getType()); // GC2G8M1 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 184, 64, 12).getType()); // GC2FYH4 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 60, 132, 12).getType()); // GC299CV + assertEquals(CacheType.EVENT, parseMapPNG(bitmap, 244, 124, 12).getType()); // GC3E5FW + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 200, 160, 12).getType()); // GC29NR9 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 216, 116, 12).getType()); // GC17P5R + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 144, 92, 12).getType()); // GC1WYN3 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 80, 4, 12).getType()); // GC2Z90W + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 216, 148, 12).getType()); // GC29M3P + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 176, 148, 12).getType()); // GC2HJ88 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 68, 72, 12).getType()); // GC1VRB4 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 232, 100, 12).getType()); // GC29EG4 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 220, 68, 12).getType()); // GC2YXH8 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 248, 156, 12).getType()); // GC1F277 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 208, 80, 12).getType()); // GC2NV6T + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 60, 92, 12).getType()); // GC2Y2YY + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 188, 168, 12).getType()); // GC26RT7 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 224, 124, 12).getType()); // GC1ZBPC + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 144, 80, 12).getType()); // GC29NQJ + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 192, 124, 12).getType()); // GC1QRAP + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 104, 116, 12).getType()); // GC29NR1 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 240, 44, 12).getType()); // GC35KYR + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 168, 0, 12).getType()); // GC1VR78 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 200, 84, 12).getType()); // GC2YR8Z + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 52, 160, 12).getType()); // GC1MTD8 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 236, 156, 12).getType()); // GCYW8A + + } + + public void testParseExtraMap4() { + final Bitmap bitmap = getBitmap(R.raw.map4); + + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 124, 84, 12).getType()); // GC2M3CD + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 92, 140, 12).getType()); // GC1W2A2 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 156, 108, 12).getType()); // GC3FR70 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 44, 72, 12).getType()); // GC10W91 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 104, 36, 12).getType()); // GCRC1W + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 88, 36, 12).getType()); // GC30PQF + assertTrue(parseMapPNG(bitmap, 116, 36, 12).isFound()); // GC17VWA + assertEquals(CacheType.EARTH, parseMapPNG(bitmap, 28, 56, 12).getType()); // GC1E6A6 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 96, 72, 12).getType()); // GCMVAC + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 140, 48, 12).getType()); // GCZPE4 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 88, 84, 12).getType()); // GC16G8B + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 116, 48, 12).getType()); // GCZPEB + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 148, 8, 12).getType()); // GC19QQ4 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 68, 124, 12).getType()); // GCXJGD + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 88, 156, 12).getType()); // GC1VNAE + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 24, 24, 12).getType()); // GC1AY4H + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 180, 60, 12).getType()); // GC3K4HB + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 56, 104, 12).getType()); // GC2M4EH + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 12, 132, 12).getType()); // GC2B92G + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 240, 180, 12).getType()); // GC2YJ88 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 220, 140, 12).getType()); // GC2AWBC + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 124, 44, 12).getType()); // GC16V66 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 116, 104, 12).getType()); // GC2MN5V + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 212, 4, 12).getType()); // GC3BF7V + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 168, 40, 12).getType()); // GC1PB21 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 252, 56, 12).getType()); // GC22VTB + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 108, 64, 12).getType()); // GCVE3B + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 20, 140, 12).getType()); // GC1R041 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 124, 244, 12).getType()); // GC3DWEA + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 240, 136, 12).getType()); // GC249ZE + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 124, 56, 12).getType()); // GC1X0XJ + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 56, 16, 12).getType()); // GC2ZVGB + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 164, 164, 12).getType()); // GC3D65W + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 240, 128, 12).getType()); // GC33KV9 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 220, 244, 12).getType()); // GC21VT0 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 84, 24, 12).getType()); // GC1949K + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 104, 88, 12).getType()); // GC1FKZY + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 56, 248, 12).getType()); // GC2Y5Z4 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 72, 32, 12).getType()); // GC395J6 + assertTrue(parseMapPNG(bitmap, 180, 4, 12).isFound()); // GC21MFG + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 96, 100, 12).getType()); // GC1W45E + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 144, 160, 12).getType()); // GC37BA1 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 12, 4, 12).getType()); // GC1K8KR + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 172, 92, 12).getType()); // GC3EZZ4 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 188, 132, 12).getType()); // GC26T9J + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 68, 192, 12).getType()); // GC1ZAMG + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 176, 180, 12).getType()); // GC21EZE + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 172, 76, 12).getType()); // GC1G5PT + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 208, 112, 12).getType()); // GC132VV + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 156, 40, 12).getType()); // GC264J4 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 252, 140, 12).getType()); // GC2JBNE + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 112, 76, 12).getType()); // GC16VKJ + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 16, 156, 12).getType()); // GC2ADX3 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 68, 48, 12).getType()); // GC2AZT1 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 176, 252, 12).getType()); // GC3DWNM + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 4, 156, 12).getType()); // GC30VHE + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 156, 120, 12).getType()); // GC1T9WM + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 40, 48, 12).getType()); // GC30MTZ + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 180, 232, 12).getType()); // GC2XVQA + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 72, 92, 12).getType()); // GC1VVA9 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 0, 132, 12).getType()); // GC1XNN4 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 92, 192, 12).getType()); // GC11D9P + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 52, 84, 12).getType()); // GC2M693 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 176, 196, 12).getType()); // GCZHVE + assertTrue(parseMapPNG(bitmap, 140, 108, 12).isFound()); // GC1Q5PW + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 108, 148, 12).getType()); // GC2ZR0C + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 168, 8, 12).getType()); // GCYWQH + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 196, 92, 12).getType()); // GC39VXN + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 148, 136, 12).getType()); // GC2MM6C + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 168, 28, 12).getType()); // GC2H1TG + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 240, 52, 12).getType()); // GC2QTXT + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 152, 148, 12).getType()); // GC3E7QD + assertTrue(parseMapPNG(bitmap, 160, 60, 12).isFound()); // GC2J3G9 + assertTrue(parseMapPNG(bitmap, 160, 100, 12).isFound()); // GC2327G + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 136, 32, 12).getType()); // GC2JVEH + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 208, 164, 12).getType()); // GC1NN15 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 84, 244, 12).getType()); // GC3E5JP + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 172, 16, 12).getType()); // GC1Z581 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 104, 20, 12).getType()); // GC2MENX + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 144, 60, 12).getType()); // GC1V3MG + assertTrue(parseMapPNG(bitmap, 228, 56, 12).isFound()); // GC36WZN + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 144, 212, 12).getType()); // GCR9GB + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 180, 68, 12).getType()); // GC3JZ1K + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 228, 104, 12).getType()); // GCQ95T + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 84, 220, 12).getType()); // GCWTVM + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 200, 228, 12).getType()); // GC3CC1A + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 204, 56, 12).getType()); // GC1K0WX + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 244, 208, 12).getType()); // GC1JVXG + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 84, 128, 12).getType()); // GC2XQ6C + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 248, 164, 12).getType()); // GC3B1JK + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 232, 84, 12).getType()); // GC3AT8J + assertTrue(parseMapPNG(bitmap, 160, 88, 12).isFound()); // GC2MB4P + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 132, 20, 12).getType()); // GC2NW3F + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 56, 132, 12).getType()); // GC22ERA + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 28, 32, 12).getType()); // GC2EFFK + } + + public void testParseExtraMap5() { + final Bitmap bitmap = getBitmap(R.raw.map5); + + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 60, 32, 12).getType()); // GC31DNK + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 200, 120, 12).getType()); // GCP89K + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 144, 152, 12).getType()); // GC22AR8 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 164, 92, 12).getType()); // GC1MFB7 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 16, 212, 12).getType()); // GC12F2K + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 188, 12, 12).getType()); // GC24J14 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 36, 72, 12).getType()); // GC2J8MY + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 152, 140, 12).getType()); // GC1H9WQ + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 44, 40, 12).getType()); // GC31DNZ + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 8, 152, 12).getType()); // GC34YFB + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 200, 216, 12).getType()); // GC30MK5 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 84, 20, 12).getType()); // GC304YY + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 192, 236, 12).getType()); // GC1D6AC + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 220, 48, 12).getType()); // GC1HQ8Y + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 136, 176, 12).getType()); // GC310B7 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 132, 232, 12).getType()); // GC12CR5 + assertTrue(parseMapPNG(bitmap, 240, 40, 12).isFound()); // GC24GW1 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 140, 116, 12).getType()); // GC2YYE7 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 124, 144, 12).getType()); // GC111RZ + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 48, 128, 12).getType()); // GC13A7V + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 136, 92, 12).getType()); // GC2BKW9 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 200, 184, 12).getType()); // GC30X0C + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 156, 200, 12).getType()); // GC17V4A + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 160, 120, 12).getType()); // GC2ZBWW + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 196, 36, 12).getType()); // GC14X25 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 192, 100, 12).getType()); // GC1HXAX + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 108, 168, 12).getType()); // GC3C043 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 232, 28, 12).getType()); // GC1TEAR + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 200, 204, 12).getType()); // GC3AKFV + assertTrue(parseMapPNG(bitmap, 228, 28, 12).isFound()); // GC2NMPR + //assertEquals(CacheType.VIRTUAL, parseMapPNG(bitmap, 232, 252, 12).getType()); // GC1AH0N - False detection + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 220, 188, 12).getType()); // GC1ZXDK + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 168, 212, 12).getType()); // GC3A919 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 152, 176, 12).getType()); // GC196WN + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 144, 180, 12).getType()); // GC12RE5 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 176, 116, 12).getType()); // GC1DY2M + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 44, 212, 12).getType()); // GC3MRNT + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 220, 36, 12).getType()); // GC3CWZD + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 48, 160, 12).getType()); // GC1A8E3 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 8, 252, 12).getType()); // GC10W6W + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 60, 92, 12).getType()); // GC2D9DD + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 96, 164, 12).getType()); // GC1Z4QX + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 220, 252, 12).getType()); // GCNEGK + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 32, 188, 12).getType()); // GC10916 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 204, 224, 12).getType()); // GC1CA2Y + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 120, 236, 12).getType()); // GC11B3J + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 248, 24, 12).getType()); // GCKX8C + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 128, 152, 12).getType()); // GC2V6AA + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 196, 48, 12).getType()); // GC2YG95 + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 48, 64, 12).getType()); // GCHGR8 + assertEquals(CacheType.EVENT, parseMapPNG(bitmap, 188, 96, 12).getType()); // GC3KBPK + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 208, 140, 12).getType()); // GC1C9B0 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 164, 100, 12).getType()); // GC29JGA + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 156, 28, 12).getType()); // GCN690 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 232, 20, 12).getType()); // GC18Z53 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 220, 152, 12).getType()); // GC18RB6 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 200, 248, 12).getType()); // GC2378H + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 248, 244, 12).getType()); // GCV8QA + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 12, 232, 12).getType()); // GC2MXDG + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 48, 248, 12).getType()); // GCTHJR + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 216, 200, 12).getType()); // GC1EPM5 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 232, 60, 12).getType()); // GC2N0PB + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 88, 56, 12).getType()); // GC1ZWNX + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 248, 56, 12).getType()); // GC1N11P + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 100, 180, 12).getType()); // GCM6AE + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 220, 124, 12).getType()); // GC2A1RQ + assertTrue(parseMapPNG(bitmap, 212, 4, 12).isFound()); // GC1TVKE + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 28, 212, 12).getType()); // GC2A1RR + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 128, 84, 12).getType()); // GC16AWC + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 220, 16, 12).getType()); // GC282V9 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 112, 240, 12).getType()); // GC18VT5 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 80, 248, 12).getType()); // GC10YEK + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 224, 228, 12).getType()); // GC1EA70 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 232, 244, 12).getType()); // GC14PNY + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 108, 32, 12).getType()); // GC2MMPN + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 144, 188, 12).getType()); // GC1CCF4 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 228, 208, 12).getType()); // GCV8C2 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 104, 252, 12).getType()); // GCTRPF + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 176, 92, 12).getType()); // GCRF8G + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 120, 140, 12).getType()); // GC210B9 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 204, 240, 12).getType()); // GC16NTW + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 192, 224, 12).getType()); // GC2PTVN + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 76, 116, 12).getType()); // GC1RPG0 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 144, 200, 12).getType()); // GC1FZ4T + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 172, 36, 12).getType()); // GC1ZYG8 + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 248, 196, 12).getType()); // GC17FJQ + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 88, 140, 12).getType()); // GC1KWK0 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 168, 196, 12).getType()); // GC17MNG + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 20, 252, 12).getType()); // GC13M6V + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 120, 172, 12).getType()); // GC3B30A + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 104, 92, 12).getType()); // GC2GY9D + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 128, 120, 12).getType()); // GC2Y90M + assertTrue(parseMapPNG(bitmap, 204, 40, 12).isFound()); // GC1BZ6P + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 56, 76, 12).getType()); // GC10K7X + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 196, 108, 12).getType()); // GC1F0R5 + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 120, 196, 12).getType()); // GC1KQQW + } + + public void testParseExtraMap11() { + final Bitmap bitmap = getBitmap(R.raw.map11); + assertEquals(CacheType.EVENT, parseMapPNG(bitmap, 132, 16, 11).getType()); + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 104, 48, 11).getType()); + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 128, 124, 11).getType()); + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 228, 8, 11).getType()); + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 160, 156, 11).getType()); + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 208, 176, 11).getType()); + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 252, 24, 11).getType()); + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 216, 96, 11).getType()); + assertEquals(CacheType.EARTH, parseMapPNG(bitmap, 24, 212, 11).getType()); + } + + public void testParseExtraMapall14() { + final Bitmap bitmap = getBitmap(R.raw.map_all14); + assertTrue(parseMapPNG(bitmap, 40, 16, 14).isFound()); + assertTrue(parseMapPNG(bitmap, 72, 16, 14).isFound()); + assertTrue(parseMapPNG(bitmap, 100, 16, 14).isFound()); + assertTrue(parseMapPNG(bitmap, 128, 16, 14).isFound()); + assertTrue(parseMapPNG(bitmap, 44, 44, 14).isOwn()); + assertTrue(parseMapPNG(bitmap, 76, 44, 14).isOwn()); + assertTrue(parseMapPNG(bitmap, 132, 44, 14).isOwn()); + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 40, 72, 14).getType()); + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 72, 72, 14).getType()); + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 100, 72, 14).getType()); + assertEquals(CacheType.MULTI, parseMapPNG(bitmap, 128, 72, 14).getType()); + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 40, 96, 14).getType()); + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 72, 96, 14).getType()); + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 100, 96, 14).getType()); + assertEquals(CacheType.MYSTERY, parseMapPNG(bitmap, 128, 96, 14).getType()); + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 40, 124, 14).getType()); + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 72, 124, 14).getType()); + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 100, 124, 14).getType()); + assertEquals(CacheType.TRADITIONAL, parseMapPNG(bitmap, 128, 124, 14).getType()); + assertEquals(CacheType.WHERIGO, parseMapPNG(bitmap, 40, 160, 14).getType()); + assertEquals(CacheType.WHERIGO, parseMapPNG(bitmap, 72, 160, 14).getType()); + assertEquals(CacheType.WHERIGO, parseMapPNG(bitmap, 100, 160, 14).getType()); + assertEquals(CacheType.WHERIGO, parseMapPNG(bitmap, 128, 160, 14).getType()); + assertEquals(CacheType.LETTERBOX, parseMapPNG(bitmap, 40, 184, 14).getType()); + assertEquals(CacheType.LETTERBOX, parseMapPNG(bitmap, 72, 184, 14).getType()); + assertEquals(CacheType.LETTERBOX, parseMapPNG(bitmap, 100, 184, 14).getType()); + assertEquals(CacheType.LETTERBOX, parseMapPNG(bitmap, 128, 184, 14).getType()); + assertEquals(CacheType.CITO, parseMapPNG(bitmap, 12, 224, 14).getType()); + assertEquals(CacheType.EVENT, parseMapPNG(bitmap, 40, 220, 14).getType()); + assertEquals(CacheType.EARTH, parseMapPNG(bitmap, 68, 224, 14).getType()); + assertEquals(CacheType.MEGA_EVENT, parseMapPNG(bitmap, 96, 224, 14).getType()); + assertEquals(CacheType.WEBCAM, parseMapPNG(bitmap, 120, 224, 14).getType()); + assertEquals(CacheType.VIRTUAL, parseMapPNG(bitmap, 144, 224, 14).getType()); } } diff --git a/tests/src/cgeo/geocaching/connector/gc/TrackablesTest.java b/tests/src/cgeo/geocaching/connector/gc/TrackablesTest.java index 319a3b2..ea430ac 100644 --- a/tests/src/cgeo/geocaching/connector/gc/TrackablesTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/TrackablesTest.java @@ -1,8 +1,10 @@ package cgeo.geocaching.connector.gc; +import cgeo.geocaching.Image; import cgeo.geocaching.LogEntry; import cgeo.geocaching.TrackableLog; -import cgeo.geocaching.cgTrackable; +import cgeo.geocaching.Trackable; +import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; import cgeo.geocaching.test.R; import cgeo.geocaching.utils.BaseUtils; @@ -27,36 +29,50 @@ public class TrackablesTest extends AbstractResourceInstrumentationTestCase { } public void testTrackable() { - final cgTrackable trackable = getTB2R124(); + final Trackable trackable = getTB2R124(); assertEquals("TB2R124", trackable.getGeocode()); assertEquals("Bor. Dortmund - FC Schalke 04", trackable.getName()); assertEquals("Spiridon Lui", trackable.getOwner()); } public void testTrackableWithoutImage() { - final cgTrackable trackable = getTB2R124(); + final Trackable trackable = getTB2R124(); assertNull(trackable.getImage()); assertNotNull(trackable.getDetails()); } public void testTrackableWithLogImages() { - final cgTrackable trackable = getTBXATG(); + final Trackable trackable = getTBXATG(); assertEquals("TBXATG", trackable.getGeocode()); List<LogEntry> log = trackable.getLogs(); - // second log entry has several images; just check first two - assertEquals("http://img.geocaching.com/track/log/large/f2e24c50-394c-4d74-8fb4-87298d8bff1d.jpg", log.get(4).getLogImages().get(0).getUrl()); - assertEquals("7b Welcome to Geowoodstock", log.get(4).getLogImages().get(0).getTitle()); - assertEquals("http://img.geocaching.com/track/log/large/b57c29c3-134e-4202-a2a1-69ce8920b055.jpg", log.get(4).getLogImages().get(1).getUrl()); - assertEquals("8 Crater Lake Natl Park Oregon", log.get(4).getLogImages().get(1).getTitle()); + assertNotNull(log); + assertEquals(10, log.size()); + // log entry 4 has several images; just check first two + + final List<Image> log4Images = log.get(4).getLogImages(); + assertNotNull(log4Images); + assertEquals(5, log4Images.size()); + assertEquals("http://img.geocaching.com/track/log/large/f2e24c50-394c-4d74-8fb4-87298d8bff1d.jpg", log4Images.get(0).getUrl()); + assertEquals("7b Welcome to Geowoodstock", log4Images.get(0).getTitle()); + assertEquals("http://img.geocaching.com/track/log/large/b57c29c3-134e-4202-a2a1-69ce8920b055.jpg", log4Images.get(1).getUrl()); + assertEquals("8 Crater Lake Natl Park Oregon", log4Images.get(1).getTitle()); // third log entry has one image - assertEquals("http://img.geocaching.com/track/log/large/0096b42d-4d10-45fa-9be2-2d08c0d5cc61.jpg", log.get(5).getLogImages().get(0).getUrl()); - assertEquals("Traverski's GC Univ coin on tour", log.get(5).getLogImages().get(0).getTitle()); + final List<Image> log5Images = log.get(5).getLogImages(); + assertNotNull(log5Images); + assertEquals(1, log5Images.size()); + assertEquals("http://img.geocaching.com/track/log/large/0096b42d-4d10-45fa-9be2-2d08c0d5cc61.jpg", log5Images.get(0).getUrl()); + assertEquals("Traverski's GC Univ coin on tour", log5Images.get(0).getTitle()); + + for (LogEntry entry : log) { + assertFalse(entry.log.startsWith("<div>")); + } + assertEquals("traveling", log.get(0).log); } public void testParseTrackableWithoutReleaseDate() { - cgTrackable trackable = GCParser.parseTrackable(getFileContent(R.raw.tb14wfv), null); + Trackable trackable = parseTrackable(R.raw.tb14wfv); assertNotNull(trackable); assertEquals("The Brickster", trackable.getName()); assertEquals("Adrian C", trackable.getOwner()); @@ -69,7 +85,7 @@ public class TrackablesTest extends AbstractResourceInstrumentationTestCase { } public void testParseRelativeLink() { - final cgTrackable trackable = GCParser.parseTrackable(getFileContent(R.raw.tb4cwjx), null); + final Trackable trackable = parseTrackable(R.raw.tb4cwjx); assertNotNull(trackable); assertEquals("The Golden Lisa", trackable.getName()); final String goal = trackable.getGoal(); @@ -78,16 +94,31 @@ public class TrackablesTest extends AbstractResourceInstrumentationTestCase { assertTrue(goal.contains("href=\"http://www.geocaching.com/seek/cache_details.aspx?wp=GC3B7PD#\"")); } - private cgTrackable getTB2R124() { - return GCParser.parseTrackable(BaseUtils.replaceWhitespace(getFileContent(R.raw.trackable_tb2r124)), null); + private Trackable parseTrackable(int trackablePage) { + String pageContent = getFileContent(trackablePage); + return GCParser.parseTrackable(BaseUtils.replaceWhitespace(pageContent), null); } - private cgTrackable getTBXATG() { - return GCParser.parseTrackable(BaseUtils.replaceWhitespace(getFileContent(R.raw.trackable_tbxatg)), null); + public void testParseMarkMissing() { + final Trackable trackable = parseTrackable(R.raw.tb29ggq); + assertNotNull(trackable); + final List<LogEntry> logs = trackable.getLogs(); + assertNotNull(logs); + assertFalse(logs.isEmpty()); + LogEntry marked = logs.get(4); + assertEquals(LogType.MARKED_MISSING, marked.type); + } + + private Trackable getTB2R124() { + return parseTrackable(R.raw.trackable_tb2r124); + } + + private Trackable getTBXATG() { + return parseTrackable(R.raw.trackable_tbxatg); } public void testParseTrackableNotExisting() { - cgTrackable trackable = GCParser.parseTrackable(getFileContent(R.raw.tb_not_existing), null); + Trackable trackable = GCParser.parseTrackable(getFileContent(R.raw.tb_not_existing), null); assertNull(trackable); } diff --git a/tests/src/cgeo/geocaching/connector/opencaching/OkapiClientTest.java b/tests/src/cgeo/geocaching/connector/opencaching/OkapiClientTest.java index 5576028..0519b58 100644 --- a/tests/src/cgeo/geocaching/connector/opencaching/OkapiClientTest.java +++ b/tests/src/cgeo/geocaching/connector/opencaching/OkapiClientTest.java @@ -2,7 +2,7 @@ package cgeo.geocaching.connector.opencaching; import cgeo.CGeoTestCase; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.connector.oc.OkapiClient; import cgeo.geocaching.enumerations.LoadFlags; @@ -15,9 +15,8 @@ public class OkapiClientTest extends CGeoTestCase { assertEquals(geoCode, cache.getGeocode()); assertEquals("Oshkosh Municipal Tank", cache.getName()); assertTrue(cache.isDetailed()); - // cache should be stored to DB (to listID 0) when loaded above - cache = cgeoapplication.getInstance().loadCache(geoCode, LoadFlags.LOAD_ALL_DB_ONLY); + cache = cgData.loadCache(geoCode, LoadFlags.LOAD_ALL_DB_ONLY); assertNotNull(cache); assertEquals(geoCode, cache.getGeocode()); assertEquals("Oshkosh Municipal Tank", cache.getName()); diff --git a/tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java b/tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java index c872c9d..9c3063d 100644 --- a/tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java +++ b/tests/src/cgeo/geocaching/enumerations/CacheSizeTest.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import android.test.AndroidTestCase; +import java.util.Locale; + public class CacheSizeTest extends AndroidTestCase { public static void testOrder() { @@ -15,13 +17,14 @@ public class CacheSizeTest extends AndroidTestCase { assertEquals(CacheSize.UNKNOWN, CacheSize.getById(null)); assertEquals(CacheSize.UNKNOWN, CacheSize.getById("random garbage")); assertEquals(CacheSize.LARGE, CacheSize.getById("large")); + assertEquals(CacheSize.LARGE, CacheSize.getById("LARGE")); } public static void testGetByIdComplete() { for (CacheSize size : CacheSize.values()) { assertEquals(size, CacheSize.getById(size.id)); - assertEquals(size, CacheSize.getById(size.id.toLowerCase())); - assertEquals(size, CacheSize.getById(size.id.toUpperCase())); + assertEquals(size, CacheSize.getById(size.id.toLowerCase(Locale.US))); + assertEquals(size, CacheSize.getById(size.id.toUpperCase(Locale.US))); } } } diff --git a/tests/src/cgeo/geocaching/enumerations/CacheTypeTest.java b/tests/src/cgeo/geocaching/enumerations/CacheTypeTest.java index dd35669..21e97c0 100644 --- a/tests/src/cgeo/geocaching/enumerations/CacheTypeTest.java +++ b/tests/src/cgeo/geocaching/enumerations/CacheTypeTest.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import android.test.AndroidTestCase; +import java.util.Locale; + public class CacheTypeTest extends AndroidTestCase { public static void testGetById() { @@ -21,16 +23,16 @@ public class CacheTypeTest extends AndroidTestCase { public static void testGetByIdComplete() { for (CacheType type : CacheType.values()) { assertEquals(type, CacheType.getById(type.id)); - assertEquals(type, CacheType.getById(type.id.toLowerCase())); - assertEquals(type, CacheType.getById(type.id.toUpperCase())); + assertEquals(type, CacheType.getById(type.id.toLowerCase(Locale.US))); + assertEquals(type, CacheType.getById(type.id.toUpperCase(Locale.US))); } } public static void testGetByPatternComplete() { for (CacheType type : CacheType.values()) { assertEquals(type, CacheType.getByPattern(type.pattern)); - assertEquals(type, CacheType.getByPattern(type.pattern.toLowerCase())); - assertEquals(type, CacheType.getByPattern(type.pattern.toUpperCase())); + assertEquals(type, CacheType.getByPattern(type.pattern.toLowerCase(Locale.US))); + assertEquals(type, CacheType.getByPattern(type.pattern.toUpperCase(Locale.US))); } } } diff --git a/tests/src/cgeo/geocaching/enumerations/LogTypeTest.java b/tests/src/cgeo/geocaching/enumerations/LogTypeTest.java index 44f464e..81ca33b 100644 --- a/tests/src/cgeo/geocaching/enumerations/LogTypeTest.java +++ b/tests/src/cgeo/geocaching/enumerations/LogTypeTest.java @@ -19,7 +19,8 @@ public class LogTypeTest extends AndroidTestCase { public static void testGetByType() { assertEquals(LogType.UNKNOWN, LogType.getByIconName("")); assertEquals(LogType.UNKNOWN, LogType.getByIconName(null)); - assertEquals(LogType.GRABBED_IT, LogType.getByType("grabbed IT ")); + assertEquals(LogType.GRABBED_IT, LogType.getByType("grabbed it")); + assertEquals(LogType.GRABBED_IT, LogType.getByType(" gRAbbed IT ")); } } diff --git a/tests/src/cgeo/geocaching/export/ExportTest.java b/tests/src/cgeo/geocaching/export/ExportTest.java index 5d3d137..cdd64b2 100644 --- a/tests/src/cgeo/geocaching/export/ExportTest.java +++ b/tests/src/cgeo/geocaching/export/ExportTest.java @@ -13,7 +13,7 @@ public class ExportTest extends CGeoTestCase { final LogEntry log = new LogEntry(1353244820000L, LogType.FOUND_IT, "Hidden in a tree"); final StringBuilder logStr = new StringBuilder(); FieldnoteExport.appendFieldNote(logStr, cache, log); - assertEquals("GCX1234,2012-11-18T14:20:20Z,Found it,\"Hidden in a tree\"\n", logStr.toString()); + assertEquals("Non matching export " + logStr.toString(), "GCX1234,2012-11-18T13:20:20Z,Found it,\"Hidden in a tree\"\n", logStr.toString()); } } diff --git a/tests/src/cgeo/geocaching/files/GPXImporterTest.java b/tests/src/cgeo/geocaching/files/GPXImporterTest.java index da99c11..8c05ee0 100644 --- a/tests/src/cgeo/geocaching/files/GPXImporterTest.java +++ b/tests/src/cgeo/geocaching/files/GPXImporterTest.java @@ -3,7 +3,7 @@ package cgeo.geocaching.files; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; @@ -71,8 +71,7 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { assertEquals(GPXImporter.IMPORT_STEP_FINISHED, iMsg.next().what); SearchResult search = (SearchResult) importStepHandler.messages.get(3).obj; assertEquals(Collections.singletonList(geocode), new ArrayList<String>(search.getGeocodes())); - - cgCache cache = cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); assertCacheProperties(cache); assertTrue(cache.getWaypoints().isEmpty()); @@ -99,8 +98,7 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { assertImportStepMessages(GPXImporter.IMPORT_STEP_START, GPXImporter.IMPORT_STEP_READ_FILE, GPXImporter.IMPORT_STEP_READ_WPT_FILE, GPXImporter.IMPORT_STEP_STORE_STATIC_MAPS, GPXImporter.IMPORT_STEP_FINISHED); SearchResult search = (SearchResult) importStepHandler.messages.get(4).obj; assertEquals(Collections.singletonList("GC31J2H"), new ArrayList<String>(search.getGeocodes())); - - cgCache cache = cgeoapplication.getInstance().loadCache("GC31J2H", LoadFlags.LOAD_CACHE_OR_DB); + cgCache cache = cgData.loadCache("GC31J2H", LoadFlags.LOAD_CACHE_OR_DB); assertCacheProperties(cache); assertEquals(2, cache.getWaypoints().size()); } @@ -113,8 +111,7 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { runImportThread(importThread); assertImportStepMessages(GPXImporter.IMPORT_STEP_START, GPXImporter.IMPORT_STEP_READ_FILE, GPXImporter.IMPORT_STEP_STORE_STATIC_MAPS, GPXImporter.IMPORT_STEP_FINISHED); - - final cgCache cache = cgeoapplication.getInstance().loadCache("AID1", LoadFlags.LOAD_CACHE_OR_DB); + final cgCache cache = cgData.loadCache("AID1", LoadFlags.LOAD_CACHE_OR_DB); assertCacheProperties(cache); assertEquals("First Aid Station #1", cache.getName()); } @@ -136,8 +133,7 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { assertImportStepMessages(GPXImporter.IMPORT_STEP_START, GPXImporter.IMPORT_STEP_READ_FILE, GPXImporter.IMPORT_STEP_STORE_STATIC_MAPS, GPXImporter.IMPORT_STEP_FINISHED); SearchResult search = (SearchResult) importStepHandler.messages.get(3).obj; assertEquals(Collections.singletonList("OC5952"), new ArrayList<String>(search.getGeocodes())); - - cgCache cache = cgeoapplication.getInstance().loadCache("OC5952", LoadFlags.LOAD_CACHE_OR_DB); + cgCache cache = cgData.loadCache("OC5952", LoadFlags.LOAD_CACHE_OR_DB); assertCacheProperties(cache); } @@ -179,8 +175,7 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { assertImportStepMessages(GPXImporter.IMPORT_STEP_START, GPXImporter.IMPORT_STEP_READ_FILE, GPXImporter.IMPORT_STEP_STORE_STATIC_MAPS, GPXImporter.IMPORT_STEP_FINISHED); SearchResult search = (SearchResult) importStepHandler.messages.get(3).obj; assertEquals(Collections.singletonList(geocode), new ArrayList<String>(search.getGeocodes())); - - cgCache cache = cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); assertCacheProperties(cache); assertTrue(cache.getWaypoints().isEmpty()); @@ -198,8 +193,7 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { assertImportStepMessages(GPXImporter.IMPORT_STEP_START, GPXImporter.IMPORT_STEP_READ_FILE, GPXImporter.IMPORT_STEP_READ_WPT_FILE, GPXImporter.IMPORT_STEP_STORE_STATIC_MAPS, GPXImporter.IMPORT_STEP_FINISHED); SearchResult search = (SearchResult) importStepHandler.messages.get(4).obj; assertEquals(Collections.singletonList(geocode), new ArrayList<String>(search.getGeocodes())); - - cgCache cache = cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); assertCacheProperties(cache); assertEquals(1, cache.getWaypoints().size()); // this is the original pocket query result without test waypoint } @@ -225,8 +219,7 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { assertImportStepMessages(GPXImporter.IMPORT_STEP_START, GPXImporter.IMPORT_STEP_READ_FILE, GPXImporter.IMPORT_STEP_READ_WPT_FILE, GPXImporter.IMPORT_STEP_STORE_STATIC_MAPS, GPXImporter.IMPORT_STEP_FINISHED); SearchResult search = (SearchResult) importStepHandler.messages.get(4).obj; assertEquals(Collections.singletonList(geocode), new ArrayList<String>(search.getGeocodes())); - - cgCache cache = cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + cgCache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); assertCacheProperties(cache); assertEquals(1, cache.getWaypoints().size()); // this is the original pocket query result without test waypoint } @@ -266,10 +259,9 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { tempDir = new File(System.getProperty("java.io.tmpdir"), "cgeogpxesTest"); tempDir.mkdir(); - // workaround to get storage initialized - cgeoapplication.getInstance().getAllHistoricCachesCount(); - listId = cgeoapplication.getInstance().createList("cgeogpxesTest"); + cgData.getAllHistoryCachesCount(); + listId = cgData.createList("cgeogpxesTest"); importCacheStaticMaps = Settings.isStoreOfflineMaps(); Settings.setStoreOfflineMaps(true); @@ -279,11 +271,11 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { @Override protected void tearDown() throws Exception { - SearchResult search = cgeoapplication.getInstance().getBatchOfStoredCaches(false, null, CacheType.ALL, listId); + SearchResult search = cgData.getBatchOfStoredCaches(null, CacheType.ALL, listId); List<cgCache> cachesInList = new ArrayList<cgCache>(); cachesInList.addAll(search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB)); - cgeoapplication.getInstance().markDropped(cachesInList); - cgeoapplication.getInstance().removeList(listId); + cgData.markDropped(cachesInList); + cgData.removeList(listId); deleteDirectory(tempDir); Settings.setStoreOfflineMaps(importCacheStaticMaps); Settings.setStoreOfflineWpMaps(importWpStaticMaps); diff --git a/tests/src/cgeo/geocaching/files/GPXParserTest.java b/tests/src/cgeo/geocaching/files/GPXParserTest.java index 6c3c237..bbb4514 100644 --- a/tests/src/cgeo/geocaching/files/GPXParserTest.java +++ b/tests/src/cgeo/geocaching/files/GPXParserTest.java @@ -4,8 +4,8 @@ import cgeo.geocaching.LogEntry; import cgeo.geocaching.SearchResult; import cgeo.geocaching.StoredList; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgWaypoint; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; @@ -24,10 +24,11 @@ import java.util.Collection; import java.util.EnumSet; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Set; public class GPXParserTest extends AbstractResourceInstrumentationTestCase { - private static final SimpleDateFormat LOG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // 2010-04-20T07:00:00Z + private static final SimpleDateFormat LOG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); // 2010-04-20T07:00:00Z private int listId; public void testGPXVersion100() throws Exception { @@ -166,7 +167,7 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { private static void assertGc31j2hWaypoints(final cgCache cache) { assertNotNull(cache.getWaypoints()); assertEquals(2, cache.getWaypoints().size()); - cgWaypoint wp = cache.getWaypoints().get(1); + Waypoint wp = cache.getWaypoints().get(1); assertEquals("GC31J2H", wp.getGeocode()); assertEquals("00", wp.getPrefix()); assertEquals("---", wp.getLookup()); @@ -212,29 +213,19 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { } } // reload caches, because the parser only returns the minimum version of each cache - return new ArrayList<cgCache>(cgeoapplication.getInstance().loadCaches(result, LoadFlags.LOAD_ALL_DB_ONLY)); + return new ArrayList<cgCache>(cgData.loadCaches(result, LoadFlags.LOAD_ALL_DB_ONLY)); } - public static void testParseDateWithFractionalSeconds() { + public static void testParseDateWithFractionalSeconds() throws ParseException { // was experienced in GSAK file final String dateString = "2011-08-13T02:52:18.103Z"; - try { - GPXParser.parseDate(dateString); - } catch (ParseException e) { - fail(); - e.printStackTrace(); - } + GPXParser.parseDate(dateString); } - public static void testParseDateWithHugeFraction() { + public static void testParseDateWithHugeFraction() throws ParseException { // see issue 821 String dateString = "2011-11-07T00:00:00.0000000-07:00"; - try { - GPXParser.parseDate(dateString); - } catch (ParseException e) { - fail(); - e.printStackTrace(); - } + GPXParser.parseDate(dateString); } public void testSelfmadeGPXWithoutGeocodes() throws Exception { @@ -265,10 +256,9 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { removeCacheCompletely(geocode); final List<cgCache> caches = readGPX10(R.raw.lazy); assertEquals(1, caches.size()); - cgeoapplication.getInstance().removeAllFromCache(); - + cgData.removeAllFromCache(); // load only the minimum cache, it has several members missing - final cgCache minimalCache = cgeoapplication.getInstance().loadCache(geocode, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL)); + final cgCache minimalCache = cgData.loadCache(geocode, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL)); // now check that we load lazy members on demand assertFalse(minimalCache.getAttributes().isEmpty()); @@ -297,17 +287,17 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { @Override protected void setUp() throws Exception { super.setUp(); - listId = cgeoapplication.getInstance().createList("Temporary unit testing"); + listId = cgData.createList("Temporary unit testing"); assertTrue(listId != StoredList.TEMPORARY_LIST_ID); assertTrue(listId != StoredList.STANDARD_LIST_ID); } @Override protected void tearDown() throws Exception { - SearchResult search = cgeoapplication.getInstance().getBatchOfStoredCaches(false, null, CacheType.ALL, listId); + SearchResult search = cgData.getBatchOfStoredCaches(null, CacheType.ALL, listId); assertNotNull(search); - cgeoapplication.getInstance().removeCaches(search.getGeocodes(), LoadFlags.REMOVE_ALL); - cgeoapplication.getInstance().removeList(listId); + cgData.removeCaches(search.getGeocodes(), LoadFlags.REMOVE_ALL); + cgData.removeList(listId); super.tearDown(); } } diff --git a/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java b/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java new file mode 100644 index 0000000..2578efa --- /dev/null +++ b/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java @@ -0,0 +1,84 @@ +package cgeo.geocaching.files; + +import com.jayway.android.robotium.solo.Solo; + +import android.annotation.TargetApi; +import android.os.Build; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.Suppress; +import android.widget.CheckBox; + +import java.util.ArrayList; + +@TargetApi(Build.VERSION_CODES.FROYO) +@Suppress() /* This test breaks the continuous integration server, do not run it for now. */ +public class SimpleDirChooserUITest extends ActivityInstrumentationTestCase2<SimpleDirChooser> { + + private Solo solo; + + public SimpleDirChooserUITest() { + super(SimpleDirChooser.class); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + solo = new Solo(getInstrumentation(), getActivity()); + } + + public void testSingleSelection() throws InterruptedException { + // normally our activity should be ready, but we already had Jenkins report no checkboxes right here at the beginning + solo.waitForActivity(solo.getCurrentActivity().getClass().getSimpleName(), 2000); + + assertChecked("Newly opened activity", 0); + solo.scrollToBottom(); + pause(); + // according to the documentation, automatic pauses only happen in the clickXYZ() methods. + // Therefore lets introduce a manual pause after the scrolling methods. + + final int lastIndex = solo.getCurrentCheckBoxes().size() - 1; + + solo.clickOnCheckBox(lastIndex); + assertTrue(solo.getCurrentCheckBoxes().get(lastIndex).isChecked()); + assertFalse(solo.getCurrentCheckBoxes().get(0).isChecked()); + assertChecked("Clicked last checkbox", 1); + + solo.scrollUp(); + pause(); + solo.scrollToBottom(); + pause(); + assertChecked("Refreshing last checkbox", 1); + + solo.scrollToTop(); + pause(); + solo.clickOnCheckBox(0); + assertChecked("Clicked first checkbox", 1); + assertTrue(solo.getCurrentCheckBoxes().get(0).isChecked()); + solo.clickOnCheckBox(1); + assertChecked("Clicked second checkbox", 1); + assertTrue(solo.getCurrentCheckBoxes().get(1).isChecked()); + } + + private static void pause() throws InterruptedException { + Thread.sleep(500); + } + + private void assertChecked(String message, int expectedChecked) { + int checked = 0; + final ArrayList<CheckBox> boxes = solo.getCurrentCheckBoxes(); + assertNotNull("Could not get checkboxes", boxes); + assertTrue("There are no checkboxes", boxes.size() > 1); + for (CheckBox checkBox : boxes) { + if (checkBox.isChecked()) { + checked++; + } + } + assertEquals(message, expectedChecked, checked); + } + + @Override + public void tearDown() throws Exception { + solo.finishOpenedActivities(); + super.tearDown(); + } +} diff --git a/tests/src/cgeo/geocaching/sorting/NameComparatorTest.java b/tests/src/cgeo/geocaching/sorting/NameComparatorTest.java index fa3b16c..98c77fd 100644 --- a/tests/src/cgeo/geocaching/sorting/NameComparatorTest.java +++ b/tests/src/cgeo/geocaching/sorting/NameComparatorTest.java @@ -13,13 +13,7 @@ public class NameComparatorTest extends AndroidTestCase { } } - private NameComparator comp; - - @Override - protected void setUp() throws Exception { - super.setUp(); - comp = new NameComparator(); - } + private NameComparator comp = new NameComparator(); public void testLexical() { assertSorted(new NamedCache("A"), new NamedCache("Z")); diff --git a/tests/src/cgeo/geocaching/test/AbstractResourceInstrumentationTestCase.java b/tests/src/cgeo/geocaching/test/AbstractResourceInstrumentationTestCase.java index 0d3d53b..cd8b5e7 100644 --- a/tests/src/cgeo/geocaching/test/AbstractResourceInstrumentationTestCase.java +++ b/tests/src/cgeo/geocaching/test/AbstractResourceInstrumentationTestCase.java @@ -1,6 +1,6 @@ package cgeo.geocaching.test; -import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.cgData; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; @@ -18,7 +18,7 @@ public abstract class AbstractResourceInstrumentationTestCase extends Instrument protected static void removeCacheCompletely(final String geocode) { final EnumSet<RemoveFlag> flags = EnumSet.copyOf(LoadFlags.REMOVE_ALL); flags.add(RemoveFlag.REMOVE_OWN_WAYPOINTS_ONLY_FOR_TESTING); - cgeoapplication.getInstance().removeCache(geocode, flags); + cgData.removeCache(geocode, flags); } protected InputStream getResourceStream(int resourceId) { diff --git a/tests/src/cgeo/geocaching/test/RegExPerformanceTest.java b/tests/src/cgeo/geocaching/test/RegExPerformanceTest.java index b9f8138..bd30532 100644 --- a/tests/src/cgeo/geocaching/test/RegExPerformanceTest.java +++ b/tests/src/cgeo/geocaching/test/RegExPerformanceTest.java @@ -8,6 +8,7 @@ import cgeo.geocaching.test.mock.MockedCache; import cgeo.geocaching.utils.BaseUtils; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; @@ -69,7 +70,10 @@ public class RegExPerformanceTest extends TestCase { public final static Pattern PATTERN_DESCRIPTION = Pattern.compile("<span id=\"ctl00_ContentBody_LongDescription\">(.*?)</span>[^<]*</div>[^<]*<p>[^<]*</p>[^<]*<p>[^<]*<strong>\\W*Additional Hints</strong>"); - public final static MockedCache[] MOCKED_CACHES = { new GC2CJPF(), new GC1ZXX2(), new GC2JVEH(), new GC3XX5J() }; + public final static List<MockedCache> MOCKED_CACHES; + static { + MOCKED_CACHES = Arrays.asList(new GC2CJPF(), new GC1ZXX2(), new GC2JVEH(), new GC3XX5J()); + } public static void testRegEx() { List<String> output = doTheTests(10); @@ -124,7 +128,7 @@ public class RegExPerformanceTest extends TestCase { for (int j = 0; j < iterations; j++) { BaseUtils.getMatch(page, pattern, true, ""); } - return (System.currentTimeMillis() - start); + return System.currentTimeMillis() - start; } diff --git a/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java b/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java index 9aa18f9..5e8a1d7 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java +++ b/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java @@ -1,7 +1,7 @@ package cgeo.geocaching.test.mock; -import cgeo.geocaching.cgImage; -import cgeo.geocaching.cgTrackable; +import cgeo.geocaching.Image; +import cgeo.geocaching.Trackable; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; @@ -133,16 +133,16 @@ public class GC2JVEH extends MockedCache { } @Override - public List<cgTrackable> getInventory() { - final ArrayList<cgTrackable> inventory = new ArrayList<cgTrackable>(); - inventory.add(new cgTrackable()); + public List<Trackable> getInventory() { + final ArrayList<Trackable> inventory = new ArrayList<Trackable>(); + inventory.add(new Trackable()); return inventory; } @Override - public List<cgImage> getSpoilers() { - final ArrayList<cgImage> spoilers = new ArrayList<cgImage>(); - final cgImage mockedImage = new cgImage(null, null, null); + public List<Image> getSpoilers() { + final ArrayList<Image> spoilers = new ArrayList<Image>(); + final Image mockedImage = new Image(null, null, null); spoilers.add(mockedImage); spoilers.add(mockedImage); spoilers.add(mockedImage); diff --git a/tests/src/cgeo/geocaching/test/mock/MockedCache.java b/tests/src/cgeo/geocaching/test/mock/MockedCache.java index 352c34d..f667264 100644 --- a/tests/src/cgeo/geocaching/test/mock/MockedCache.java +++ b/tests/src/cgeo/geocaching/test/mock/MockedCache.java @@ -1,8 +1,8 @@ package cgeo.geocaching.test.mock; import cgeo.geocaching.ICache; -import cgeo.geocaching.cgImage; -import cgeo.geocaching.cgTrackable; +import cgeo.geocaching.Image; +import cgeo.geocaching.Trackable; import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.BaseUtils; @@ -70,7 +70,7 @@ public abstract class MockedCache implements ICache { return BaseUtils.replaceWhitespace(buffer.toString()); } catch (IOException e) { - e.printStackTrace(); + Assert.fail(e.getMessage()); } finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(br); @@ -134,12 +134,12 @@ public abstract class MockedCache implements ICache { } @Override - public List<cgTrackable> getInventory() { + public List<Trackable> getInventory() { return null; } @Override - public List<cgImage> getSpoilers() { + public List<Image> getSpoilers() { return null; } diff --git a/tests/src/cgeo/geocaching/ui/FormatterTest.java b/tests/src/cgeo/geocaching/ui/FormatterTest.java new file mode 100644 index 0000000..5546ea5 --- /dev/null +++ b/tests/src/cgeo/geocaching/ui/FormatterTest.java @@ -0,0 +1,30 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.R; +import cgeo.geocaching.Waypoint; +import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.enumerations.WaypointType; + +import android.test.AndroidTestCase; + +public class FormatterTest extends AndroidTestCase { + + public static void testParkingWaypoint() { + assertFormatting(new Waypoint("you can park here", WaypointType.PARKING, false), WaypointType.PARKING.getL10n()); + } + + public static void testOriginalWaypoint() { + assertFormatting(new Waypoint("an original", WaypointType.ORIGINAL, false), WaypointType.ORIGINAL.getL10n()); + } + + public static void testOwnWaypoint() { + Waypoint own = new Waypoint("my own", WaypointType.OWN, true); + own.setPrefix(Waypoint.PREFIX_OWN); + assertFormatting(own, cgeoapplication.getInstance().getString(R.string.waypoint_custom)); + } + + private static void assertFormatting(Waypoint waypoint, String expected) { + assertEquals(expected, Formatter.formatWaypointInfo(waypoint)); + } + +} |
