aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/.classpath18
-rw-r--r--main/.factorypath3
-rw-r--r--main/.settings/org.eclipse.jdt.apt.core.prefs4
-rw-r--r--main/.settings/org.eclipse.jdt.core.prefs735
-rw-r--r--main/AndroidManifest.xml90
-rw-r--r--main/ant.properties2
-rw-r--r--main/build.xml8
-rw-r--r--main/libs/butterknife-1.3.2.jarbin0 -> 12597 bytes
-rw-r--r--main/lint.xml1
-rw-r--r--main/proguard.cfg4
-rw-r--r--main/project/attributes/iconlist.txt5
-rwxr-xr-xmain/project/attributes/makeicons1res.sh2
-rw-r--r--main/project/attributes/readme.txt3
-rw-r--r--main/project/attributes/svgs/easy_climbing.svg84
-rw-r--r--main/project/attributes/svgs/geotour.svg72
-rw-r--r--main/project/attributes_okapi/AttrGen/.classpath6
-rw-r--r--main/project/attributes_okapi/AttrGen/.project17
-rw-r--r--main/project/attributes_okapi/AttrGen/.settings/org.eclipse.jdt.core.prefs11
-rw-r--r--main/project/attributes_okapi/AttrGen/.settings/org.eclipse.jdt.ui.prefs54
-rw-r--r--main/project/attributes_okapi/AttrGen/build.xml14
-rw-r--r--main/project/attributes_okapi/AttrGen/src/GenerateAttributes.java172
-rw-r--r--main/project/attributes_okapi/AttributeParser.java327
-rw-r--r--main/project/attributes_okapi/attributes.xml1940
-rw-r--r--main/project/attributes_okapi/genattr.jarbin0 -> 4006 bytes
-rw-r--r--main/project/attributes_okapi/genattr.sh2
-rw-r--r--main/project/attributes_okapi/readme.txt10
-rw-r--r--main/project/rawimages/c-geo_icon.svg543
-rw-r--r--main/project/rawimages/c_geo_icon_basic_512.pngbin54668 -> 0 bytes
-rw-r--r--main/project/rawimages/c_geo_icon_basic_freigestellt_512.pngbin56921 -> 0 bytes
-rw-r--r--main/res/drawable-hdpi/actionbar_manual.pngbin652 -> 0 bytes
-rw-r--r--main/res/drawable-hdpi/ic_menu_start_conversation.pngbin0 -> 1650 bytes
-rw-r--r--main/res/drawable-ldpi/actionbar_manual.pngbin501 -> 0 bytes
-rw-r--r--main/res/drawable-ldpi/ic_menu_start_conversation.pngbin0 -> 1293 bytes
-rw-r--r--main/res/drawable-mdpi/actionbar_manual.pngbin769 -> 0 bytes
-rw-r--r--main/res/drawable-mdpi/attribute_easy_climbing.pngbin0 -> 1236 bytes
-rw-r--r--main/res/drawable-mdpi/attribute_geotour.pngbin0 -> 961 bytes
-rw-r--r--main/res/drawable-mdpi/helper_manual.pngbin50536 -> 0 bytes
-rw-r--r--main/res/drawable-mdpi/helper_pocketquery.pngbin0 -> 22238 bytes
-rw-r--r--main/res/drawable-mdpi/ic_menu_start_conversation.pngbin0 -> 1104 bytes
-rw-r--r--main/res/drawable/favorite_background_dark.xml (renamed from main/res/drawable/favourite_background_dark.xml)0
-rw-r--r--main/res/drawable/favorite_background_green_dark.xml (renamed from main/res/drawable/favourite_background_green_dark.xml)0
-rw-r--r--main/res/drawable/favorite_background_green_light.xml (renamed from main/res/drawable/favourite_background_green_light.xml)0
-rw-r--r--main/res/drawable/favorite_background_light.xml (renamed from main/res/drawable/favourite_background_light.xml)0
-rw-r--r--main/res/drawable/favorite_background_orange_dark.xml (renamed from main/res/drawable/favourite_background_orange_dark.xml)0
-rw-r--r--main/res/drawable/favorite_background_orange_light.xml (renamed from main/res/drawable/favourite_background_orange_light.xml)0
-rw-r--r--main/res/drawable/favorite_background_red_dark.xml (renamed from main/res/drawable/favourite_background_red_dark.xml)0
-rw-r--r--main/res/drawable/favorite_background_red_light.xml (renamed from main/res/drawable/favourite_background_red_light.xml)0
-rw-r--r--main/res/layout-land/coords.xml7
-rw-r--r--main/res/layout-land/navigate.xml26
-rw-r--r--main/res/layout/about_activity.xml48
-rw-r--r--main/res/layout/actionbar.xml6
-rw-r--r--main/res/layout/actionbar_button_compass.xml15
-rw-r--r--main/res/layout/actionbar_button_map.xml13
-rw-r--r--main/res/layout/actionbar_button_myposition.xml12
-rw-r--r--main/res/layout/actionbar_button_search.xml13
-rw-r--r--main/res/layout/actionbar_progress.xml4
-rw-r--r--main/res/layout/actionbar_title.xml16
-rw-r--r--main/res/layout/actionbar_title_no_home.xml10
-rw-r--r--main/res/layout/addresses.xml11
-rw-r--r--main/res/layout/addresses_item.xml4
-rw-r--r--main/res/layout/attribute_descriptions.xml2
-rw-r--r--main/res/layout/authorization_activity.xml (renamed from main/res/layout/twitter_authorization_activity.xml)20
-rw-r--r--main/res/layout/cache_image_item.xml8
-rw-r--r--main/res/layout/cache_information_item.xml6
-rw-r--r--main/res/layout/caches.xml29
-rw-r--r--main/res/layout/caches_footer.xml2
-rw-r--r--main/res/layout/caches_item.xml12
-rw-r--r--main/res/layout/cacheview.xml26
-rw-r--r--main/res/layout/cacheview_description.xml10
-rw-r--r--main/res/layout/cacheview_details.xml10
-rw-r--r--main/res/layout/cacheview_logs_item.xml16
-rw-r--r--main/res/layout/coords.xml7
-rw-r--r--main/res/layout/edit_waypoint_activity.xml18
-rw-r--r--main/res/layout/editor.xml25
-rw-r--r--main/res/layout/fragment_edit_note.xml15
-rw-r--r--main/res/layout/gpx.xml11
-rw-r--r--main/res/layout/gpx_item.xml4
-rw-r--r--main/res/layout/init.xml95
-rw-r--r--main/res/layout/livemapinfo.xml2
-rw-r--r--main/res/layout/main.xml61
-rw-r--r--main/res/layout/map_google.xml27
-rw-r--r--main/res/layout/map_mapsforge.xml27
-rw-r--r--main/res/layout/map_mapsforge_old.xml27
-rw-r--r--main/res/layout/map_static.xml11
-rw-r--r--main/res/layout/mapfile_item.xml4
-rw-r--r--main/res/layout/navigate.xml205
-rw-r--r--main/res/layout/point.xml18
-rw-r--r--main/res/layout/popup.xml22
-rw-r--r--main/res/layout/recaptcha_dialog.xml2
-rw-r--r--main/res/layout/search.xml18
-rw-r--r--main/res/layout/spoilers.xml11
-rw-r--r--main/res/layout/status.xml2
-rw-r--r--main/res/layout/touch.xml23
-rw-r--r--main/res/layout/trackable_activity.xml20
-rw-r--r--main/res/layout/trackable_details_view.xml4
-rw-r--r--main/res/layout/trackable_logs_img.xml16
-rw-r--r--main/res/layout/trackable_logs_item.xml24
-rw-r--r--main/res/layout/useful_apps.xml33
-rw-r--r--main/res/layout/useful_apps_activity.xml23
-rw-r--r--main/res/layout/useful_apps_item.xml3
-rw-r--r--main/res/layout/visit.xml25
-rw-r--r--main/res/layout/visit_image.xml26
-rw-r--r--main/res/layout/visit_trackable.xml6
-rw-r--r--main/res/layout/waypoint_item.xml8
-rw-r--r--main/res/layout/waypoint_popup.xml20
-rw-r--r--main/res/menu/abstract_logging_activity.xml22
-rw-r--r--main/res/menu/abstract_popup_activity.xml35
-rw-r--r--main/res/menu/compass_activity_options.xml36
-rw-r--r--main/res/menu/images_list_context.xml11
-rw-r--r--main/res/menu/logging_ui.xml13
-rw-r--r--main/res/menu/main_activity_options.xml (renamed from main/res/menu/main_options.xml)0
-rw-r--r--main/res/menu/map_activity.xml85
-rw-r--r--main/res/menu/navigate_any_point_activity_options.xml24
-rw-r--r--main/res/menu/search_activity_options.xml10
-rw-r--r--main/res/menu/settings_activity_options.xml8
-rw-r--r--main/res/menu/static_maps_activity_options.xml8
-rw-r--r--main/res/menu/trackable_activity.xml15
-rw-r--r--main/res/values-cs/strings.xml43
-rw-r--r--main/res/values-da/strings.xml4
-rw-r--r--main/res/values-de/strings.xml102
-rw-r--r--main/res/values-es/strings.xml112
-rw-r--r--main/res/values-fr/strings.xml62
-rw-r--r--main/res/values-hu/strings.xml29
-rw-r--r--main/res/values-it/strings.xml160
-rw-r--r--main/res/values-ja/strings.xml36
-rw-r--r--main/res/values-nb/strings.xml5
-rw-r--r--main/res/values-nl/strings.xml32
-rw-r--r--main/res/values-pl/strings.xml38
-rw-r--r--main/res/values-pt/strings.xml22
-rw-r--r--main/res/values-sk/strings.xml22
-rw-r--r--main/res/values-sv/strings.xml64
-rw-r--r--main/res/values/.gitignore1
-rw-r--r--main/res/values/attrs.xml8
-rw-r--r--main/res/values/cache_attributes.xml4
-rw-r--r--main/res/values/dimens.xml4
-rw-r--r--main/res/values/ids.xml5
-rw-r--r--main/res/values/strings.xml93
-rw-r--r--main/res/values/strings_not_translatable.xml13
-rw-r--r--main/res/values/styles.xml20
-rw-r--r--main/res/values/themes.xml32
-rw-r--r--main/src/cgeo/geocaching/AboutActivity.java31
-rw-r--r--main/src/cgeo/geocaching/AbstractLoggingActivity.java22
-rw-r--r--main/src/cgeo/geocaching/AbstractPopupActivity.java54
-rw-r--r--main/src/cgeo/geocaching/AddressListActivity.java6
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java330
-rw-r--r--main/src/cgeo/geocaching/CachePopup.java8
-rw-r--r--main/src/cgeo/geocaching/CompassActivity.java (renamed from main/src/cgeo/geocaching/cgeonavigate.java)197
-rw-r--r--main/src/cgeo/geocaching/DirectionProvider.java7
-rw-r--r--main/src/cgeo/geocaching/EditWaypointActivity.java100
-rw-r--r--main/src/cgeo/geocaching/Geocache.java89
-rw-r--r--main/src/cgeo/geocaching/GpxFileListActivity.java7
-rw-r--r--main/src/cgeo/geocaching/ImageSelectActivity.java97
-rw-r--r--main/src/cgeo/geocaching/ImagesActivity.java18
-rw-r--r--main/src/cgeo/geocaching/Intents.java4
-rw-r--r--main/src/cgeo/geocaching/LogTrackableActivity.java53
-rw-r--r--main/src/cgeo/geocaching/MainActivity.java (renamed from main/src/cgeo/geocaching/cgeo.java)147
-rw-r--r--main/src/cgeo/geocaching/NavigateAnyPointActivity.java171
-rw-r--r--main/src/cgeo/geocaching/SearchActivity.java92
-rw-r--r--main/src/cgeo/geocaching/SearchResult.java6
-rw-r--r--main/src/cgeo/geocaching/SelectMapfileActivity.java5
-rw-r--r--main/src/cgeo/geocaching/Settings.java117
-rw-r--r--main/src/cgeo/geocaching/SettingsActivity.java47
-rw-r--r--main/src/cgeo/geocaching/StaticMapsActivity.java11
-rw-r--r--main/src/cgeo/geocaching/StaticMapsProvider.java27
-rw-r--r--main/src/cgeo/geocaching/StoredList.java37
-rw-r--r--main/src/cgeo/geocaching/TrackableActivity.java119
-rw-r--r--main/src/cgeo/geocaching/UsefulAppsActivity.java124
-rw-r--r--main/src/cgeo/geocaching/VisitCacheActivity.java251
-rw-r--r--main/src/cgeo/geocaching/Waypoint.java3
-rw-r--r--main/src/cgeo/geocaching/WaypointPopup.java35
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractActivity.java66
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractListActivity.java34
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java13
-rw-r--r--main/src/cgeo/geocaching/activity/ActivityMixin.java24
-rw-r--r--main/src/cgeo/geocaching/activity/IAbstractActivity.java2
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java8
-rw-r--r--main/src/cgeo/geocaching/cgData.java52
-rw-r--r--main/src/cgeo/geocaching/cgeoapplication.java4
-rw-r--r--main/src/cgeo/geocaching/cgeocaches.java124
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java4
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java27
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java5
-rw-r--r--main/src/cgeo/geocaching/connector/IConnector.java41
-rw-r--r--main/src/cgeo/geocaching/connector/ILoggingManager.java32
-rw-r--r--main/src/cgeo/geocaching/connector/ImageResult.java23
-rw-r--r--main/src/cgeo/geocaching/connector/LogResult.java23
-rw-r--r--main/src/cgeo/geocaching/connector/NoLoggingManager.java46
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java32
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java132
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java4
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java52
-rw-r--r--main/src/cgeo/geocaching/connector/oc/AttributeParser.java327
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java754
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiConnector.java6
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java82
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java109
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java67
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCXMLClient.java115
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java371
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java69
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheAttribute.java30
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheType.java14
-rw-r--r--main/src/cgeo/geocaching/enumerations/LogType.java62
-rw-r--r--main/src/cgeo/geocaching/enumerations/WaypointType.java4
-rw-r--r--main/src/cgeo/geocaching/export/AbstractExport.java7
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java58
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java195
-rw-r--r--main/src/cgeo/geocaching/files/AbstractFileListActivity.java6
-rw-r--r--main/src/cgeo/geocaching/files/FileParser.java12
-rw-r--r--main/src/cgeo/geocaching/files/GPXImporter.java921
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java1
-rw-r--r--main/src/cgeo/geocaching/files/LocalStorage.java19
-rw-r--r--main/src/cgeo/geocaching/files/SimpleDirChooser.java20
-rw-r--r--main/src/cgeo/geocaching/filter/AttributeFilter.java23
-rw-r--r--main/src/cgeo/geocaching/filter/DifficultyFilter.java5
-rw-r--r--main/src/cgeo/geocaching/filter/FilterUserInterface.java9
-rw-r--r--main/src/cgeo/geocaching/filter/IFilterFactory.java4
-rw-r--r--main/src/cgeo/geocaching/filter/ModifiedFilter.java7
-rw-r--r--main/src/cgeo/geocaching/filter/OriginFilter.java5
-rw-r--r--main/src/cgeo/geocaching/filter/SizeFilter.java9
-rw-r--r--main/src/cgeo/geocaching/filter/StateFilter.java31
-rw-r--r--main/src/cgeo/geocaching/filter/TerrainFilter.java8
-rw-r--r--main/src/cgeo/geocaching/filter/TrackablesFilter.java9
-rw-r--r--main/src/cgeo/geocaching/filter/TypeFilter.java9
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVote.java7
-rw-r--r--main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java6
-rw-r--r--main/src/cgeo/geocaching/maps/AbstractMap.java2
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java115
-rw-r--r--main/src/cgeo/geocaching/maps/CachesOverlay.java23
-rw-r--r--main/src/cgeo/geocaching/maps/MapProviderFactory.java9
-rw-r--r--main/src/cgeo/geocaching/maps/PositionOverlay.java11
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java4
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleCacheOverlayItem.java11
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java11
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapItemFactory.java5
-rw-r--r--main/src/cgeo/geocaching/maps/interfaces/CachesOverlayItemImpl.java4
-rw-r--r--main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java2
-rw-r--r--main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java3
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java4
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java15
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java11
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapItemFactory.java5
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java4
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlayItem.java15
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java6
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapItemFactory024.java5
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java24
-rw-r--r--main/src/cgeo/geocaching/network/Network.java18
-rw-r--r--main/src/cgeo/geocaching/network/OAuth.java16
-rw-r--r--main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java326
-rw-r--r--main/src/cgeo/geocaching/network/StatusUpdater.java13
-rw-r--r--main/src/cgeo/geocaching/speech/SpeechService.java188
-rw-r--r--main/src/cgeo/geocaching/speech/TextFactory.java71
-rw-r--r--main/src/cgeo/geocaching/twitter/Twitter.java70
-rw-r--r--main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java305
-rw-r--r--main/src/cgeo/geocaching/ui/CacheDetailsCreator.java21
-rw-r--r--main/src/cgeo/geocaching/ui/CacheListAdapter.java61
-rw-r--r--main/src/cgeo/geocaching/ui/CompassView.java33
-rw-r--r--main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java38
-rw-r--r--main/src/cgeo/geocaching/ui/DecryptTextClickListener.java6
-rw-r--r--main/src/cgeo/geocaching/ui/EditNoteDialog.java70
-rw-r--r--main/src/cgeo/geocaching/ui/ImagesList.java52
-rw-r--r--main/src/cgeo/geocaching/ui/LoggingUI.java40
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java8
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/EditorDialog.java60
-rw-r--r--main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java139
-rw-r--r--main/src/cgeo/geocaching/utils/BaseUtils.java7
-rw-r--r--main/src/cgeo/geocaching/utils/ClipboardUtils.java4
-rw-r--r--main/src/cgeo/geocaching/utils/GeoDirHandler.java22
-rw-r--r--main/src/cgeo/geocaching/utils/ImageHelper.java38
-rw-r--r--main/src/cgeo/geocaching/utils/Log.java7
-rw-r--r--main/src/cgeo/geocaching/utils/PeriodicHandler.java33
-rw-r--r--main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java375
-rw-r--r--main/templates/ocde_okapi.xml5
-rw-r--r--main/templates/private.properties9
-rw-r--r--main/thirdparty/android/support/v4/app/FragmentListActivity.java (renamed from main/src/android/support/v4/app/FragmentListActivity.java)0
-rw-r--r--main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java (renamed from main/src/cgeo/org/kxml2/io/KXmlSerializer.java)0
-rw-r--r--main/thirdparty/com/google/zxing/integration/android/IntentIntegrator.java419
-rw-r--r--main/thirdparty/com/google/zxing/integration/android/IntentResult.java95
-rw-r--r--main/thirdparty/com/viewpagerindicator/PageIndicator.java (renamed from main/src/com/viewpagerindicator/PageIndicator.java)0
-rw-r--r--main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java (renamed from main/src/com/viewpagerindicator/TitlePageIndicator.java)0
-rw-r--r--main/thirdparty/com/viewpagerindicator/TitleProvider.java (renamed from main/src/com/viewpagerindicator/TitleProvider.java)0
-rw-r--r--main/thirdparty/org/openintents/intents/FileManagerIntents.java (renamed from main/src/org/openintents/intents/FileManagerIntents.java)0
285 files changed, 10258 insertions, 5404 deletions
diff --git a/main/.classpath b/main/.classpath
index 79a19e9..72adb52 100644
--- a/main/.classpath
+++ b/main/.classpath
@@ -6,14 +6,18 @@
<attribute name="ignore_optional_problems" value="true"/>
</attributes>
</classpathentry>
- <classpathentry exported="true" kind="lib" path="libs/commons-lang3-3.1.jar"/>
- <classpathentry kind="lib" path="libs/locus-api-4.0.jar"/>
- <classpathentry kind="lib" path="libs/commons-collections-3.2.1.jar"/>
- <classpathentry kind="lib" path="libs/android-support-v4.jar"/>
- <classpathentry kind="lib" path="libs/mapsforge-map-0.3.0-jar-with-dependencies.jar"/>
- <classpathentry kind="lib" path="libs/mapsforge-map-0.2.4.jar"/>
+ <classpathentry kind="src" path="thirdparty">
+ <attributes>
+ <attribute name="ignore_optional_problems" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="annotation_gen">
+ <attributes>
+ <attribute name="ignore_optional_problems" value="true"/>
+ </attributes>
+ </classpathentry>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
- <classpathentry kind="lib" path="libs/httpclientandroidlib-1.1.1.jar"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
diff --git a/main/.factorypath b/main/.factorypath
new file mode 100644
index 0000000..d54f9b4
--- /dev/null
+++ b/main/.factorypath
@@ -0,0 +1,3 @@
+<factorypath>
+ <factorypathentry kind="WKSPJAR" id="/cgeo/libs/butterknife-1.3.2.jar" enabled="true" runInBatchMode="false"/>
+</factorypath>
diff --git a/main/.settings/org.eclipse.jdt.apt.core.prefs b/main/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 0000000..813e822
--- /dev/null
+++ b/main/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=annotation_gen
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/main/.settings/org.eclipse.jdt.core.prefs b/main/.settings/org.eclipse.jdt.core.prefs
index 3c08e45..41c73f0 100644
--- a/main/.settings/org.eclipse.jdt.core.prefs
+++ b/main/.settings/org.eclipse.jdt.core.prefs
@@ -1,367 +1,368 @@
-eclipse.preferences.version=1
-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
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.doc.comment.support=enabled
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-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.fallthroughCase=warning
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
-org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
-org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=no_tag
-org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
-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.nullReference=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.rawTypeReference=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
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=warning
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-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.unhandledWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.6
-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0
-org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=0
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=0
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0
-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=0
-org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0
-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_after_package=1
-org.eclipse.jdt.core.formatter.blank_lines_before_field=0
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.jdt.core.formatter.blank_lines_before_method=1
-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.jdt.core.formatter.blank_lines_before_package=0
-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.jdt.core.formatter.comment.format_block_comments=true
-org.eclipse.jdt.core.formatter.comment.format_header=true
-org.eclipse.jdt.core.formatter.comment.format_html=true
-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
-org.eclipse.jdt.core.formatter.comment.format_line_comments=false
-org.eclipse.jdt.core.formatter.comment.format_source_code=true
-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
-org.eclipse.jdt.core.formatter.comment.line_length=120
-org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
-org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
-org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
-org.eclipse.jdt.core.formatter.compact_else_if=true
-org.eclipse.jdt.core.formatter.continuation_indentation=2
-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
-org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_empty_lines=false
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
-org.eclipse.jdt.core.formatter.indentation.size=4
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.join_lines_in_comments=false
-org.eclipse.jdt.core.formatter.join_wrapped_lines=false
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.lineSplit=120
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=space
-org.eclipse.jdt.core.formatter.tabulation.size=4
-org.eclipse.jdt.core.formatter.use_on_off_tags=false
-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
-org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+eclipse.preferences.version=1
+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
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+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.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=no_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
+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.nullReference=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.rawTypeReference=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
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+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.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=0
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=0
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=false
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=false
+org.eclipse.jdt.core.formatter.join_wrapped_lines=false
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml
index 5cf5f74..27b5081 100644
--- a/main/AndroidManifest.xml
+++ b/main/AndroidManifest.xml
@@ -25,14 +25,27 @@
android:backupAgent="cgeo.geocaching.backup.CentralBackupAgent"
android:allowBackup="true" >
<uses-library android:name="com.google.android.maps" android:required="false" />
- <meta-data
+
+ <!-- Samsung Multi-Window support -->
+ <uses-library android:name="com.sec.android.app.multiwindow" android:required="false" />
+ <meta-data
+ android:name="com.sec.android.support.multiwindow"
+ android:value="true" />
+ <meta-data
+ android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W"
+ android:resource="@dimen/app_defaultsize_w" />
+ <meta-data
+ android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H"
+ android:resource="@dimen/app_defaultsize_h" />
+
+ <meta-data
android:name="android.app.default_searchable"
android:value=".SearchActivity" />
<meta-data
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAIsvD_aUSDMwWOf9NkwwxZ4kJJI_AG2EaxjSu2jw" />
<activity
- android:name=".cgeo"
+ android:name=".MainActivity"
android:label="@string/app_name"
android:windowSoftInputMode="stateHidden"
android:theme="@style/cgeo_main"
@@ -40,6 +53,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
</intent-filter>
</activity>
<activity
@@ -64,43 +78,43 @@
</activity>
<activity
android:name=".AboutActivity"
- android:label="@string/app_name"
+ android:label="@string/about"
android:windowSoftInputMode="stateHidden"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity
android:name=".UsefulAppsActivity"
- android:label="@string/app_name"
+ android:label="@string/helpers"
android:windowSoftInputMode="stateHidden"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity
android:name=".twitter.TwitterAuthorizationActivity"
- android:label="@string/app_name"
+ android:label="@string/auth_twitter"
android:windowSoftInputMode="stateHidden"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity
android:name=".EditWaypointActivity"
- android:label="@string/app_name"
+ android:label="@string/waypoint_edit_title"
android:windowSoftInputMode="stateHidden"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity
android:name=".NavigateAnyPointActivity"
- android:label="@string/app_name"
+ android:label="@string/search_destination"
android:windowSoftInputMode="stateHidden"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity
android:name=".AddressListActivity"
- android:label="@string/app_name"
+ android:label="@string/search_address_result"
android:windowSoftInputMode="stateHidden"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity
android:name=".SettingsActivity"
- android:label="@string/app_name"
+ android:label="@string/settings"
android:windowSoftInputMode="stateHidden"
android:configChanges="keyboardHidden|orientation" >
</activity>
@@ -125,27 +139,27 @@
</activity>
<activity
android:name=".maps.google.GoogleMapActivity"
- android:label="@string/app_name" >
+ android:label="@string/map_map" >
</activity>
<activity
android:name=".maps.mapsforge.MapsforgeMapActivity"
- android:label="@string/app_name" >
+ android:label="@string/map_map" >
</activity>
<activity
android:name=".maps.mapsforge.v024.MapsforgeMapActivity024"
- android:label="@string/app_name" >
+ android:label="@string/map_map" >
</activity>
<activity
android:name=".StaticMapsActivity"
- android:label="@string/app_name" >
+ android:label="@string/map_static_title" >
</activity>
<activity
android:name=".VisitCacheActivity"
- android:label="@string/app_name">
+ android:label="@string/log_new_log">
</activity>
<activity
android:name=".LogTrackableActivity"
- android:label="@string/app_name"
+ android:label="@string/trackable_touch"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity
@@ -179,6 +193,24 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="www.geocaching.com" android:pathPrefix="/seek/cache_details.aspx" />
</intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="http" android:host="opencaching.de" android:pathPrefix="/OC" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="http" android:host="www.opencaching.de" android:pathPrefix="/OC" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="http" android:host="www.opencaching.de" android:pathPrefix="/viewcache.php" />
+ </intent-filter>
</activity>
<activity
android:name="cgeo.geocaching.TrackableActivity"
@@ -204,33 +236,43 @@
</intent-filter>
</activity>
<activity
- android:name=".cgeonavigate"
- android:label="@string/app_name_compass">
+ android:name=".CompassActivity"
+ android:label="@string/compass_title">
</activity>
<activity
android:name=".GpxFileListActivity"
- android:label="@string/app_name"
+ android:label="@string/gpx_import_title"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity
android:name=".SelectMapfileActivity"
- android:label="@string/app_name"
+ android:label="@string/map_file_select_title"
android:configChanges="keyboardHidden|orientation" >
</activity>
<provider android:name=".apps.LocusDataStorageProvider"
android:authorities="cgeo.geocaching.apps.locusdatastorageprovider" />
<activity android:name="WaypointPopup"
- android:label="@string/app_name"
+ android:label="@string/waypoint"
android:windowSoftInputMode="stateHidden"
android:theme="@style/popup_dark"
android:configChanges="keyboardHidden|orientation" >
</activity>
<activity android:name=".files.SimpleDirChooser"
- android:label="@string/app_name">
+ android:label="@string/simple_dir_chooser_title">
</activity>
<activity
android:name=".ImageSelectActivity"
- android:label="@string/app_name">
- </activity>
- </application>
+ android:label="@string/log_image">
+ </activity>
+ <service
+ android:name=".speech.SpeechService"
+ android:label="@string/tts_service" >
+ </service>
+ <activity
+ android:name=".connector.oc.OCAuthorizationActivity"
+ android:label="@string/app_name"
+ android:windowSoftInputMode="stateHidden"
+ android:configChanges="keyboardHidden|orientation" >
+ </activity>
+</application>
</manifest>
diff --git a/main/ant.properties b/main/ant.properties
index c26774c..e3fa250 100644
--- a/main/ant.properties
+++ b/main/ant.properties
@@ -17,3 +17,5 @@
proguard.config=proguard.cfg
proguard.jar=support/proguard.jar
+source.dir=src;thirdparty
+java.compilerargs=-Xlint \ No newline at end of file
diff --git a/main/build.xml b/main/build.xml
index febb4ae..b97a158 100644
--- a/main/build.xml
+++ b/main/build.xml
@@ -53,7 +53,7 @@
<!-- Custom targets -->
<target name="install_release" description="Install signed release application" depends="release">
<exec executable="${sdk.dir}/platform-tools/adb">
- <arg line="install -r ./bin/${ant.project.name}-release.apk" />
+ <arg line="-d install -r ./bin/${ant.project.name}-release.apk" />
</exec>
</target>
@@ -83,6 +83,12 @@
<copy file="./templates/mapsapikey.xml" todir="./res/values/" overwrite="true">
<filterset refid="build-tokens" />
</copy>
+ <copy file="./templates/ocde_okapi.xml" todir="./res/values/" overwrite="true">
+ <filterset>
+ <filter token="ocde.okapi.consumer.key" value="${ocde.okapi.consumer.key}"/>
+ <filter token="ocde.okapi.consumer.secret" value="${ocde.okapi.consumer.secret}"/>
+ </filterset>
+ </copy>
</target>
<!--
diff --git a/main/libs/butterknife-1.3.2.jar b/main/libs/butterknife-1.3.2.jar
new file mode 100644
index 0000000..1bd6fe6
--- /dev/null
+++ b/main/libs/butterknife-1.3.2.jar
Binary files differ
diff --git a/main/lint.xml b/main/lint.xml
index c5b2b18..b165280 100644
--- a/main/lint.xml
+++ b/main/lint.xml
@@ -2,6 +2,7 @@
<lint>
<issue id="ContentDescription" severity="ignore" />
<issue id="ExportedContentProvider" severity="ignore" />
+ <issue id="InvalidPackage" severity="ignore" />
<issue id="MissingTranslation" severity="ignore" />
<issue id="Registered" severity="ignore" />
</lint> \ No newline at end of file
diff --git a/main/proguard.cfg b/main/proguard.cfg
index ee4d81a..23d603d 100644
--- a/main/proguard.cfg
+++ b/main/proguard.cfg
@@ -63,3 +63,7 @@
-keepclassmembers class cgeo.geocaching.compatibility.AndroidLevel8 {
public static <methods>;
}
+
+# Butter knife view injection, see http://jakewharton.github.io/butterknife/
+-dontwarn butterknife.Views$InjectViewProcessor
+-keepclassmembers class **$$ViewInjector {*;} \ No newline at end of file
diff --git a/main/project/attributes/iconlist.txt b/main/project/attributes/iconlist.txt
index 046add1..9d7584e 100644
--- a/main/project/attributes/iconlist.txt
+++ b/main/project/attributes/iconlist.txt
@@ -27,7 +27,7 @@ kids | 6 | 59 | x | PD | | ht
onehour | 7 | | x | CC0 | The Noun Project | http://thenounproject.com/noun/clock/#icon-No2306
scenic | 8 | | | PD | USA National Park Service | http://thenounproject.com/noun/binoculars/#icon-No112
hiking | 9 | 25 | | PD | USA National Park Service | http://thenounproject.com/noun/hiker/#icon-No562
-climbing | 10 | 28 | | PD | USA National Park Service | http://thenounproject.com/noun/climbing/#icon-No526
+climbing | 10 | | | PD | USA National Park Service | http://thenounproject.com/noun/climbing/#icon-No526
wading | 11 | | x | PD | USA National Park Service | http://thenounproject.com/noun/wading/#icon-No581
swimming | 12 | 29 | | PD | USA National Park Service | http://thenounproject.com/noun/swimming/#icon-No226
available | 13 | 38 | x | PD | koem | selfmade
@@ -86,6 +86,7 @@ railway | | 10 | | CC0 | | ht
syringe | | 23 | | CC0 | Betovarg Jabib | http://thenounproject.com/noun/syringe/#icon-No1508
swamp | | 26 | x | CC0 | Megan Strickland | http://thenounproject.com/noun/hand/#icon-No1477
hills | | 27 | x | PD | koem | selfmade
+easy_climbing | | 28 | x | PD | USA National Park Service | http://thenounproject.com/noun/climbing/#icon-No526
poi | | 30 | | PD | | http://thenounproject.com/noun/point-of-interest/#icon-No522
moving_target | | 31 | x | PD | | http://thenounproject.com/noun/running/#icon-No246
webcam | | 32 | | PD | | http://thenounproject.com/noun/video-camera/#icon-No637
@@ -109,3 +110,5 @@ other_cache | | 57 | x | PD | koem | se
ask_owner | | 58 | x | PD | koem | selfmade
#
unknown | -1 | -1 | x | PD | koem | selfmade
+geotour | 67 | | | CC0 | James Keuning | http://thenounproject.com/noun/suitcase/#icon-No9097
+
diff --git a/main/project/attributes/makeicons1res.sh b/main/project/attributes/makeicons1res.sh
index 85e9fd7..d0413cf 100755
--- a/main/project/attributes/makeicons1res.sh
+++ b/main/project/attributes/makeicons1res.sh
@@ -7,7 +7,9 @@ require () {
}
require optipng
+#part of ImageMagick package
require convert
+#part of ImageMagick package
require composite
require sed
diff --git a/main/project/attributes/readme.txt b/main/project/attributes/readme.txt
index 9b56328..f6af0db 100644
--- a/main/project/attributes/readme.txt
+++ b/main/project/attributes/readme.txt
@@ -69,3 +69,6 @@ If you made new icons:
./listEnStrings.sh will list all attribute strings from strings.xml and creates empty string tags for missing strings. The output of the missing string tags lack a ">" sign so that you get a compiler error as a reminder, when you inserted them into values/strings.xml.
+7. Edit res/values/cache_attributes.xml so that filtering can be performed with new attribute
+
+8. Edit src/cgeo/geocaching/files/GPXParser.java so attribute is recognized in GPX import
diff --git a/main/project/attributes/svgs/easy_climbing.svg b/main/project/attributes/svgs/easy_climbing.svg
new file mode 100644
index 0000000..682b053
--- /dev/null
+++ b/main/project/attributes/svgs/easy_climbing.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="96.114998"
+ height="94.002548"
+ viewBox="0 0 96.114999 94.002552"
+ enable-background="new 0 0 99.572 99.993"
+ xml:space="preserve"
+ inkscape:version="0.48.3.1 r9886"
+ sodipodi:docname="easy_climbing.svg"><metadata
+ id="metadata2876"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs2874"><inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 49.996498 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="99.571999 : 49.996498 : 1"
+ inkscape:persp3d-origin="49.785999 : 33.330999 : 1"
+ id="perspective2878" /></defs><sodipodi:namedview
+ pagecolor="#009674"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1317"
+ inkscape:window-height="744"
+ id="namedview2872"
+ showgrid="false"
+ inkscape:zoom="3.3377778"
+ inkscape:cx="46.452495"
+ inkscape:cy="45.214888"
+ inkscape:window-x="49"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+
+<path
+ d="m 77.215999,51.217552 7.57,-1.002 6.642,-27.295 4.687,0.25 0,66.571 c 0,2.356 -1.904,4.261003 -4.26,4.261003 L 2.1299988,93.927555 -1.1822193e-6,84.804552 23.584999,79.566552 l 3.685,-8.748 21.756,-7.77 16.636,7.369 6.392,-2.081 5.162,-17.119 z"
+ id="path2866"
+ style="fill:#ffffff"
+ inkscape:connector-curvature="0" />
+<g
+ id="g2986"
+ transform="matrix(0.74143286,0,0,0.74143286,0.25199462,0)"><path
+ style="fill:#ffffff"
+ id="path2864"
+ d="m 11.271,42.81 c -0.451,0.927 -0.777,1.955 -0.952,3.058 -0.075,0.552 -0.126,1.103 -0.126,1.654 l 0.401,25.259 -8.723,18.798 c -0.301,0.552 -0.526,1.203 -0.626,1.88 -0.477,3.107 1.654,5.99 4.762,6.467 2.406,0.376 4.712,-0.853 5.815,-2.883 l 9.6,-20.553 c 0.2,-0.477 0.376,-0.978 0.451,-1.529 0.024,-0.25 0.05,-0.525 0.05,-0.776 l -0.075,-15.608 14.738,6.435 2.381,15.265 c 0.477,2.23 2.306,4.01 4.688,4.386 3.107,0.451 5.99,-1.679 6.466,-4.763 0.075,-0.525 0.075,-1.053 0.025,-1.553 L 47.238,59.93 c -0.352,-1.78 -1.529,-3.309 -3.184,-4.086 l -13.184,-5.865 8.396,-14.613 4.161,5.289 c 0.426,0.477 0.977,0.877 1.604,1.128 l 15.866,4.637 c 2.105,0.451 4.261,-0.652 5.088,-2.682 0.928,-2.306 -0.176,-4.913 -2.456,-5.84 -0.075,-0.025 -0.15,-0.05 -0.226,-0.075 L 49.517,33.762 39.143,21.305 C 37.588,19.651 35.508,18.473 33.102,18.097 28.891,17.47 24.906,19.475 22.8,22.884 L 11.271,42.81 z"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#ffffff"
+ id="path2868"
+ d="m 38.24,16.994 c 4.687,0 8.496,-3.81 8.496,-8.497 C 46.736,3.81 42.927,0 38.24,0 c -4.688,0 -8.497,3.81 -8.497,8.497 0,4.687 3.81,8.497 8.497,8.497 z"
+ inkscape:connector-curvature="0" /></g>
+
+<g
+ transform="matrix(0.44375412,0,0,0.44375412,51.851618,11.258457)"
+ id="g2986-6"><path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff"
+ id="path2864-9"
+ d="m 11.271,42.81 c -0.451,0.927 -0.777,1.955 -0.952,3.058 -0.075,0.552 -0.126,1.103 -0.126,1.654 l 0.401,25.259 -8.723,18.798 c -0.301,0.552 -0.526,1.203 -0.626,1.88 -0.477,3.107 1.654,5.99 4.762,6.467 2.406,0.376 4.712,-0.853 5.815,-2.883 l 9.6,-20.553 c 0.2,-0.477 0.376,-0.978 0.451,-1.529 0.024,-0.25 0.05,-0.525 0.05,-0.776 l -0.075,-15.608 14.738,6.435 2.381,15.265 c 0.477,2.23 2.306,4.01 4.688,4.386 3.107,0.451 5.99,-1.679 6.466,-4.763 0.075,-0.525 0.075,-1.053 0.025,-1.553 L 47.238,59.93 c -0.352,-1.78 -1.529,-3.309 -3.184,-4.086 l -13.184,-5.865 8.396,-14.613 4.161,5.289 c 0.426,0.477 0.977,0.877 1.604,1.128 l 15.866,4.637 c 2.105,0.451 4.261,-0.652 5.088,-2.682 0.928,-2.306 -0.176,-4.913 -2.456,-5.84 -0.075,-0.025 -0.15,-0.05 -0.226,-0.075 L 49.517,33.762 39.143,21.305 C 37.588,19.651 35.508,18.473 33.102,18.097 28.891,17.47 24.906,19.475 22.8,22.884 L 11.271,42.81 z" /><path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff"
+ id="path2868-3"
+ d="m 38.24,16.994 c 4.687,0 8.496,-3.81 8.496,-8.497 C 46.736,3.81 42.927,0 38.24,0 c -4.688,0 -8.497,3.81 -8.497,8.497 0,4.687 3.81,8.497 8.497,8.497 z" /></g></svg> \ No newline at end of file
diff --git a/main/project/attributes/svgs/geotour.svg b/main/project/attributes/svgs/geotour.svg
new file mode 100644
index 0000000..c615c37
--- /dev/null
+++ b/main/project/attributes/svgs/geotour.svg
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="88.75"
+ height="83.125"
+ viewBox="0 0 71 66.5"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="geotour.svg">
+ <sodipodi:namedview
+ pagecolor="#009674"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1366"
+ inkscape:window-height="702"
+ id="namedview10"
+ showgrid="true"
+ inkscape:zoom="4"
+ inkscape:cx="49.222291"
+ inkscape:cy="32.85486"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg2"
+ inkscape:snap-grids="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0">
+ <inkscape:grid
+ originy="-10.312499px"
+ originx="-5.6249999px"
+ snapvisiblegridlinesonly="true"
+ enabled="true"
+ visible="true"
+ empspacing="5"
+ id="grid2991"
+ type="xygrid" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata14">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs12" />
+ <path
+ sodipodi:nodetypes="sccccccccssccccsscssccssccsscsc"
+ inkscape:connector-curvature="0"
+ id="rect2983"
+ d="M 35.5,0 C 32.173466,0 28.832789,0.597736 24.39741,1.796264 l 0,9.592816 -8.839641,0 0,55.11092 39.884462,0 0,-55.11092 -8.839641,0 c 0,0 0.110884,-6.3567879 0,-9.592816 C 42.167211,0.597736 38.826534,0 35.5,0 z m 0,4.547988 c 2.217689,0 4.429721,0.3509981 6.64741,1.0701151 l 0,5.7709769 -13.29482,0 0,-5.7709769 C 31.070279,4.8989861 33.282311,4.547988 35.5,4.547988 z M 5.233068,11.38908 C 2.069078,11.45462 0,11.971529 0,16.166379 0.221769,31.088062 0,56.928586 0,61.722701 0,66.516816 2.24739,66.5 6.6827691,66.5 l 4.4198209,0 0,-55.11092 -4.4198209,0 c -0.493858,0 -0.997702,-0.0094 -1.4497011,0 z m 54.664343,0 0,55.11092 4.41982,0 C 68.374172,66.5 71,66.51682 71,61.722701 71,56.928586 70.778231,31.088062 71,16.166379 71,11.372264 68.75261,11.38908 64.317231,11.38908 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:none" />
+</svg>
diff --git a/main/project/attributes_okapi/AttrGen/.classpath b/main/project/attributes_okapi/AttrGen/.classpath
new file mode 100644
index 0000000..18d70f0
--- /dev/null
+++ b/main/project/attributes_okapi/AttrGen/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/main/project/attributes_okapi/AttrGen/.project b/main/project/attributes_okapi/AttrGen/.project
new file mode 100644
index 0000000..cccc238
--- /dev/null
+++ b/main/project/attributes_okapi/AttrGen/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>AttrGen</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/main/project/attributes_okapi/AttrGen/.settings/org.eclipse.jdt.core.prefs b/main/project/attributes_okapi/AttrGen/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8000cd6
--- /dev/null
+++ b/main/project/attributes_okapi/AttrGen/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+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
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/main/project/attributes_okapi/AttrGen/.settings/org.eclipse.jdt.ui.prefs b/main/project/attributes_okapi/AttrGen/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..cc7a309
--- /dev/null
+++ b/main/project/attributes_okapi/AttrGen/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,54 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/main/project/attributes_okapi/AttrGen/build.xml b/main/project/attributes_okapi/AttrGen/build.xml
new file mode 100644
index 0000000..e8426f3
--- /dev/null
+++ b/main/project/attributes_okapi/AttrGen/build.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project default="create_run_jar" name="Create Runnable Jar for Project AttrGen">
+ <!--this file was created by Eclipse Runnable JAR Export Wizard-->
+ <!--ANT 1.7 is required -->
+ <target name="create_run_jar">
+ <jar destfile="../genattr.jar" filesetmanifest="mergewithoutmain">
+ <manifest>
+ <attribute name="Main-Class" value="GenerateAttributes"/>
+ <attribute name="Class-Path" value="."/>
+ </manifest>
+ <fileset dir="bin"/>
+ </jar>
+ </target>
+</project>
diff --git a/main/project/attributes_okapi/AttrGen/src/GenerateAttributes.java b/main/project/attributes_okapi/AttrGen/src/GenerateAttributes.java
new file mode 100644
index 0000000..725dfff
--- /dev/null
+++ b/main/project/attributes_okapi/AttrGen/src/GenerateAttributes.java
@@ -0,0 +1,172 @@
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+public class GenerateAttributes {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ File inFile = new File(args[0]);
+ InputStream inputStream;
+
+ try {
+
+ writeHeader();
+
+ inputStream = new FileInputStream(inFile);
+ Reader reader = new InputStreamReader(inputStream,"UTF-8");
+
+ InputSource is = new InputSource(reader);
+ is.setEncoding("UTF-8");
+
+ parseAttributes(is);
+
+ writeTrailer();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void writeHeader() {
+ System.out.print(
+"// This is a generated file, do not change manually!\n" +
+"\n" +
+"package cgeo.geocaching.connector.oc;\n" +
+"\n" +
+"import java.util.HashMap;\n" +
+"import java.util.Map;\n" +
+"\n" +
+"public class AttributeParser {\n" +
+"\n" +
+" private final static Map<String, Integer> attrMapDe;\n" +
+" private final static Map<String, Integer> attrMapPl;\n" +
+"\n" +
+" static {\n" +
+" attrMapDe = new HashMap<String, Integer>();\n" +
+" attrMapPl = new HashMap<String, Integer>();\n" +
+"\n" +
+" // last header line\n");
+ }
+
+ private static void writeAttr(AttrInfo attr) {
+
+ for(String name : attr.names) {
+ if (attr.oc_de_id > 0) {
+ System.out.println(" attrMapDe.put(\"" + name + "\", " + attr.oc_de_id + ");");
+ }
+ if (attr.oc_pl_id > 0) {
+ System.out.println(" attrMapPl.put(\"" + name + "\", " + attr.oc_pl_id + ");");
+ }
+ }
+
+ }
+
+ private static void writeTrailer() {
+ System.out.print(
+" // first trailer line\n" +
+"\n" +
+" }\n" +
+"\n" +
+" public static int getOcDeId(final String name) {\n" +
+"\n" +
+" int result = 0;\n" +
+"\n" +
+" if (attrMapDe.containsKey(name)) {\n" +
+" result = attrMapDe.get(name);\n" +
+" }\n" +
+" return result;\n" +
+" }\n" +
+"}\n");
+ }
+
+ private static void parseAttributes(InputSource stream) {
+
+ try {
+
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ SAXParser saxParser = factory.newSAXParser();
+
+ DefaultHandler handler = new DefaultHandler() {
+
+ AttrInfo attr;
+ ArrayList<String> names;
+ boolean readingName;
+
+ public void startElement(String uri, String localName,
+ String qName, Attributes attributes)
+ throws SAXException {
+
+ if (qName.equalsIgnoreCase("attr")) {
+ attr = new AttrInfo();
+ names = new ArrayList<String>();
+ }
+
+ if (attr != null && qName.equalsIgnoreCase("opencaching")) {
+ if ("http://opencaching.de/".equalsIgnoreCase(attributes.getValue("site_url"))) {
+ attr.oc_de_id = Integer.parseInt(attributes.getValue("id"));
+ } else if ("http://opencaching.pl/".equalsIgnoreCase(attributes.getValue("site_url"))) {
+ attr.oc_pl_id = Integer.parseInt(attributes.getValue("id"));
+ }
+ }
+
+ if (names != null && qName.equalsIgnoreCase("name")) {
+ readingName = true;
+ }
+ }
+
+ public void endElement(String uri, String localName,
+ String qName)
+ throws SAXException {
+
+ if (attr != null && qName.equalsIgnoreCase("attr")) {
+ attr.names = names.toArray(new String[]{});
+ names = null;
+ writeAttr(attr);
+ attr = null;
+ }
+
+ readingName = false;
+ }
+
+ public void characters(char ch[], int start, int length)
+ throws SAXException {
+
+ if (readingName) {
+ names.add(new String(ch, start, length));
+ }
+ }
+
+ };
+
+ saxParser.parse(stream, handler);
+
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ static class AttrInfo {
+ public int oc_de_id;
+ public int oc_pl_id;
+ public String[] names;
+ }
+
+}
diff --git a/main/project/attributes_okapi/AttributeParser.java b/main/project/attributes_okapi/AttributeParser.java
new file mode 100644
index 0000000..63bee77
--- /dev/null
+++ b/main/project/attributes_okapi/AttributeParser.java
@@ -0,0 +1,327 @@
+// This is a generated file, do not change manually!
+
+package cgeo.geocaching.connector.oc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class AttributeParser {
+
+ private final static Map<String, Integer> attrMapDe;
+ private final static Map<String, Integer> attrMapPl;
+
+ static {
+ attrMapDe = new HashMap<String, Integer>();
+ attrMapPl = new HashMap<String, Integer>();
+
+ // last header line
+ attrMapDe.put("Listed at Opencaching only", 6);
+ attrMapDe.put("Dostępna tylko na Opencaching", 6);
+ attrMapDe.put("Nur bei Opencaching logbar", 6);
+ attrMapDe.put("Solo loggeable en Opencaching", 6);
+ attrMapDe.put("Loggabile solo su Opencaching", 6);
+ attrMapPl.put("Near a Survey Marker", 54);
+ attrMapPl.put("W pobliżu punktu geodezyjnego", 54);
+ attrMapPl.put("Whereigo Cache", 55);
+ attrMapPl.put("Whereigo Cache", 55);
+ attrMapPl.put("Whereigo Cache", 55);
+ attrMapDe.put("Letterbox Cache", 8);
+ attrMapPl.put("Letterbox Cache", 56);
+ attrMapDe.put("Skrzynka typu Letterbox", 8);
+ attrMapPl.put("Skrzynka typu Letterbox", 56);
+ attrMapDe.put("Letterbox (benötigt Stempel)", 8);
+ attrMapPl.put("Letterbox (benötigt Stempel)", 56);
+ attrMapDe.put("Letterbox (necesita un estampador)", 8);
+ attrMapPl.put("Letterbox (necesita un estampador)", 56);
+ attrMapDe.put("Letterbox (richiede un timbro)", 8);
+ attrMapPl.put("Letterbox (richiede un timbro)", 56);
+ attrMapPl.put("GeoHotel", 43);
+ attrMapPl.put("GeoHotel", 43);
+ attrMapPl.put("GeoHotel", 43);
+ attrMapPl.put("Magnetic cache", 49);
+ attrMapPl.put("Przyczepiona magnesem", 49);
+ attrMapPl.put("magnetischer Cache", 49);
+ attrMapPl.put("Description contains an audio file", 50);
+ attrMapPl.put("Opis zawiera plik audio", 50);
+ attrMapPl.put("Offset cache", 51);
+ attrMapPl.put("Offset cache", 51);
+ attrMapPl.put("Peilungscache", 51);
+ attrMapPl.put("Garmin's wireless beacon", 52);
+ attrMapPl.put("Beacon - Garmin Chirp", 52);
+ attrMapPl.put("Funksignal – Garmin Chirp", 52);
+ attrMapPl.put("Dead Drop USB cache", 53);
+ attrMapPl.put("Dead Drop USB skrzynka", 53);
+ attrMapDe.put("Has a moving target", 31);
+ attrMapDe.put("bewegliches Ziel", 31);
+ attrMapDe.put("Objetivo en movimiento", 31);
+ attrMapDe.put("Oggetto in movimento", 31);
+ attrMapDe.put("Webcam Cache", 32);
+ attrMapDe.put("Webcam Cache", 32);
+ attrMapDe.put("Webcam Cache", 32);
+ attrMapDe.put("Webcam Cache", 32);
+ attrMapDe.put("Other cache type", 57);
+ attrMapDe.put("sonstiger Cachetyp", 57);
+ attrMapDe.put("Otro tipo de cache", 57);
+ attrMapDe.put("Altro tipo di cache", 57);
+ attrMapDe.put("Investigation required", 54);
+ attrMapDe.put("Recherche", 54);
+ attrMapDe.put("Investigación", 54);
+ attrMapDe.put("Ricerca", 54);
+ attrMapDe.put("Puzzle / Mystery", 55);
+ attrMapDe.put("Rätsel", 55);
+ attrMapDe.put("Puzzle / Misterio", 55);
+ attrMapDe.put("Puzzle / Mystery", 55);
+ attrMapDe.put("Arithmetical problem", 56);
+ attrMapDe.put("Rechenaufgabe", 56);
+ attrMapDe.put("Problema matemático", 56);
+ attrMapDe.put("Problema matematico", 56);
+ attrMapDe.put("Ask owner for start conditions", 58);
+ attrMapDe.put("Startbedingungen beim Owner erfragen", 58);
+ attrMapDe.put("Ask owner for start conditions", 58);
+ attrMapDe.put("Ask owner for start conditions", 58);
+ attrMapPl.put("Wheelchair accessible", 44);
+ attrMapPl.put("Dostępna dla niepełnosprawnych", 44);
+ attrMapPl.put("rollstuhltauglich", 44);
+ attrMapDe.put("Near the parking area", 24);
+ attrMapDe.put("nahe beim Auto", 24);
+ attrMapDe.put("Cerca de un Parking", 24);
+ attrMapDe.put("Vicino all'area di parcheggio", 24);
+ attrMapPl.put("Access only by walk", 84);
+ attrMapPl.put("Dostępna tylko pieszo", 84);
+ attrMapDe.put("Long walk", 25);
+ attrMapDe.put("längere Wanderung", 25);
+ attrMapDe.put("Larga caminata", 25);
+ attrMapDe.put("Lunga camminata", 25);
+ attrMapDe.put("Swamp, marsh or wading", 26);
+ attrMapDe.put("sumpfig/matschiges Gelände / waten", 26);
+ attrMapDe.put("Pantano / terreno fangoso", 26);
+ attrMapDe.put("Palude o marcita", 26);
+ attrMapDe.put("Hilly area", 27);
+ attrMapDe.put("hügeliges Gelände", 27);
+ attrMapDe.put("Terreno montañoso", 27);
+ attrMapDe.put("Area collinare", 27);
+ attrMapDe.put("Some climbing (no gear needed)", 28);
+ attrMapDe.put("leichtes Klettern (ohne Ausrüstung)", 28);
+ attrMapDe.put("fácil de subir (sin equipo)", 28);
+ attrMapDe.put("Arrampicata (attrezzatura non necessaria)", 28);
+ attrMapDe.put("Swimming required", 29);
+ attrMapDe.put("Schwimmen erforderlich", 29);
+ attrMapDe.put("Requiere nadar", 29);
+ attrMapDe.put("Nuoto necessario", 29);
+ attrMapDe.put("Access or parking fee", 36);
+ attrMapDe.put("Zugangs- bzw. Parkentgelt", 36);
+ attrMapDe.put("Acceso o parking pagando", 36);
+ attrMapDe.put("Tassa di ingresso o di parcheggio", 36);
+ attrMapPl.put("Bikes allowed", 85);
+ attrMapPl.put("Dostępna rowerem", 85);
+ attrMapPl.put("Hidden in natural surroundings (forests, mountains, etc.)", 60);
+ attrMapPl.put("Umiejscowiona na łonie natury (lasy, góry, itp.)", 60);
+ attrMapPl.put("Historic site", 61);
+ attrMapPl.put("Miejsce historyczne", 61);
+ attrMapDe.put("Point of interest", 30);
+ attrMapDe.put("interessanter Ort", 30);
+ attrMapDe.put("Punto de interes", 30);
+ attrMapDe.put("Punto di interesse", 30);
+ attrMapDe.put("Hidden wihin enclosed rooms (caves, buildings etc.)", 33);
+ attrMapDe.put("in geschlossenen Räumen (Höhle, Gebäude, etc.)", 33);
+ attrMapDe.put("en espacios confinados (cuevas, edificios, etc)", 33);
+ attrMapDe.put("All'interno di stanze chiuse (caverne, edifici, ecc.)", 33);
+ attrMapDe.put("Hidden under water", 34);
+ attrMapDe.put("Im Wasser versteckt", 34);
+ attrMapDe.put("En el agua", 34);
+ attrMapDe.put("Nell'acqua", 34);
+ attrMapDe.put("Parking area nearby", 18);
+ attrMapDe.put("Parkplatz in der Nähe", 18);
+ attrMapDe.put("Parking cercano", 18);
+ attrMapDe.put("Parcheggio nei pressi", 18);
+ attrMapDe.put("Public transportation", 19);
+ attrMapDe.put("erreichbar mit ÖVM", 19);
+ attrMapDe.put("Transporte Público", 19);
+ attrMapDe.put("Trasporto pubblico", 19);
+ attrMapDe.put("Drinking water nearby", 20);
+ attrMapDe.put("Trinkwasser in der Nähe", 20);
+ attrMapDe.put("Agua potable en las cercanias", 20);
+ attrMapDe.put("Acqua potabile nei pressi", 20);
+ attrMapDe.put("Public restrooms nearby", 21);
+ attrMapDe.put("öffentliche Toilette in der Nähe", 21);
+ attrMapDe.put("Aseos públicos cercanos", 21);
+ attrMapDe.put("Bagni pubblici nei pressi", 21);
+ attrMapDe.put("Public phone nearby", 22);
+ attrMapDe.put("Telefon in der Nähe", 22);
+ attrMapDe.put("Teléfono Público en las cercanias", 22);
+ attrMapDe.put("Telefono pubblico nei pressi", 22);
+ attrMapDe.put("First aid available", 23);
+ attrMapDe.put("Erste Hilfe verfügbar", 23);
+ attrMapDe.put("Disponible socorro rapido", 23);
+ attrMapDe.put("Disponibile pronto soccorso", 23);
+ attrMapDe.put("Available 24/7", 38);
+ attrMapDe.put("rund um die Uhr machbar", 38);
+ attrMapDe.put("Disponible las 24 horas", 38);
+ attrMapDe.put("Disponibile 24 ore", 38);
+ attrMapDe.put("Not 24/7", 39);
+ attrMapPl.put("Not 24/7", 80);
+ attrMapDe.put("Dostępna w określonych godzinach", 39);
+ attrMapPl.put("Dostępna w określonych godzinach", 80);
+ attrMapDe.put("nur zu bestimmten Uhrzeiten", 39);
+ attrMapPl.put("nur zu bestimmten Uhrzeiten", 80);
+ attrMapDe.put("Sólo disponible a ciertas horas", 39);
+ attrMapPl.put("Sólo disponible a ciertas horas", 80);
+ attrMapDe.put("Disponibile solo in certi orari", 39);
+ attrMapPl.put("Disponibile solo in certi orari", 80);
+ attrMapDe.put("Not recommended at night", 40);
+ attrMapDe.put("nur tagüber", 40);
+ attrMapDe.put("solo por el día", 40);
+ attrMapDe.put("solo di giorno", 40);
+ attrMapPl.put("Recommended at night", 91);
+ attrMapPl.put("Zalecane szukanie nocą", 91);
+ attrMapPl.put("am besten nachts findbar", 91);
+ attrMapDe.put("Only at night", 1);
+ attrMapDe.put("nur bei Nacht", 1);
+ attrMapDe.put("Sólo por la noche", 1);
+ attrMapDe.put("Solo di notte", 1);
+ attrMapDe.put("All seasons", 42);
+ attrMapDe.put("ganzjähig zugänglich", 42);
+ attrMapDe.put("Todas las temporadas", 42);
+ attrMapDe.put("Tutte le stagioni", 42);
+ attrMapDe.put("Only available during specified seasons", 60);
+ attrMapDe.put("Nur zu bestimmten Zeiten im Jahr", 60);
+ attrMapDe.put("Sólo disponible durante las estaciones especificadas", 60);
+ attrMapDe.put("Disponibile solo in certe stagioni", 60);
+ attrMapDe.put("Breeding season / protected nature", 43);
+ attrMapDe.put("Brutsaison / Naturschutz", 43);
+ attrMapDe.put("Temporada de reproducción / protección de la naturaleza", 43);
+ attrMapDe.put("Stagione di riproduzione / natura protetta", 43);
+ attrMapDe.put("Available during winter", 44);
+ attrMapDe.put("schneesicheres Versteck", 44);
+ attrMapDe.put("Nieve en el escondite", 44);
+ attrMapDe.put("Luogo a prova di neve", 44);
+ attrMapDe.put("Not at high water level", 41);
+ attrMapDe.put("nicht bei Hochwasser oder Flut", 41);
+ attrMapDe.put("Compass required", 47);
+ attrMapPl.put("Compass required", 47);
+ attrMapDe.put("Potrzebny kompas", 47);
+ attrMapPl.put("Potrzebny kompas", 47);
+ attrMapDe.put("Kompass", 47);
+ attrMapPl.put("Kompass", 47);
+ attrMapDe.put("Brújula", 47);
+ attrMapPl.put("Brújula", 47);
+ attrMapDe.put("Bussola", 47);
+ attrMapPl.put("Bussola", 47);
+ attrMapPl.put("Take something to write", 48);
+ attrMapPl.put("Weź coś do pisania", 48);
+ attrMapPl.put("You may need a shovel", 81);
+ attrMapPl.put("Potrzebna łopatka", 81);
+ attrMapDe.put("Flashlight required", 48);
+ attrMapPl.put("Flashlight required", 82);
+ attrMapDe.put("Potrzebna latarka", 48);
+ attrMapPl.put("Potrzebna latarka", 82);
+ attrMapDe.put("Taschenlampe", 48);
+ attrMapPl.put("Taschenlampe", 82);
+ attrMapDe.put("Linterna", 48);
+ attrMapPl.put("Linterna", 82);
+ attrMapDe.put("Lampada tascabile", 48);
+ attrMapPl.put("Lampada tascabile", 82);
+ attrMapDe.put("Climbing gear required", 49);
+ attrMapDe.put("Kletterzeug", 49);
+ attrMapDe.put("Equipo de escalada", 49);
+ attrMapDe.put("Attrezzatura per arrampicata", 49);
+ attrMapDe.put("Cave equipment required", 50);
+ attrMapDe.put("Höhlenzeug", 50);
+ attrMapDe.put("Equipación para cuevas", 50);
+ attrMapDe.put("Attrezzatura per grotta", 50);
+ attrMapDe.put("Diving equipment required", 51);
+ attrMapDe.put("Taucherausrüstung", 51);
+ attrMapDe.put("Diving equipment", 51);
+ attrMapDe.put("Equipo de buceo", 51);
+ attrMapDe.put("Special tools required", 46);
+ attrMapPl.put("Special tools required", 83);
+ attrMapDe.put("Wymagany dodatkowy sprzęt", 46);
+ attrMapPl.put("Wymagany dodatkowy sprzęt", 83);
+ attrMapDe.put("spezielle Ausrüstung", 46);
+ attrMapPl.put("spezielle Ausrüstung", 83);
+ attrMapDe.put("Equipamiento especial", 46);
+ attrMapPl.put("Equipamiento especial", 83);
+ attrMapDe.put("Equipaggiamento speciale", 46);
+ attrMapPl.put("Equipaggiamento speciale", 83);
+ attrMapDe.put("Requires a boat", 52);
+ attrMapPl.put("Requires a boat", 86);
+ attrMapDe.put("Wymaga sprzętu pływającego", 52);
+ attrMapPl.put("Wymaga sprzętu pływającego", 86);
+ attrMapDe.put("Wasserfahrzeug", 52);
+ attrMapPl.put("Wasserfahrzeug", 86);
+ attrMapDe.put("Barca", 52);
+ attrMapPl.put("Barca", 86);
+ attrMapDe.put("Barca", 52);
+ attrMapPl.put("Barca", 86);
+ attrMapDe.put("No GPS required", 35);
+ attrMapDe.put("ohne GPS findbar", 35);
+ attrMapDe.put("Sin GPS", 35);
+ attrMapDe.put("Senza GPS", 35);
+ attrMapDe.put("Dangerous area", 9);
+ attrMapPl.put("Dangerous area", 90);
+ attrMapDe.put("Skrzynka niebezpieczna", 9);
+ attrMapPl.put("Skrzynka niebezpieczna", 90);
+ attrMapDe.put("gefährliches Gebiet", 9);
+ attrMapPl.put("gefährliches Gebiet", 90);
+ attrMapDe.put("Zona Peligrosa", 9);
+ attrMapPl.put("Zona Peligrosa", 90);
+ attrMapDe.put("Area pericolosa", 9);
+ attrMapPl.put("Area pericolosa", 90);
+ attrMapDe.put("Active railway nearby", 10);
+ attrMapDe.put("aktive Eisenbahnlinie in der Nähe", 10);
+ attrMapDe.put("Cerca del ferrocarril activo", 10);
+ attrMapDe.put("Ferrovia attiva nei pressi", 10);
+ attrMapDe.put("Cliff / Rocks", 11);
+ attrMapDe.put("Klippen / Felsen", 11);
+ attrMapDe.put("Acantilado / Rocas", 11);
+ attrMapDe.put("Scogliera / Rocce", 11);
+ attrMapDe.put("Hunting", 12);
+ attrMapDe.put("Jagdgebiet", 12);
+ attrMapDe.put("Zona de Caza", 12);
+ attrMapDe.put("Caccia", 12);
+ attrMapDe.put("Thorns", 13);
+ attrMapDe.put("Dornen", 13);
+ attrMapDe.put("Espinas", 13);
+ attrMapDe.put("Spine", 13);
+ attrMapDe.put("Ticks", 14);
+ attrMapDe.put("Zecken", 14);
+ attrMapDe.put("Garrapatas", 14);
+ attrMapDe.put("Zecche", 14);
+ attrMapDe.put("Abandoned mines", 15);
+ attrMapDe.put("Folgen des Bergbaus", 15);
+ attrMapDe.put("Mina abandonada", 15);
+ attrMapDe.put("Miniere abbandonate", 15);
+ attrMapDe.put("Poisonous plants", 16);
+ attrMapDe.put("giftige Pflanzen", 16);
+ attrMapDe.put("Planta venenosa", 16);
+ attrMapDe.put("Piante velenose", 16);
+ attrMapDe.put("Dangerous animals", 17);
+ attrMapDe.put("giftige/gefährliche Tiere", 17);
+ attrMapDe.put("Animales Peligrosos", 17);
+ attrMapDe.put("Animali pericolosi", 17);
+ attrMapPl.put("Quick cache", 40);
+ attrMapPl.put("Szybka skrzynka", 40);
+ attrMapDe.put("Overnight stay necessary", 37);
+ attrMapDe.put("Übernachtung erforderlich", 37);
+ attrMapDe.put("Necesario pernoctar", 37);
+ attrMapDe.put("Necessario pernottamento", 37);
+ attrMapPl.put("Take your children", 41);
+ attrMapPl.put("Można zabrać dzieci", 41);
+ attrMapDe.put("Suited for children (10-12 yo)", 59);
+ attrMapDe.put("kindgerecht (10-12 Jahre)", 59);
+ attrMapDe.put("Apto para niños (10-12 años)", 59);
+ attrMapDe.put("Suited for children (10-12 anni)", 59);
+ // first trailer line
+
+ }
+
+ public static int getOcDeId(final String name) {
+
+ int result = 0;
+
+ if (attrMapDe.containsKey(name)) {
+ result = attrMapDe.get(name);
+ }
+ return result;
+ }
+}
diff --git a/main/project/attributes_okapi/attributes.xml b/main/project/attributes_okapi/attributes.xml
new file mode 100644
index 0000000..ede81a8
--- /dev/null
+++ b/main/project/attributes_okapi/attributes.xml
@@ -0,0 +1,1940 @@
+<!--
+
+Current status: WORKING DRAFT
+
+This is the list of all geocache attributes supported by OKAPI. In
+practise, it will usually include any atribute used by at least one of
+the Opencaching installations.
+
+
+NOTES FOR EXTERNAL APP DEVELOPERS
+=================================
+
+DO NOT read or parse this file in your apps! It is NOT guaranteed to stay
+backward-compatible. Use public OKAPI methods instead.
+
+
+NOTES FOR OC/OKAPI DEVELOPERS
+=============================
+
+Every OC installation has its own set of internal attributes. This file
+allows them to be merged with other attributes from other OC installations.
+It is periodically read by every OKAPI installation, *directly from
+the repository*.
+
+This file defines the mapping between:
+
+1. Internal attribute IDs of various Opencaching nodes.
+2. Groundspeak's attribute IDs (used by geocaching.com).
+3. OKAPI's attribute IDs.
+
+Important: This is a verbose, many-to-many, optional relationship! Crow's foot
+notation: http://i.imgur.com/cNGz1xt.png. All those attributes may appear not
+very useful when provided this way, but there is nothing OKAPI can do about it.
+We leave the UI clarity problem for app developers.
+
+-->
+
+<xml>
+
+ <!-- Language forms - status: just an idea, unimplemented (see form=""
+ attributes in <attr> elements). TODO: fill missing form="" attributes. -->
+
+ <form id="is / not is">
+ <prefix lang="en">
+ <include><b>Include</b> the cache, only if it is:</include>
+ <exclude><b>Exclude</b> the cache if it is:</exclude>
+ </prefix>
+ <prefix lang="pl">
+ <include><b>Uwzględnij</b> skrzynkę, tylko jeśli jest:</include>
+ <exclude><b>Pomiń</b> skrzynkę, jeśli jest:</exclude>
+ </prefix>
+ </form>
+
+ <form id="contains / does not contain">
+ <prefix lang="en">
+ <include><b>Include</b> the cache, only if it contains:</include>
+ <exclude><b>Exclude</b> the cache if it contains:</exclude>
+ </prefix>
+ <prefix lang="pl">
+ <include><b>Uwzględnij</b> skrzynkę, tylko jeśli zawiera:</include>
+ <exclude><b>Pomiń</b> skrzynkę, jeśli nie zawiera:</exclude>
+ </prefix>
+ </form>
+
+ <form id="allowed / not allowed">
+ <prefix lang="en">
+ <include>The following <b>must be allowed</b>:</include>
+ <exclude>The following <b>may not be allowed</b>:</exclude>
+ </prefix>
+ </form>
+
+ <form id="required / not required">
+ <prefix lang="en">
+ <include>The following <b>must be required</b>:</include>
+ <exclude>The following <b>may not be required</b>:</exclude>
+ </prefix>
+ </form>
+
+ <form id="if / if not">
+ <prefix lang="en">
+ <include>The following <b>must be true</b>:</include>
+ <exclude>The following <b>may not be true</b>:</exclude>
+ </prefix>
+ </form>
+
+ <!--
+
+ NOTICE: Categories are currently NOT implemented. In particular, the
+ attr[categories] is ignored. See issue 70.
+
+ <category id="de-cache-types">
+ <name lang="en">TODO</name>
+ </category>
+
+ <category id="de-location">
+ <name lang="en">TODO</name>
+ </category>
+
+ <category id="de-facilities">
+ <name lang="en">TODO</name>
+ </category>
+
+ <category id="de-time-and-seasons">
+ <name lang="en">TODO</name>
+ </category>
+
+ <category id="de-tools">
+ <name lang="en">TODO</name>
+ </category>
+
+ <category id="de-dangers">
+ <name lang="en">TODO</name>
+ </category>
+
+ <category id="de-rating">
+ <name lang="en">TODO</name>
+ </category>
+
+ <category id="de-preconditions">
+ <name lang="en">TODO</name>
+ </category>
+
+ <category id="de-accessibility">
+ <name lang="en">TODO</name>
+ </category>
+
+ -->
+
+ <attr okapi_attr_id="oconly" categories="de-listing" form="is / is not">
+ <opencaching site_url="http://opencaching.de/" id="6" />
+ <name lang="en">Listed at Opencaching only</name>
+ <desc lang="en">
+ This geocache is listed at Opencaching only.
+ </desc>
+ <name lang="pl">Dostępna tylko na Opencaching</name>
+ <desc lang="pl">
+ Skrzynka "jednosystemowa", dostępna jedynie poprzez serwis Opencaching.
+ </desc>
+ <name lang="de">Nur bei Opencaching logbar</name>
+ <desc lang="de">
+ Der Geocache ist nur bei Opencaching gelistet. Benutzer anderer
+ Geocache-Datenbanken haben so einen schnellen Überblick, welche Geocaches
+ es sich lohnt näher anzusehen.
+ </desc>
+ <name lang="es">Solo loggeable en Opencaching</name>
+ <desc lang="es">
+ Este geocachee esta publicado sólo en Opencaching. Este atributo permite
+ a los usuarios de otras plataformas encontrar rápidamente caches
+ interesantes de calidad OC geocaching.
+ </desc>
+ <name lang="it">Loggabile solo su Opencaching</name>
+ <desc lang="it">
+ Questa geocache è pubblicata solo su Opencaching. Questo attributo permette
+ agli utenti di altre piattaforme di geocaching di trovare velocemente
+ interessanti cache OC di qualità.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="near-survey-marker" categories="de-cache-types" form="is / is not">
+ <opencaching site_url="http://opencaching.pl/" id="54" />
+ <name lang="en">Near a Survey Marker</name>
+ <desc lang="en">
+ The cache is hidden in near proximity of a survey marker (also known
+ as geodetic marks).
+ </desc>
+ <name lang="pl">W pobliżu punktu geodezyjnego</name>
+ <desc lang="pl">
+ Skrzynka ukryta w pobliżu punktu geodezyjnego.
+ <a href='http://wiki.opencaching.pl/index.php/Benchmark'>Więcej informacji</a>.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="wherigo" categories="de-cache-types" form="is / is not">
+ <opencaching site_url="http://opencaching.pl/" id="55" />
+ <name lang="en">Whereigo Cache</name>
+ <desc lang="en">
+ Cache description includes a file - the Whereigo cartridge. In order to
+ find the cache, you need to download the file and install it on
+ a proper compatible device.
+ </desc>
+ <name lang="pl">Whereigo Cache</name>
+ <desc lang="pl">
+ Opis skrzynki zawiera scenariusz WIGO (ang. Whereigo). Aby móc zdobyć skrzynkę
+ należy pobrać scenariusz i wgrać go do kompatybilnego z nim urządzenia.
+ <a href='http://wiki.opencaching.pl/index.php/Wherigo_czyli_Scenariusze_WIGO'>Więcej informacji</a>.
+ </desc>
+ <name lang="de">Whereigo Cache</name>
+ </attr>
+
+ <attr okapi_attr_id="letterbox" categories="de-cache-types" form="is / is not">
+ <opencaching site_url="http://opencaching.pl/" id="56" />
+ <opencaching site_url="http://opencaching.de/" id="8" />
+ <name lang="en">Letterbox Cache</name>
+ <desc lang="en">
+ There is a stamp in the cache for stamping your personal logbook, and the
+ cache’s logbook will be stamped with your personal stamp. Take care not
+ to mix up stamps and to leave the cache’s stamp in the cache!
+ </desc>
+ <name lang="pl">Skrzynka typu Letterbox</name>
+ <desc lang="pl">
+ W skrzynce znajduje się pieczątka, której nie można zabrać ze sobą.
+ Możesz jej użyć do ostemplowania swojego osobistego dziennika.
+ Logbook skrzynki powinien z kolei zostać ostemplowany Twoją własną
+ pieczątką.
+ <a href='http://wiki.opencaching.pl/index.php/Letterboxing'>Więcej informacji</a>.
+ </desc>
+ <name lang="de">Letterbox (benötigt Stempel)</name>
+ <desc lang="de">
+ In dem Behälter vor Ort befindet sich ein Stempel, mit dem man sein
+ persönliches Logbuch abstempeln kann. Das Logbuch im Geocache wird
+ ebenfalls mit einem persönlichen Stempel signiert. Bitte achte unbedingt
+ darauf, dass du den Stempel aus dem Geocache nicht mitnimmst oder tauschst!
+ <a href='http://wiki.opencaching.de/index.php/Letterboxing'>Weitere Informationen</a>.
+ </desc>
+ <name lang="es">Letterbox (necesita un estampador)</name>
+ <desc lang="es">
+ Hay un sello en el cache para estamparlo en su libro de registro personal,
+ y el libro de registro del cache será sellada con su sello personal.
+ ¡Tenga cuidado de no mezclar los sellos!
+ </desc>
+ <name lang="it">Letterbox (richiede un timbro)</name>
+ <desc lang="it">
+ C'è un timbro nella cache per timbrare il tuo quaderno personale,
+ e il log della cache verrà timbrato con il tuo timbro personale.
+ Fate attenzione a non confondere i timbri e a lasciare il timbro della
+ cache nella cache!
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="geohotel" categories="de-cache-types" form="is / is not">
+ <opencaching site_url="http://opencaching.pl/" id="43" />
+ <name lang="en">GeoHotel</name>
+ <desc lang="en">
+ Primary purpose of the "GeoHotel" caches is to exchange trackables
+ (TravelBugs, GeoKretys, etc.).
+ </desc>
+ <name lang="pl">GeoHotel</name>
+ <desc lang="pl">
+ Atrybut ten oznacza skrzynki których głównym celem jest lokowanie
+ w tej skrzynce różnych wędrujących rzeczy np GeoKrety, GeoLutins,
+ GeoFish itp.
+ </desc>
+ <name lang="de">GeoHotel</name>
+ </attr>
+
+ <attr okapi_attr_id="magnet" categories="de-cache-types" form="is / is not">
+ <opencaching site_url="http://opencaching.pl/" id="49" />
+ <name lang="en">Magnetic cache</name>
+ <desc lang="en">
+ This geocache is attached with a magnet.
+ </desc>
+ <name lang="pl">Przyczepiona magnesem</name>
+ <desc lang="pl">
+ Skrzynka zawiera magnes i przymocowana jest za jego pomocą.
+ </desc>
+ <name lang="de">magnetischer Cache</name>
+ </attr>
+
+ <attr okapi_attr_id="audiofile" categories="de-cache-types" form="if / if not">
+ <opencaching site_url="http://opencaching.pl/" id="50" />
+ <name lang="en">Description contains an audio file</name>
+ <desc lang="pl">
+ In order to find this cache, you must listen to an audio recording,
+ which is attached to the cache description.
+ </desc>
+ <name lang="pl">Opis zawiera plik audio</name>
+ <desc lang="pl">
+ Aby odnaleźć skrzynkę, należy odsłuchać plik dźwiękowy. Może on
+ zawierać zakodowane informacje, dźwięki otoczenia, opis dotarcia
+ do skrzynki.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="offset" categories="de-cache-types" form="is / is not">
+ <opencaching site_url="http://opencaching.pl/" id="51" />
+ <name lang="en">Offset cache</name>
+ <desc lang="pl">
+ A specific type of a MultiCache. The coordinates point to a starting
+ point. The description contains simple instructions to follow
+ once you are in the starting point (usually, an azimuth and a
+ distance).
+ </desc>
+ <name lang="pl">Offset cache</name>
+ <desc lang="pl">
+ Szczególny przypadek skrzynki typu multicache, składający się z
+ punktu startowego (określonego współrzędnymi) oraz jasnych
+ informacjami o sposobie dotarcia do finału (np. azymutu i
+ odległości).
+ </desc>
+ <name lang="de">Peilungscache</name>
+ </attr>
+
+ <attr okapi_attr_id="chirp" categories="de-cache-types" form="contains / does not contain">
+ <groundspeak id="60" inc="true" name="Wireless Beacon" />
+ <opencaching site_url="http://opencaching.pl/" id="52" />
+ <name lang="en">Garmin's wireless beacon</name>
+ <desc lang="en">
+ Contains Garmin's wireless chirp beacon.
+ </desc>
+ <name lang="pl">Beacon - Garmin Chirp</name>
+ <desc lang="pl">
+ Skrzynka zawiera Beacon Garmin chirp.
+ </desc>
+ <name lang="de">Funksignal – Garmin Chirp</name>
+ </attr>
+
+ <attr okapi_attr_id="usb" categories="de-cache-types" form="is / is not">
+ <opencaching site_url="http://opencaching.pl/" id="53" />
+ <name lang="en">Dead Drop USB cache</name>
+ <desc lang="pl">
+ The cache consists of an unmovable USB mass storage device, e.g.
+ fixed into a wall, curb etc. The device contains readme.txt file
+ with cache description and a logbook.txt file where you can log
+ your visit.
+ </desc>
+ <name lang="pl">Dead Drop USB skrzynka</name>
+ <desc lang="pl">
+ Skrzynka typu USB Dead Drop. Pen-drive przymocowany lub wmurowany
+ w ścianę, budynek, krawiężnik itp. Aby zalogować znalezienie, należy
+ wpisać się do pliku logbook.txt znajdującego się w pamięci urządzenia.
+ <a href='http://wiki.opencaching.pl/index.php/Skrzynka_Dead_Drop'>Wiecej informacji</a>.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="moving" categories="de-cache-types" form="if / if not">
+ <!-- This looks redundant to the 'moving cache' type, but it may also be a
+ moving final of a multi- or quiz cache. -->
+ <opencaching site_url="http://opencaching.de/" id="31" />
+ <name lang="en">Has a moving target</name>
+ <desc lang="en">
+ This geocache is moving around. For example, the owner might regularly
+ move the cache from one place to another, or the finders will do this
+ task and post new coordinates in their log entries. The owner must
+ update coordinates in the cache description after each move.
+ </desc>
+ <!-- TODO: "Has a" was added. -->
+ <name lang="de">bewegliches Ziel</name>
+ <desc lang="de">
+ Der Geocache verändert seine Position und ist deshalb nicht immer am
+ gleichen Ort zu finden. Es gibt Varianten, bei denen der Geocache-Besitzer
+ den Geocache regelmäßig an anderen Orten versteckt, oder der Finder den
+ Geocache an einem neuen Ort versteckt. Danach muss der Besitzer jeweils
+ die Beschreibung aktualisieren.
+ </desc>
+ <name lang="es">Objetivo en movimiento</name>
+ <desc lang="es">
+ Este geocache está en movimiento. Por ejemplo, el propietario podía mover
+ la caché periódicamente de un lugar a otro, o un geobuscador podría hacer
+ esto y ofrecer nuevos detalles en su registro. El propietario debe
+ actualizar las coordenadas en la descripción del cache después de cada
+ movimiento.
+ </desc>
+ <name lang="it">Oggetto in movimento</name>
+ <desc lang="it">
+ Questa geocache è in muovimento. Per esempio, il proprietario potrebbe
+ spostare regolarmente la cache da un luogo ad un altro, o i cacher
+ potrebbero eseguire questa operazione e indicare nuove coordinate nel
+ loro log. Il proprietario deve aggiornare le coordinate nella descrizione
+ della cache dopo ogni mossa.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="webcam" categories="de-cache-types" form="is / is not">
+ <opencaching site_url="http://opencaching.de/" id="32" />
+ <name lang="en">Webcam Cache</name>
+ <desc lang="en">
+ There is a webcam at the target location. You must record a webcam
+ picture of your visit and include it in your 'found' log entry. There
+ may be additional requirements like a geocaching banner on the photo.
+ The webcam’s address is included in the cache description.
+ </desc>
+ <name lang="de">Webcam Cache</name>
+ <desc lang="de">
+ Am Ziel befindet sich eine Webcam, und für einen Fund muss man das Bild
+ der Webcam von sich selbst aufnehmen, um nachzuweisen, dass man vor Ort
+ war. Manche Webcam-Caches setzen auch weitere Bedingungen, z.B. einen
+ Geocaching-Banner auf dem Bild. Die Webadresse der Webcam ist in der
+ Beschreibung angegeben.
+ </desc>
+ <name lang="es">Webcam Cache</name>
+ <desc lang="es">
+ Hay una webcam en el lugar de destino. necesidad a alguien para registrar
+ con un pantallazo de la imagen de la webcam de su visita e incluirlo en
+ el registro. Puede haber requisitos adicionales como un signo de
+ geocaching en la imagen. La dirección de la webcam está incluido en la
+ descripción de la cache.
+ </desc>
+ <name lang="it">Webcam Cache</name>
+ <desc lang="it">
+ C'è una webcam nella posizione di destinazione. E' necessario registrare
+ una foto con la webcam della vostra visita e includerla nel log. Ci
+ possono essere requisiti addizionali come un segnale di geocaching sulla
+ foto. L'indirizzo della webcam è incluso nella descrizione della cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="other-type" categories="de-cache-types">
+ <!--
+ This looks redundant to the "unknown type" cache type, but
+ it is used vor special variants of basic cache types - e.g. a
+ multicache where you won't just find a box at the final but have
+ to meet an additional challenge there.
+ -->
+ <opencaching site_url="http://opencaching.de/" id="57" />
+ <name lang="en">Other cache type</name>
+ <desc lang="en">
+ This is none of the standard, pre-defined types of cache.
+ Use this attribute for special, unusual caches.
+ </desc>
+ <name lang="de">sonstiger Cachetyp</name>
+ <desc lang="de">
+ Dieser Cache passt in keine der üblichen Kategorien von Caches (Cachearten).
+ </desc>
+ <name lang="es">Otro tipo de cache</name>
+ <desc lang="es">
+ Este es un cache que no pertenece a ninguna de las categorías predefinicas
+ - estándar.
+ </desc>
+ <name lang="it">Altro tipo di cache</name>
+ <desc lang="it">
+ Questa è una cache che non appartiene a nessuna delle categorie standard
+ perdefinite. Usa questo attributo per cache speciali e inusuali.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="investigation" categories="de-preconditions">
+ <opencaching site_url="http://opencaching.de/" id="54" />
+ <name lang="en">Investigation required</name>
+ <desc lang="en">
+ You must investigate additional information before you can seek this cache.
+ </desc>
+ <name lang="de">Recherche</name>
+ <desc lang="de">
+ Für diesen Cache muss vorab nach Informationen gesucht werden.
+ </desc>
+ <name lang="es">Investigación</name>
+ <desc lang="es">
+ Necesitas encontrar más información antes de poder buscar este cache.
+ </desc>
+ <name lang="it">Ricerca</name>
+ <desc lang="it">
+ È necessario trovare ulteriori informazioni prima di poter cercare
+ questa cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="puzzle" categories="de-preconditions">
+ <groundspeak id="47" inc="true" name="Field puzzle" />
+ <opencaching site_url="http://opencaching.de/" id="55" />
+ <name lang="en">Puzzle / Mystery</name>
+ <desc lang="en">
+ Puzzles or mysteries have to be solved before or while seeking this cache.
+ </desc>
+ <name lang="de">Rätsel</name>
+ <desc lang="de">
+ Bei diesem Cache sind als Vorarbeit oder während der Suche Rütsel zu lösen.
+ </desc>
+ <name lang="es">Puzzle / Misterio</name>
+ <desc lang="es">
+ Misterio o Puzzle para ser resuelto antes o durante la búsqueda de este cache.
+ </desc>
+ <name lang="it">Puzzle / Mystery</name>
+ <desc lang="it">
+ Puzzle o Mystery devono essere risolti prima o durante la ricerca di
+ questa cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="maths" categories="de-preconditions">
+ <opencaching site_url="http://opencaching.de/" id="56" />
+ <name lang="en">Arithmetical problem</name>
+ <desc lang="en">
+ Before or while seeking this cache, arithmetical problems must be solved
+ which go beyond very basic calculations.
+ </desc>
+ <name lang="de">Rechenaufgabe</name>
+ <desc lang="de">
+ Es müssen vorab oder während der Suche Rechenaufgaben gelöst werden, die
+ über das kleine Geocacher 1x1 hinausgehen. zum Beispiel
+ Mittelpunktberechnungen oder Peilungen.
+ </desc>
+ <name lang="es">Problema matemático</name>
+ <desc lang="es">
+ Antes o durante la búsqueda de este cache, resolver problemas matemáticos
+ sencillos más difícil a los cálculos de la base.
+ </desc>
+ <name lang="it">Problema matematico</name>
+ <desc lang="it">
+ Prima o durante la ricerca di questa cache, devono essere risolti problemi
+ matematici più difficili di semplici calcoli base.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="ask-owner" categories="de-preconditions">
+ <opencaching site_url="http://opencaching.de/" id="58" />
+ <name lang="en">Ask owner for start conditions</name>
+ <desc lang="en">
+ Before doing this cache, you must ask the owner for the starting conditions.
+ E.g. the cache may be linked to certain events at varying dates.
+ </desc>
+ <name lang="de">Startbedingungen beim Owner erfragen</name>
+ <desc lang="de">
+ Bei diesem Cache ist es nötig, sich vor dem Angehen des Caches beim
+ Eigentümer über die Bedingungen zum Angehen zu informieren.
+ </desc>
+ <name lang="es">Ask owner for start conditions</name>
+ <desc lang="es">
+ Pregunte a los propietarios por las condiciones iniciales
+ </desc>
+ <name lang="it">Ask owner for start conditions</name>
+ <desc lang="it">
+ Chiedere al proprietario per le condizioni di partenza
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="wheelchair" categories="de-accessibility">
+ <groundspeak id="24" inc="true" name="Wheelchair accessible" />
+ <opencaching site_url="http://opencaching.pl/" id="44" />
+ <name lang="en">Wheelchair accessible</name>
+ <desc lang="en">
+ The cache is hidden in a way which makes it possible to be found
+ when moving on a wheelchair.
+ </desc>
+ <name lang="pl">Dostępna dla niepełnosprawnych</name>
+ <desc lang="pl">
+ Skrzynka ukryta w sposób umożliwiający jej znalezienie osobom
+ poruszającym się na wózku inwalidzkim. Dotyczy to zarówno
+ lokalizacji (np. dojazd alejką pod samą skrzynkę), jak i sposobu
+ ukrycia.
+ </desc>
+ <name lang="de">rollstuhltauglich</name>
+ </attr>
+
+ <attr okapi_attr_id="drivein" categories="de-accessibility">
+ <groundspeak id="53" inc="true" name="Park and grab" />
+ <opencaching site_url="http://opencaching.de/" id="24" />
+ <name lang="en">Near the parking area</name>
+ <desc lang="en">
+ The geocache is located close to a parking area, only a few steps away.
+ </desc>
+ <name lang="de">nahe beim Auto</name>
+ <desc lang="de">
+ Der Parkplatz befindet sich in unmittelbarer Nähe zum Geocache.
+ Es sind nicht mehr als einige Schritte notwendig um den Geocache zu finden.
+ </desc>
+ <name lang="es">Cerca de un Parking</name>
+ <desc lang="es">
+ El geocache se encuentra cerca de un parking, a poca distancia.
+ </desc>
+ <name lang="it">Vicino all'area di parcheggio</name>
+ <desc lang="it">
+ La geocache è posta vicino ad un'area di parcheggio, solo poco distante.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="walk-only" categories="de-accessibility">
+ <opencaching site_url="http://opencaching.pl/" id="84" />
+ <name lang="en">Access only by walk</name>
+ <desc lang="en">
+ The cache is accessible by walk only.
+ </desc>
+ <name lang="pl">Dostępna tylko pieszo</name>
+ <desc lang="pl">
+ Skrzynka dostępna tylko pieszo.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="hike" categories="de-accessibility">
+ <groundspeak id="9" inc="true" name="Significant Hike" />
+ <opencaching site_url="http://opencaching.de/" id="25" />
+ <name lang="en">Long walk</name>
+ <desc lang="en">
+ This cache requires a long walk - more than 5 km round trip. In the
+ mountains and other steep areas, the distance for a 'long walk' may be
+ shorter. Walking shoes and appropriate equipment are recommended.
+ </desc>
+ <name lang="de">längere Wanderung</name>
+ <desc lang="de">
+ Bei diesem Cache erwartet euch eine Wanderung von mehr als 5 Kilometer,
+ vom Ausgangspunkt bis zum Cache und wieder zurück. Im Gebirge und bei
+ entsprechenden Steigungen kann das Attribut auch bei kürzeren Wegstrecken
+ gesetzt sein. Gute Wanderschuhe und entsprechende Ausrüstung empfehlen sich.
+ </desc>
+ <name lang="es">Larga caminata</name>
+ <desc lang="es">
+ Esta cache requiere una larga caminata - más de 5 kilometros de ida y
+ vuelta. En las montañas escarpadas o en otras áreas. Recomendados calzado
+ para caminar y equipo adecuado.
+ </desc>
+ <name lang="it">Lunga camminata</name>
+ <desc lang="it">
+ Questa cache richiede una lunga camminata - più di 5 km tra andata e
+ ritorno. In montagna o in altre aree ripide, la distanza per una cache
+ del genere può essere minore. Sono raccomandati scarpe da escursione ed
+ equipaggiamento adeguato.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="wading" categories="de-accessibility">
+ <groundspeak id="11" inc="true" name="May require wading" />
+ <opencaching site_url="http://opencaching.de/" id="26" />
+ <name lang="en">Swamp, marsh or wading</name>
+ <desc lang="en">
+ This cache requires passing swampy or marshy ground our wading throuh
+ shallow water. Wear appropriate clothes. After rainfall, the terrain
+ may be very demanding or not passable at all.
+ </desc>
+ <name lang="de">sumpfig/matschiges Gelände / waten</name>
+ <desc lang="de">
+ Bei diesem Cache geht es durch sumpfiges oder matschiges Gelände oder
+ es muss durch flaches Wasser gewatet werden. Entsprechende Kleidung
+ wird empfohlen. Nach Regenfällen kann das Gelände wesentlich schwerer
+ oder überhaupt nicht begehbar sein.
+ </desc>
+ <!-- TODO: add 'wading' to Spanish translation -->
+ <name lang="es">Pantano / terreno fangoso</name>
+ <desc lang="es">
+ Esta cache requiere la superación de pantanos. Usar ropa apropiada.
+ Después de la lluvia, el suelo puede ser difícil o no factible.
+ </desc>
+ <!-- TODO: add 'wading' to Italian translation -->
+ <name lang="it">Palude o marcita</name>
+ <desc lang="it">
+ Questa cache richiede il superamento di terreno paludoso o
+ acquitrinoso. Indossare un abbigliamento adeguato. Dopo la pioggia,
+ il terreno può essere molto impegnativo o non praticabile a tutti.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="steep" categories="de-accessibility">
+ <opencaching site_url="http://opencaching.de/" id="27" />
+ <name lang="en">Hilly area</name>
+ <desc lang="en">
+ One or more ascents lie between you and the cache.
+ </desc>
+ <name lang="de">hügeliges Gelände</name>
+ <desc lang="de">
+ Auf dem Weg zum Geocache bzw. während der Cachesuche sind eine oder
+ mehrere Steigungen zu überwinden.
+ </desc>
+ <name lang="es">Terreno montañoso</name>
+ <desc lang="es">
+ Una o más pendientes para acceder al cache.
+ </desc>
+ <name lang="it">Area collinare</name>
+ <desc lang="it">
+ Una o più salite si trovano tra voi e la cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="climbing" categories="de-accessibility">
+ <groundspeak id="10" inc="true" name="Difficult climbing" />
+ <opencaching site_url="http://opencaching.de/" id="28" />
+ <name lang="en">Some climbing (no gear needed)</name>
+ <desc lang="en">
+ This cache requires some climbing and you may have to use your hands,
+ but you won’t need climbing gear. Be very careful during rainy weather
+ or before thunderstorms!
+ </desc>
+ <name lang="de">leichtes Klettern (ohne Ausrüstung)</name>
+ <desc lang="de">
+ Während der Cachesuche ist leichtes Klettern notwendig, bei dem man sich
+ z.B. mit den Händen festhalten muss. Gute Trittsicherheit und
+ Schwindelfreiheit empfehlen sich. Es ist jedoch keine Spezialausrüstung
+ notwendig wie z.B. Sicherungsseil, Klettersteigset oder Steigeisen.
+ Besonders bei feuchter Witterung oder vor Gewittern sollte man mit der
+ entsprechenden Vorsicht handeln.
+ </desc>
+ <name lang="es">fácil de subir (sin equipo)</name>
+ <desc lang="es">
+ Esta cache requiere un poco de escalada y puede ser necesario usar las
+ manos, pero no es necesario material de montaña. ¡Tenga mucho cuidado
+ durante la temporada de lluvias.!
+ </desc>
+ <name lang="it">Arrampicata (attrezzatura non necessaria)</name>
+ <desc lang="it">
+ Questa cache richiede un po' di arrampicata e potrebbe essere necessario
+ usare le mani, ma non c'è bisogno di attrezzatura da arrampicata.
+ Prestare molta attenzione durante la stagione delle piogge o prima dei
+ temporali!
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="swimming" categories="de-accessibility">
+ <groundspeak id="12" inc="true" name="May require swimming" />
+ <opencaching site_url="http://opencaching.de/" id="29" />
+ <name lang="en">Swimming required</name>
+ <desc lang="en">
+ This cache requires crossing a river or a lake. The water can be steep.
+ </desc>
+ <name lang="de">Schwimmen erforderlich</name>
+ <desc lang="de">
+ Auf dem Weg zum Geocache muss ein Fluß oder See überquert werden.
+ Das Wasser ist tief genug um zu schwimmen. Je nach Örtlichkeit kann auch
+ ein Schlauchboot, Kajak oder ähnliches verwendet werden (näheres ist
+ in der Beschreibung zum Geocache zu finden). Die Entfernung ist aber ohne
+ besondere Ausdauer noch zu schwimmen.
+ </desc>
+ <name lang="es">Requiere nadar</name>
+ <desc lang="es">
+ Esta cache requiere cruzar un río o un lago. El agua es lo suficientemente
+ profundo para nadar. Puede utilizar un barco, pero la distancia es lo
+ suficientemente corto como para ser asequible para un nadador.
+ </desc>
+ <name lang="it">Nuoto necessario</name>
+ <desc lang="it">
+ Questa cache richiede l'attraversamento di un fiume o un lago. L'acqua è
+ abbastanza profonda per nuotare. È possibile utilizzare una barca, ma la
+ distanza è abbastanza breve per essere alla portata di un nuotatore medio.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="fee" categories="de-accessibility">
+ <groundspeak id="2" inc="true" name="Access or parking fee" />
+ <opencaching site_url="http://opencaching.de/" id="36" />
+ <name lang="en">Access or parking fee</name>
+ <desc lang="en">
+ You must pay an access or parking fee to access this cache.
+ </desc>
+ <name lang="de">Zugangs- bzw. Parkentgelt</name>
+ <desc lang="de">
+ Um zum Cache zu gelangen, müsst ihr entweder einen Eintritt oder eine
+ Parkgebühr bezahlen.
+ </desc>
+ <name lang="es">Acceso o parking pagando</name>
+ <desc lang="es">
+ Deberas pagar un acceso o estacionamiento para acceder a esta cache.
+ </desc>
+ <name lang="it">Tassa di ingresso o di parcheggio</name>
+ <desc lang="it">
+ Devi pagare un accesso o parcheggio a pagamento per accedere a questa cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="bike" categories="de-accessibility">
+ <groundspeak id="32" inc="true" name="Bicycles" />
+ <opencaching site_url="http://opencaching.pl/" id="85" />
+ <name lang="en">Bikes allowed</name>
+ <desc lang="en">
+ You can reach the cache by bike.
+ </desc>
+ <name lang="pl">Dostępna rowerem</name>
+ <desc lang="pl">
+ Można dojechać do skrzynki rowerem.
+ </desc>
+ <desc lang="de">Fahrräder erlaubt</desc>
+ </attr>
+
+ <attr okapi_attr_id="nature" categories="de-location">
+ <opencaching site_url="http://opencaching.pl/" id="60" />
+ <name lang="en">Hidden in natural surroundings (forests, mountains, etc.)</name> <!-- i.e. not in a city? -->
+ <desc lang="en">
+ The cache is hidden in a remote and quick place - a forest, wild
+ meadow, a swap, etc.
+ </desc>
+ <name lang="pl">Umiejscowiona na łonie natury (lasy, góry, itp.)</name>
+ <desc lang="pl">
+ Umiejscowiona na łonie natury, z dala od cywilizacji - las, dzika
+ łąka, mokradła.
+ </desc>
+ <desc lang="de">in freier Natur versteckt</desc>
+ </attr>
+
+ <attr okapi_attr_id="historic" categories="de-location">
+ <opencaching site_url="http://opencaching.pl/" id="61" />
+ <name lang="en">Historic site</name>
+ <desc lang="en">
+ The cache is hidden near a historic site - a castle, battleplace,
+ cementary, old bunkers, etc.
+ </desc>
+ <name lang="pl">Miejsce historyczne</name>
+ <desc lang="pl">
+ W sąsiedztwie miejsca historycznego - zamku, pałacu, pola bitwy,
+ cmentarza, ale także fortów czy bunkrów.
+ </desc>
+ <desc lang="de">historischer Ort</desc>
+ </attr>
+
+ <attr okapi_attr_id="poi" categories="de-location">
+ <opencaching site_url="http://opencaching.de/" id="30" />
+ <name lang="en">Point of interest</name>
+ <desc lang="en">
+ There is a point of interest at the cache, like a nice scenic view
+ or a larger castle ruin. This place is worth visiting it even
+ without a geocache nearby.
+ </desc>
+ <name lang="de">interessanter Ort</name>
+ <desc lang="de">
+ Der Geocache ist in unmittelbarer Nähe zu einer Sehenswürdigkeit
+ versteckt. Das kann ein z.B. schüner Aussichtspunkt oder eine größere
+ Burgruine sein. Ein Besuch würde sich auch ohne besonderen Anlass
+ (den Geocache) lohnen.
+ </desc>
+ <name lang="es">Punto de interes</name>
+ <desc lang="es">
+ Hay un monumento cerca del cache, como un paisaje hermoso o un castillo
+ en ruinas. Este lugar es digno de visitar, incluso sin un geocache cerca.
+ </desc>
+ <name lang="it">Punto di interesse</name>
+ <desc lang="it">
+ C'è un punto di interesse alla cache, come un bel panorama o di un
+ castello in rovina. Questo luogo merita una visita anche senza una
+ geocache vicina.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="indoor" categories="de-location">
+ <opencaching site_url="http://opencaching.de/" id="33" />
+ <name lang="en">Hidden wihin enclosed rooms (caves, buildings etc.)</name>
+ <desc lang="en">
+ This geocache is not hidden in the open air, but within a building,
+ a cave or similar.
+ </desc>
+ <name lang="de">in geschlossenen Räumen (Höhle, Gebäude, etc.)</name>
+ <desc lang="de">
+ Das Ziel des Geocaches liegt nicht im Freien, sondern zum Beispiel in
+ einem Gebäude oder einer Höhle.
+ </desc>
+ <name lang="es">en espacios confinados (cuevas, edificios, etc)</name>
+ <desc lang="es">
+ Este geocache no está al aire libre, esta oculto dentro de un edificio,
+ una cueva o similares.
+ </desc>
+ <name lang="it">All'interno di stanze chiuse (caverne, edifici, ecc.)</name>
+ <desc lang="it">
+ Questa geocache non è nascosta all'aria aperta ma all'interno di un
+ edificio, di una grotta o simili.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="submerged" categories="de-location">
+ <opencaching site_url="http://opencaching.de/" id="34" />
+ <name lang="en">Hidden under water</name>
+ <desc lang="en">
+ This cache or one of the stages is placed underwater.
+ You will get wet when doing this cache.
+ </desc>
+ <name lang="de">Im Wasser versteckt</name>
+ <desc lang="de">
+ Der Geocache oder eine der Stationen ist im Wasser versteckt. Um die
+ Aufgabe zu lösen muss man ggf. das Wasser betreten, schwimmen oder tauchen.
+ </desc>
+ <name lang="es">En el agua</name>
+ <!-- TODO: update Spanish translation, English and German descriptions have slightly changed -->
+ <desc lang="es">
+ Esta cache o una de sus etapas se encuentran bajo el agua. Usted debe
+ entrar en el agua, nadar o zambullirse.
+ </desc>
+ <name lang="it">Nell'acqua</name>
+ <!-- TODO: update Italian translation, English and German descriptions have slightly changed -->
+ <desc lang="it">
+ Questa cache o uno dei suoi stadi sono posizionati sott'acqua. Devi
+ entrare in acqua, nuotare o fare una immersione.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="parking" categories="de-facilities">
+ <groundspeak id="25" inc="true" name="Parking available" />
+ <opencaching site_url="http://opencaching.de/" id="18" />
+ <name lang="en">Parking area nearby</name>
+ <desc lang="en">
+ A nearby parking area is situated as starting point for doing this cache.
+ </desc>
+ <name lang="de">Parkplatz in der Nähe</name>
+ <desc lang="de">
+ Es gibt in der Nähe einen Parklplatz, der sich als Startpunkt für die
+ Cachesuche eignet.
+ </desc>
+ <name lang="es">Parking cercano</name>
+ <desc lang="es">
+ Una zona de aparcamiento se encuentra cerca del punto de partida de
+ este cache.
+ </desc>
+ <name lang="it">Parcheggio nei pressi</name>
+ <desc lang="it">
+ Una area di parcheggio è situata nei pressi del punto di partenza di
+ questa cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="public-transport" categories="de-facilities">
+ <groundspeak id="26" inc="true" name="Public transportation" />
+ <opencaching site_url="http://opencaching.de/" id="19" />
+ <name lang="en">Public transportation</name>
+ <desc lang="en">
+ This cache is located outside of urban areas and has a public
+ transport station nearby.
+ </desc>
+ <name lang="de">erreichbar mit ÖVM</name>
+ <desc lang="de">
+ Dieser Cache lässt sich mit Hilfe von öffentlichen Verkehrsmitteln erreichen
+ und liegt außerhalb von Städten.
+ </desc>
+ <name lang="es">Transporte Público</name>
+ <desc lang="es">
+ Este cache se encuentra también fuera de las zonas urbanas y una
+ estación de transporte público.
+ </desc>
+ <name lang="it">Trasporto pubblico</name>
+ <desc lang="it">
+ Questa cache è situata al difuori di aree urbane e ha una stazione di
+ trasporto pubblico nelle vicinanze.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="drinking-water" categories="de-facilities">
+ <groundspeak id="27" inc="true" name="Drinking water nearby" />
+ <opencaching site_url="http://opencaching.de/" id="20" />
+ <name lang="en">Drinking water nearby</name>
+ <desc lang="en">
+ There is drinking water along the trail or near the cache. This may be
+ useful especially especially when doing event caches, longer hikes or
+ caches at probably dirty locations.
+ </desc>
+ <name lang="de">Trinkwasser in der Nähe</name>
+ <desc lang="de">
+ Während der Cachetour oder in der Nähe des Geocaches ist Trinkwasser
+ verfügbar. Besonders bei Event-Caches, längeren Multicaches und bei
+ Geocaches wo man vermutlich schmutzig wird kann dies hilfreich sein.
+ </desc>
+ <name lang="es">Agua potable en las cercanias</name>
+ <desc lang="es">
+ Hay agua potable a lo largo de la ruta o cerca de la cache. Este
+ atributo es especialmente útil en la planificación de Eventos,
+ o caches con viajes largos a lugares como las cuevas o minas
+ probablemente esté sucio.
+ </desc>
+ <name lang="it">Acqua potabile nei pressi</name>
+ <desc lang="it">
+ C'è acqua potabile lungo il percorso o nelle vicinanze della cache.
+ Questo attributo è utile soprattutto nella pianificazione di cache
+ evento, di lunghe escursioni o di cache in luoghi probabilmente
+ sporchi come le grotte o le miniere.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="restrooms" categories="de-facilities">
+ <groundspeak id="28" inc="true" name="Public restrooms nearby" />
+ <opencaching site_url="http://opencaching.de/" id="21" />
+ <name lang="en">Public restrooms nearby</name>
+ <desc lang="en">
+ There are public restrooms along the way or near the cache.
+ </desc>
+ <name lang="de">öffentliche Toilette in der Nähe</name>
+ <desc lang="de">
+ Während der Cachetour oder in der Nähe des Geocaches ist eine öffentliche
+ Toilette verfügbar.
+ </desc>
+ <name lang="es">Aseos públicos cercanos</name>
+ <desc lang="es">
+ Hay baños públicos a lo largo de la carretera o en las proximidades
+ del cache.
+ </desc>
+ <name lang="it">Bagni pubblici nei pressi</name>
+ <desc lang="it">
+ Ci sono WC pubblici lungo la strada o nelle vicinanze della cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="phone" categories="de-facilities">
+ <groundspeak id="29" inc="true" name="Telephone nearby" />
+ <opencaching site_url="http://opencaching.de/" id="22" />
+ <name lang="en">Public phone nearby</name>
+ <desc lang="en">
+ There is a public phone along the way or near the cache.
+ </desc>
+ <name lang="de">Telefon in der Nähe</name>
+ <desc lang="de">
+ Während der Cachetour oder in der Nähe des Geocaches gibt es ein
+ öffentliches Telefon.
+ </desc>
+ <name lang="es">Teléfono Público en las cercanias</name>
+ <desc lang="es">
+ Hay teléfonos públicos en la carretera o en las proximidades del cache.
+ </desc>
+ <name lang="it">Telefono pubblico nei pressi</name>
+ <desc lang="it">
+ Ci sono telefoni pubblici lungo la strada o nelle vicinanze della cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="first-aid" categories="de-facilities">
+ <opencaching site_url="http://opencaching.de/" id="23" />
+ <name lang="en">First aid available</name>
+ <desc lang="en">
+ There is a first aid station, call box, mountain rescue or similar
+ arrangement near the cache.
+ </desc>
+ <name lang="de">Erste Hilfe verfügbar</name>
+ <desc lang="de">
+ In der Nähe des Caches findet ihr eine Erste Hilfe-Station, Notrufsäule,
+ Bergwacht oder entsprechende Einrichtung.
+ </desc>
+ <name lang="es">Disponible socorro rapido</name>
+ <desc lang="es">
+ Hay un punto de socorro, un teléfono para pedir ayuda, un centro de
+ rescate de montaña o similar cerca del cache.
+ </desc>
+ <name lang="it">Disponibile pronto soccorso</name>
+ <desc lang="it">
+ C'è un pronto soccorso, un telefono per chiamate di soccorso, un centro
+ di soccorso alpino o simili nelle vicinanze della cache.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="24-hours" categories="de-time-and-seasons">
+ <groundspeak id="13" inc="true" name="Available at all times" />
+ <opencaching site_url="http://opencaching.de/" id="38" />
+ <name lang="en">Available 24/7</name>
+ <desc lang="en">
+ This cache can be found at any time of day or week.
+ </desc>
+ <name lang="de">rund um die Uhr machbar</name>
+ <desc lang="de">
+ Dieser Cache ist jederzeit machbar, sowohl am Tage als auch in der Nacht.
+ </desc>
+ <name lang="es">Disponible las 24 horas</name>
+ <desc lang="es">
+ Esta cache se puede encontrar tanto de día como de noche.
+ </desc>
+ <name lang="it">Disponibile 24 ore</name>
+ <desc lang="it">
+ Questa cache può essere trovata sia di giorno che di notte.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="not-24-hours" categories="de-time-and-seasons">
+ <groundspeak id="13" inc="false" name="Available at all times" />
+ <opencaching site_url="http://opencaching.pl/" id="80" />
+ <opencaching site_url="http://opencaching.de/" id="39" />
+ <name lang="en">Not 24/7</name>
+ <desc lang="en">
+ This cache can only be done at certain times of day or week - see the cache
+ description for more details. For example, the cache may be placed in an
+ area with restricted opening hours.
+ </desc>
+ <name lang="pl">Dostępna w określonych godzinach</name>
+ <desc lang="pl">
+ Dostępna w określonych dniach, godzinach, często wstęp płatny.
+ Często będzie to muzeum lub skansen. Szczegółowe informacje o
+ dostępności powinny znajdować się w opisie skrzynki.
+ </desc>
+ <name lang="de">nur zu bestimmten Uhrzeiten</name>
+ <desc lang="de">
+ Dieser Cache lässt sich nur zu bestimmten Tageszeiten absolvieren.
+ Nähere Angaben sind in der Beschreibung des Caches zu finden.
+ </desc>
+ <name lang="es">Sólo disponible a ciertas horas</name>
+ <desc lang="es">
+ Esta cache se puede hacer solamente en ciertos momentos del día -
+ véase la descripción de caché para obtener más detalles.
+ </desc>
+ <name lang="it">Disponibile solo in certi orari</name>
+ <desc lang="it">
+ Questa cache può essere cercata solo a certe ore del giorno -
+ vedi la descrizione per ulteriori informazioni.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="daycache" categories="de-time-and-seasons">
+ <groundspeak id="14" inc="false" name="Recommended at night" />
+ <opencaching site_url="http://opencaching.de/" id="40" />
+ <name lang="en">Not recommended at night</name>
+ <desc lang="en">
+ Searching for this cache is not recommended by night. It might be
+ dangerous, or the cache may be hidden in an area where flashlights
+ may attract unwanted attention.
+ </desc>
+ <name lang="de">nur tagüber</name>
+ <desc lang="de">
+ Dieser Cache lässt sich nur tagsüber angehen, zum Beispiel weil das Gelände
+ gefährlich ist oder die Suche mit Taschenlampen in einem Wohngebiet negativ
+ auffallen würde.
+ </desc>
+ <name lang="es">solo por el día</name>
+ <desc lang="es">
+ Deberas encontrar este cache sólo durante el día. Por ejemplo, el área pued
+ ser peligroso y contienen rocas o abismos. O bien, el uso de linternas puede
+ ser imposible porque sería sospechoso en una zona residencial.
+ </desc>
+ <name lang="it">solo di giorno</name>
+ <desc lang="it">
+ Si dovrebbe cercare questa cache solamente durante il giorno. Ad esempio,
+ l'area può essere pericolosa e contenere scogliere o abissi. Oppure,
+ l'utilizzo di torce elettriche potrebbe essere impossibile perché
+ risulterebbe sospetto all'interno di una zona residenziale.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="night-recommended" categories="de-time-and-seasons">
+ <!--
+ GS has "night cache" (52) and "recommended at night" (14).
+ night cache = can normally ONLY be done at night, reflectors etc.
+ recommended at night = can well be done at night
+
+ On OCPL there is no distinction between these two. OCPL uses
+ "Recommended at night" attribute for "Night caches" too.
+ -->
+ <groundspeak id="14" inc="true" name="Recommended at night" />
+ <opencaching site_url="http://opencaching.pl/" id="91" />
+ <name lang="en">Recommended at night</name>
+ <desc lang="pl">
+ It is recommended to search for this cache by night. I.e. there
+ might be some light-reflecting surfaces involved which are usually
+ invisible during daylight.
+ </desc>
+ <name lang="pl">Zalecane szukanie nocą</name>
+ <desc lang="pl">
+ Aby znaleźć skrzynkę zalecane jest poszukiwanie jej nocą, ze
+ względu na miejsce ukrycia lub użyte elementy odblaskowe, których
+ oświetlenie umożliwia odnalezienie skrzynki.
+ </desc>
+ <name lang="de">am besten nachts findbar</name>
+ </attr>
+
+ <attr okapi_attr_id="nightcache" categories="de-time-and-seasons">
+ <!--
+ GS has "night cache" (52) and "recommended at night" (14).
+ night cache = can normally ONLY be done at night, reflectors etc.
+ recommended at night = can well be done at night
+ -->
+ <groundspeak id="52" inc="true" name="Night Cache" />
+ <opencaching site_url="http://opencaching.de/" id="1" />
+ <name lang="en">Only at night</name>
+ <desc lang="en">
+ This geocache can be found at night only - it is a so-called night cache.
+ There may be reflectors which have to be flashlighted and will point
+ to the hiding place, or other special night-caching mechanisms.
+ </desc>
+ <name lang="de">nur bei Nacht</name>
+ <desc lang="de">
+ Der Geocache kann nur bei Nacht gelöst werden und wird deshalb Nachtcache
+ genannt. Zum Beispiel mössen Reflektoren mit einer Taschenlampe
+ angeleuchtet werden, die dann den Weg zum Versteck zeigen.
+ </desc>
+ <name lang="es">Sólo por la noche</name>
+ <desc lang="es">
+ Esta cache se puede encontrar solamente por la noche - tienes que
+ considerar cache notturna. Puede haber placas reflectantes que
+ brillaran y te llevaran al cache, o otros mecanismo especiales para
+ caches nocturnos.
+ </desc>
+ <name lang="it">Solo di notte</name>
+ <desc lang="it">
+ Questa cache può essere trovata solo di notte - è una cosiddetta
+ cache notturna. Ci possono essere targhette riflettenti che devono
+ essere illuminate e ti conducono al nascondiglio, o altri speciali
+ meccanismi di caching notturno.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="all-seasons" categories="de-time-and-seasons">
+ <groundspeak id="62" inc="false" name="Seasonal access" />
+ <opencaching site_url="http://opencaching.de/" id="42" />
+ <name lang="en">All seasons</name>
+ <desc lang="en">
+ This cache can be found the whole year round, while difficulty may
+ depend on seasons.
+ </desc>
+ <name lang="de">ganzjähig zugänglich</name>
+ <desc lang="de">
+ Dieser Cache lässt sich während des gesamten Jahres finden, wobei je
+ nach Jahreszeit die Schwierigkeit bei der Suche schwanken kann.
+ </desc>
+ <name lang="es">Todas las temporadas</name>
+ <desc lang="es">
+ Esta cache se encuentrar durante todo el año, mientras que la dificultad
+ puede depender de las estaciones.
+ </desc>
+ <name lang="it">Tutte le stagioni</name>
+ <desc lang="it">
+ Questa cache si trova tutto l'anno, mentre la difficoltà può dipendere
+ dalle stagioni.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="not-all-seasons" categories="de-time-and-seasons">
+ <groundspeak id="62" inc="true" name="Seasonal access" />
+ <opencaching site_url="http://opencaching.de/" id="60" />
+ <name lang="en">Only available during specified seasons</name>
+ <desc lang="en">
+ This cache can be done at certain seasons only - see the cache
+ description for more details.
+ </desc>
+ <name lang="de">Nur zu bestimmten Zeiten im Jahr</name>
+ <desc lang="de">
+ Dieser Cache lässt sich nur zu bestimmten Zeite im Jahr absolvieren.
+ Näheres ist in der Cachebeschreibung angegeben.
+ </desc>
+ <name lang="es">Sólo disponible durante las estaciones especificadas</name>
+ <desc lang="es">
+ Esta cache se puede hacer en ciertas épocas del año solamente - vea la
+ descripción de cache para obtener más detalles.
+ </desc>
+ <name lang="it">Disponibile solo in certe stagioni</name>
+ <desc lang="it">
+ Questa cache può essere cercata solo in certe stagioni - vedi la
+ descrizione per ulteriori informazioni.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="np-season" categories="de-time-and-seasons">
+ <opencaching site_url="http://opencaching.de/" id="43" />
+ <name lang="en">Breeding season / protected nature</name>
+ <desc lang="en">
+ Don’t seek this cache during animal breeding season! See the cache
+ description on which time of year must be avoided. Also, pay
+ attention to the local terms and signs regarding nature protection.
+ </desc>
+ <name lang="de">Brutsaison / Naturschutz</name>
+ <desc lang="de">
+ Dieser Cache sollte in der Brutsaison nicht absolviert werden. In der
+ Beschreibung sollte angegeben sein, welche Jahreszeit davon betroffen ist.
+ Achte bitte auch auf die örtliche Beschilderung zum Naturschutz.
+ </desc>
+ <name lang="es">Temporada de reproducción / protección de la naturaleza</name>
+ <desc lang="es">
+ ¡No intente esta cache durante la temporada de cría de los animales!
+ Vvéase la descripción del cache de la época del año debe ser evitado.
+ Preste atención también a las condiciones o signos en cuanto al respeto
+ por la naturaleza.
+ </desc>
+ <name lang="it">Stagione di riproduzione / natura protetta</name>
+ <desc lang="it">
+ Non cercare questa cache durante il periodo riproduttivo degli animali!
+ Vedi descrizione della cache quale periodo dell'anno debba essere evitato.
+ Prestate anche attenzione alle condizioni o ai cartelli riguardo il
+ rispetto della natura.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="snow-proof" categories="de-time-and-seasons">
+ <groundspeak id="15" inc="true" name="Available during winter" />
+ <opencaching site_url="http://opencaching.de/" id="44" />
+ <name lang="en">Available during winter</name>
+ <desc lang="en">
+ This cache can be found even after heavy snowing. All stages and the
+ geocache are hidden in a snow-safe way: they will not be covered by
+ fallen snow, or ice, etc.
+ </desc>
+ <name lang="de">schneesicheres Versteck</name>
+ <desc lang="de">
+ Dieser Cache lässt sich auch nach starkem Schneefall suchen. Die einzelnen
+ Stationen und der Geocache sind so versteckt, dass sie nicht von Schnee
+ verdeckt werden, bzw. von Schneehaufen die durch Räumfahrzeuge entstehen.
+ </desc>
+ <name lang="es">Nieve en el escondite</name>
+ <desc lang="es">
+ Este cache también se puede encontrar después de fuertes nevadas. Todas
+ las fases y geocaches se esconde en lugares seguros para la caída de la
+ nieve, no será cubierto por acumulaciones de nieve.
+ </desc>
+ <name lang="it">Luogo a prova di neve</name>
+ <desc lang="it">
+ Questa cache può essere trovata anche dopo forti nevicate. Tutte le fasi
+ e la geocache sono nascosti in luoghi sicuri per la neve: non saranno
+ coperti da neve caduta né da cumuli di neve creati ad esempio da veicoli
+ spalaneve.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="lowwater" categories="de-time-and-seasons">
+ <opencaching site_url="http://opencaching.de/" id="41" />
+ <name lang="en">Not at high water level</name>
+ <desc lang="en">
+ This cache can be done only at low or normal water level. It is
+ inaccessible during flood.
+ </desc>
+ <name lang="de">nicht bei Hochwasser oder Flut</name>
+ <desc lang="de">
+ Der Geocache kann nur bei bei niedrigem oder normalem Wasserstand
+ bzw. bei Ebbe gesucht werden. Bei Hochwasser oder Flut ist er
+ unzugänglich.
+ </desc>
+ <!-- TODO: Spanish and Italian translations -->
+ </attr>
+
+ <attr okapi_attr_id="compass" categories="de-tools">
+ <opencaching site_url="http://opencaching.pl/" id="47" />
+ <opencaching site_url="http://opencaching.de/" id="47" />
+ <name lang="en">Compass required</name>
+ <desc lang="en">
+ A compass is required.
+ </desc>
+ <name lang="pl">Potrzebny kompas</name>
+ <desc lang="pl">
+ Kompas może okazać się niezbędny aby dotrzeć do wskazanego miejsca
+ skrzynki.
+ </desc>
+ <name lang="de">Kompass</name>
+ <desc lang="de">
+ Für diesen Cache braucht ihr einen funktionierenden Kompass für Peilungen
+ oder Orientierungen.
+ </desc>
+ <name lang="es">Brújula</name>
+ <desc lang="es">
+ Se necesita una brújula.
+ </desc>
+ <name lang="it">Bussola</name>
+ <desc lang="it">
+ E' necessaria una bussola.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="pen" categories="de-tools">
+ <opencaching site_url="http://opencaching.pl/" id="48" />
+ <name lang="en">Take something to write</name>
+ <desc lang="en">
+ There is no pencil in the cache. Take something to write with.
+ </desc>
+ <name lang="pl">Weź coś do pisania</name>
+ <desc lang="pl">
+ Skrzynka nie zawiera ołówka, weź ze sobą coś do pisania.
+ </desc>
+ <desc lang="de">Stift mitbringen</desc>
+ </attr>
+
+ <attr okapi_attr_id="digging" categories="de-tools">
+ <opencaching site_url="http://opencaching.pl/" id="81" />
+ <name lang="en">You may need a shovel</name>
+ <desc lang="en">
+ The cache may require more digging. A shovel might come in handy.
+ </desc>
+ <name lang="pl">Potrzebna łopatka</name>
+ <desc lang="pl">
+ Skrzynka jest zakopana w ziemi.
+ </desc>
+ <desc lang="de">Grabwerkzeug benötigt</desc>
+ </attr>
+
+ <attr okapi_attr_id="flashlight" categories="de-tools">
+ <groundspeak id="44" inc="true" name="Flashlight required" />
+ <opencaching site_url="http://opencaching.pl/" id="82" />
+ <opencaching site_url="http://opencaching.de/" id="48" />
+ <name lang="en">Flashlight required</name>
+ <desc lang="en">
+ You will need a flashlight to find this cache.
+ </desc>
+ <name lang="pl">Potrzebna latarka</name>
+ <desc lang="pl">
+ Przy poszukiwaniach tej skrzynki potrzebna jest latarka.
+ </desc>
+ <name lang="de">Taschenlampe</name>
+ <desc lang="de">
+ Um diesen Cache anzugehen, benötigt ihr eine funktionstüchtige
+ Taschenlampe. Denkt auch an Ersatzbatterien.
+ </desc>
+ <name lang="es">Linterna</name>
+ <desc lang="es">
+ Es necesario una linterna para encontrar este cache. ¡No se olvide de las
+ baterías de repuesto!
+ </desc>
+ <name lang="it">Lampada tascabile</name>
+ <desc lang="it">
+ E' necessaria una torcia portatile per trovare questa cache. Non
+ dimenticate le batterie di riserva!
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="climbing-gear" categories="de-tools">
+ <groundspeak id="3" inc="true" name="Climbing gear" />
+ <opencaching site_url="http://opencaching.de/" id="49" />
+ <name lang="en">Climbing gear required</name>
+ <desc lang="en">
+ For this cache, you will need climbing equipment and the knowledge
+ how to use it properly. If you are a beginner, don’t do it alone but
+ use the support of an experienced climber or mountaineer.
+ </desc>
+ <name lang="de">Kletterzeug</name>
+ <desc lang="de">
+ Um diesen Cache absolvieren zu können, benötigt ihr neben der normalen
+ Ausrüstung auch noch Kletterausrüstung, und entsprechendes Wissen um
+ deren Handhabung und ums Klettern. Laien sollten sich auf jeden Fall
+ von einem erfahrenen Kletterer oder Bergsteiger unterstützen lassen.
+ </desc>
+ <name lang="es">Equipo de escalada</name>
+ <desc lang="es">
+ Para este cache, tendrá que utilizar los equipos y saber cómo utilizarlo
+ correctamente. Si usted es un principiante, no lo haga solos, sino que
+ utiliza el apoyo de un experimentado escalador o alpinista.
+ </desc>
+ <name lang="it">Attrezzatura per arrampicata</name>
+ <desc lang="it">
+ Per questa cache, avrete bisogno di materiale da arrampicata e di saperlo
+ usare correttamente. Se sei un principiante, non farlo da solo, ma
+ utilizza il sostegno di uno scalatore esperto o un alpinista.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="cave-equipment" categories="de-tools">
+ <opencaching site_url="http://opencaching.de/" id="50" />
+ <name lang="en">Cave equipment required</name>
+ <desc lang="en">
+ This geocache is hidden in a cave, and you should use appropriate
+ equipment to access it. Beware: Even small caves may confront you with
+ unforeseen problems and dangers, like thunder storms (water!) or a
+ sprained ankle. Have advice first from cave-experienced people! Also
+ take care of protected nature; e.g. bat places must not be disturbed.
+ </desc>
+ <name lang="de">Höhlenzeug</name>
+ <desc lang="de">
+ Der Geocache ist in einer Höhle versteckt und man sollte entsprechende
+ Ausrüstung mitbringen. Vorsicht: Bereits kleinste Höhlensysteme können
+ bei unvorhergesehenen Problem z.B. Gewittern (Wasser!) oder einem
+ verstauchten Knöchel sehr gefährlich werden! Ihr solltet euch vorab
+ gründlich bei erfahreren Höhlengehern informieren. Beachtet auch den
+ Naturschutz – Fledermausquartiere dürfen nicht gestört werden!
+ </desc>
+ <name lang="es">Equipación para cuevas</name>
+ <desc lang="es">
+ Este geocache está escondido en una cueva, y se debe utilizar el equipo
+ adecuado para acceder a ella. Tenga en cuenta que incluso las pequeñas
+ cuevas pueden prever los problemas imprevistos y peligros, como durante
+ las tormentas o con un esguince de tobillo. ¡Acceda con personas
+ experimentadas en cuevas! También debe protegerse la naturaleza sobre
+ todo en esos lugares donde los murciélagos no deben ser molestados.
+ </desc>
+ <name lang="it">Attrezzatura per grotta</name>
+ <desc lang="it">
+ Questa geocache è nascosta in una grotta, e si dovrebbe utilizzare
+ attrezzature adeguate per accedervi. Attenzione: anche piccole grotte
+ possono prevedere problemi imprevisti e pericoli, come in caso di
+ temporali (acqua!) o una caviglia slogata. Consigliatevi prima con
+ persone che abbiano esperienza di grotte! Abbiate anche cura della
+ natura protetta, ad esempio dei luoghi dove i pipistrelli non devono
+ essere disturbati.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="diving-equipment" categories="de-tools">
+ <groundspeak id="5" inc="true" name="Scuba gear" />
+ <opencaching site_url="http://opencaching.de/" id="51" />
+ <name lang="en">Diving equipment required</name>
+ <desc lang="en">
+ You will need diving equipment to find this geocache. The water depth
+ of the cache location is specified in the description. Please note that
+ secure diving requires special training. Without diving experience,
+ you may search this cache in company of a diving teacher.
+ </desc>
+ <name lang="de">Taucherausrüstung</name>
+ <desc lang="de">
+ Um den Geocache zu finden benötigt ihr eine Tauchausrüstung. In welcher
+ Tiefe der Geocache liegt ist in der Beschreibung angegeben. Bitte beachtet,
+ dass Ihr für einen sicheren Tauchgang eine entsprechende Ausbildung
+ benötigt. Als Nicht-Taucher könnt ihr den Geocache evtl. zusammen mit
+ einem Tauchlehrer suchen.
+ </desc>
+ <name lang="es">Diving equipment</name>
+ <desc lang="es">
+ Necesitará un equipo de buceo para encontrar este geocache. La
+ profundidad del agua en la ubicación de la cache se especifica en la
+ descripción. Tenga en cuenta que el buceo requiere un entrenamiento
+ especial. Sin experiencia de buceo, puedes buscar por el caché, junto
+ con un buceador experimentado.
+ </desc>
+ <name lang="it">Equipo de buceo</name>
+ <desc lang="it">
+ Avrete bisogno di attrezzatura subacquea per trovare questa geocache.
+ La profondità d'acqua nella posizione della cache viene specificata nella
+ descrizione. Si prega di notare che l'immersione in tutta sicurezza
+ richiede una formazione specifica. Senza esperienza di immersioni, è
+ possibile cercare questa cache in compagnia di un insegnante di sub.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="special-tools" categories="de-tools">
+ <groundspeak id="51" inc="true" name="Special tool required" />
+ <opencaching site_url="http://opencaching.pl/" id="83" />
+ <opencaching site_url="http://opencaching.de/" id="46" />
+ <name lang="en">Special tools required</name>
+ <desc lang="en">
+ You will need special equipment which is not specified by other attributes.
+ See the cache description on what tools are required.
+ </desc>
+ <name lang="pl">Wymagany dodatkowy sprzęt</name>
+ <desc lang="pl">
+ Niezbędny jest dodatkowy, niestandardowy sprzęt - może to być np.
+ kajak, sprzęt wspinaczkowy, ale również kalkulator, kalosze itp.
+ Ogólnie przedmioty, które nie należą do standardowego wyposażenia
+ poszukiwacza.
+ </desc>
+ <name lang="de">spezielle Ausrüstung</name>
+ <desc lang="de">
+ Für diesen Cache benötigst du weitere Ausrüstung, die nicht durch die
+ anderen Attribute angegeben ist und nicht zur Standardausrüstung eines
+ Geocachers gehört. Was genau du benütigst, ist in der Beschreibung
+ angegeben.
+ </desc>
+ <name lang="es">Equipamiento especial</name>
+ <desc lang="es">
+ Necesitarás un equipo especial no especificado por otros atributos.
+ </desc>
+ <name lang="it">Equipaggiamento speciale</name>
+ <desc lang="it">
+ Avrete bisogno di attrezzature speciali non specificate da altri attributi.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="boat" categories="de-tools">
+ <groundspeak id="4" inc="true" name="Boat" />
+ <opencaching site_url="http://opencaching.pl/" id="86" />
+ <opencaching site_url="http://opencaching.de/" id="52" />
+ <name lang="en">Requires a boat</name>
+ <desc lang="en">
+ This cache can usually be found only when using a watercraft.
+ Swimming is difficult or impossible because of the distance or currents.
+ See the cache description for more details.
+ </desc>
+ <name lang="pl">Wymaga sprzętu pływającego</name>
+ <desc lang="pl">
+ Skrzynka z tym atrybutem najczęściej może być zdobyta jedynie przy
+ użyciu sprzętu pływającego (łodzi, pontonu, kajaka itp.) Dopłynięcie
+ wpław jest trudne lub niemożliwe, ze względu na dystans, silne
+ prądy itp.
+ </desc>
+ <name lang="de">Wasserfahrzeug</name>
+ <desc lang="de">
+ Der Geocache kann – normalerweise – nicht ohne ein Wasserfahrzeug gefunden
+ werden. Zum Geocache kann wegen der Entfernung oder Strömung nicht
+ geschwommen werden. Details dazu sind in der Beschreibung des Geocaches
+ angegeben.
+ </desc>
+ <name lang="es">Barca</name>
+ <desc lang="es">
+ Este cache por lo general sólo se puede encontrar con una moto de agua.
+ Nadando es imposible debido a la distancia o la corriente. Véase la
+ descripción del cache para obtener más detalles.
+ </desc>
+ <name lang="it">Barca</name>
+ <desc lang="it">
+ Questa cache di solito può essere trovata solo con una moto d'acqua. Il
+ nuoto è impossibile a causa della distanza o delle correnti. Vedi la
+ descrizione della cache per maggiori dettagli.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="nogps" categories="de-tools">
+ <opencaching site_url="http://opencaching.de/" id="35" />
+ <name lang="en">No GPS required</name>
+ <desc lang="en">
+ This cache can be found without a GPS device. No additional coordinates
+ are used besides of the starting coordinates.
+ </desc>
+ <name lang="de">ohne GPS findbar</name>
+ <desc lang="de">
+ Dieser Cache lässt sich auch ohne GPS-Empfänger finden. Die Aufgaben
+ sind so gestellt, dass man außer den Startkoordinaten keine weiteren
+ Koordinaten verwenden muss.
+ </desc>
+ <name lang="es">Sin GPS</name>
+ <desc lang="es">
+ Esta cache se puede encuentra sin un dispositivo GPS. Detalles adicionales
+ no se utilizan, además de las coordenadas iniciales.
+ </desc>
+ <name lang="it">Senza GPS</name>
+ <desc lang="it">
+ Questa cache può essere trovata senza un dispositivo GPS. Non sono
+ utilizzate coordinate addizionali oltre alle coordinate iniziali.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="dangerous-area" categories="de-dangers">
+ <groundspeak id="23" inc="true" name="Dangerous area" />
+ <opencaching site_url="http://opencaching.de/" id="9" />
+ <opencaching site_url="http://opencaching.pl/" id="90" />
+ <name lang="en">Dangerous area</name>
+ <desc lang="en">
+ The cache is located within a dangerous area, and danges may not be
+ obvious, e.g. like high-traffic roads, steep ground or falling rocks.
+ Safety measures should be taken, especially when geocaching with
+ children, large groups of people or during bad weather conditions.
+ </desc>
+ <name lang="pl">Skrzynka niebezpieczna</name>
+ <desc lang="pl">
+ Skrzynka jest ukryta w niebezpiecznym terenie. Jej poszukiwania mogą
+ narazić na niebezpieczeństwo wypadku lub urazu.
+ </desc>
+ <name lang="de">gefährliches Gebiet</name>
+ <desc lang="de">
+ In dem Gebiet, wo der Geocache versteckt wurde, ist mit Gefahren zu
+ rechnen, die unter Umständen nicht auf den ersten Blick erkennbar sind.
+ Das können z.B. stark befahrene Straßen, steile Abhänge oder Steinschlag
+ sein. Deshalb sollte man bei Geocaching-Touren mit Kindern oder größeren
+ Gruppen entsprechende Vorsichtsmaßnahmen ergreifen und je nachdem auch
+ auf die Witterung achten (z.B. Regen bei steilen Abhängen).
+ Näheres zu den Gefahren ist in der Cachebeschreibung erläutert.
+ </desc>
+ <name lang="es">Zona Peligrosa</name>
+ <desc lang="es">
+ El cache está situado en una zona peligrosa, como tales como carreteras
+ con mucho tráfico, terreno empinado o caída de rocas. Usted debe tomar
+ medidas de seguridad o evitar ir a buscar el caché, sobre todo con niños,
+ con grupos grandes o en condiciones meteorológicas adversas.
+ </desc>
+ <name lang="it">Area pericolosa</name>
+ <desc lang="it">
+ La cache è situata in un'area pericolosa come strade ad alto traffico,
+ terreno ripido o caduta sassi. Si dovrebbero adottare misure di sicurezza
+ o evitare di andare a cercare la cache, in particolare nel geocaching con
+ bambini, con gruppi numerosi o in condizioni climatiche sfavorevoli.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="railway" categories="de-dangers">
+ <opencaching site_url="http://opencaching.de/" id="10" />
+ <name lang="en">Active railway nearby</name>
+ <desc lang="en">
+ There are active railroads nearby. Please be careful, keep a safe
+ distance and cross the rails only at level crossings etc.!
+ </desc>
+ <name lang="de">aktive Eisenbahnlinie in der Nähe</name>
+ <desc lang="de">
+ In der Nähe dieses Caches gibt es genutzte Eisenbahnlinien. Bitte seid
+ entsprechend vorsichtig und achtet darauf, abseits von Bahnübergängen keine
+ Gleise zu betreten.
+ </desc>
+ <name lang="es">Cerca del ferrocarril activo</name>
+ <desc lang="es">
+ ¡Hay ferrocarriles activos en las proximidades. Por favor, tenga
+ cuidado, manteniendo una distancia segura y cruzar los rieles sólo
+ en los cruces de ferrocarril, etc.!
+ </desc>
+ <name lang="it">Ferrovia attiva nei pressi</name>
+ <desc lang="it">
+ Ci sono ferrovie attive nelle vicinanze. Per favore usate cautela,
+ tenendo una distanza di sicurezza e attraversando le rotaie solo ai
+ passaggi a livello ecc.!
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="cliff" categories="de-dangers">
+ <groundspeak id="21" inc="true" name="Cliff / falling rocks" />
+ <opencaching site_url="http://opencaching.de/" id="11" />
+ <name lang="en">Cliff / Rocks</name>
+ <desc lang="en">
+ There are cliffs or dangerous rocks nearby. Beware of falling rocks
+ at the lower side, and be careful at the upper side of cliffs -
+ especially with children and while mountain biking. It can be very
+ dangerous to take a steep slope towards a cliff, because you may not
+ notice in time where the former ends and the latter starts.
+ </desc>
+ <name lang="de">Klippen / Felsen</name>
+ <desc lang="de">
+ In der Nähe des Caches gibt es Klippen oder Felsen. Unterhalb von
+ Felsen sollte man auf Steinschlag achten, von der Oberseite der Klippen
+ sollte man sich entsprechend vorsichtig nähern (insbesondere mit Kindern
+ oder Mountainbikes). Besonders gefährlich - und nicht immer erkennbar -
+ ist es, sich über einen Steilhang von oben an eine Klippe zu nähern.
+ </desc>
+ <name lang="es">Acantilado / Rocas</name>
+ <desc lang="es">
+ Hay acantilados o rocas peligrososas en las cercanas. Tenga cuidado
+ cuando esté bajo las piedras caídas, y tenga cuidado cuando esté sobre
+ el acantilado - especialmente con los niños y el ciclismo. Puede ser
+ muy peligroso tomar un camino empinado para subir el acantilado porque
+ no se puede saber de antemano cuando el primero termina y comienza otra.
+ </desc>
+ <name lang="it">Scogliera / Rocce</name>
+ <desc lang="it">
+ Ci sono scogliere o rocce pericolose nelle vicinanze. Fate attenzione
+ alla caduta pietre quando siete sotto, e siate cauti quando siete sopra
+ la scogliera - specialmente con bambini e in bicicletta. Può essere molto
+ pericoloso prendere un sentiero ripido per salire la scogliera, poiché
+ non potete sapere in anticipo quando la prima termina e inizia l'altra.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="hunting" categories="de-dangers">
+ <groundspeak id="22" inc="true" name="Hunting" />
+ <opencaching site_url="http://opencaching.de/" id="12" />
+ <name lang="en">Hunting</name>
+ <desc lang="en">
+ The geocache is placed within a hunting ground. At twilight and in the
+ dark, a flashlight or headlight should always be used for security
+ reasons. Be considerate when meeting hunters.
+ </desc>
+ <name lang="de">Jagdgebiet</name>
+ <desc lang="de">
+ Der Geocache liegt in einem Jagdgebiet. Bei Dämmerung oder Dunkelheit
+ sollte man aus Sicherheitsgründen immer eine Taschenlampe oder
+ Stirnlampe verwenden. Bei Begegnungen mit Jägern ist gegenseitige
+ Rücksichtnahme angebracht.
+ </desc>
+ <name lang="es">Zona de Caza</name>
+ <desc lang="es">
+ El geocache se coloca dentro de un coto de caza. Al caer la tarde y en
+ la oscuridad, una linterna o faro siempre debe utilizarse por razones
+ de seguridad.
+ </desc>
+ <name lang="it">Caccia</name>
+ <desc lang="it">
+ La geocache è situata nei pressi di una area di caccia. Al crepuscolo
+ e al buio, dovrebbe sempre essere usata una torcia portatile o frontale
+ per ragioni di sicurezza. Incontrando i cacciatori è opportuna una
+ reciproca gentilezza.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="thorns" categories="de-dangers">
+ <groundspeak id="39" inc="true" name="Thorns" />
+ <opencaching site_url="http://opencaching.de/" id="13" />
+ <name lang="en">Thorns</name>
+ <desc lang="en">
+ There are thorns near the cache. Wear appropriate clothes.
+ </desc>
+ <name lang="de">Dornen</name>
+ <desc lang="de">
+ In er Nähe des Geocaches gibt es Dornen. Entsprechende Kleidung und
+ evtl. Handschuhe sind zu empfehlen.
+ </desc>
+ <name lang="es">Espinas</name>
+ <desc lang="es">
+ Hay espinas cerca de la caché. Use ropa apropiada.
+ </desc>
+ <name lang="it">Spine</name>
+ <desc lang="it">
+ Ci sono spine nei pressi della cache. Indossare indumenti appropriati.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="ticks" categories="de-dangers">
+ <groundspeak id="19" inc="true" name="Ticks" />
+ <opencaching site_url="http://opencaching.de/" id="14" />
+ <name lang="en">Ticks</name>
+ <desc lang="en">
+ There are seasonably many ticks in this area. It is recommended to wear
+ long trousers and to check yourself for ticks after geocaching.
+ There are regional risk maps for <i>tick-borne encephalitis</i> on the
+ internet.
+ </desc>
+ <name lang="de">Zecken</name>
+ <desc lang="de">
+ Je nach Saison gibt es in dem Gebiet besonders viele Zecken. Es wird
+ daher empfohlen, entsprechend lange Kleidung zu tragen und nach der
+ Cachetour nach Zecken Ausschau zu halten. FSME-Risikogebiete und
+ weitere Informationen zum Thema Zecken könnt ihr z.B. auf
+ <a href='http://www.meningitis.de'>www.meningitis.de</a> nachsehen.
+ </desc>
+ <name lang="es">Garrapatas</name>
+ <desc lang="es">
+ Cada temporada hay un montón de garrapatas en este lubar. Y es
+ recomendable llevar pantalón largo y examinarse en busca de garrapatas
+ después de encontrar el cache.
+ </desc>
+ <name lang="it">Zecche</name>
+ <desc lang="it">
+ Stagionalmente ci sono molte zecche in questa area. E' raccomandabile
+ indossare pantaloni lunghi e ispezionarsi alla ricerca di zecche dopo
+ il geocaching. In internet ci sono mappe di rischio per <i>encefalite
+ e borelliosi da morso di zecca</i>.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="mines" categories="de-dangers">
+ <groundspeak id="20" inc="true" name="Abandoned mines" />
+ <opencaching site_url="http://opencaching.de/" id="15" />
+ <name lang="en">Abandoned mines</name>
+ <desc lang="en">
+ This cache leads into a (former) mining area. There may be dangers by
+ collapsing adits, or you may need to enter adits. Be careful and use
+ appropriate equipment, especially in the dark. Old mines may be covered
+ by historic preservation.
+ </desc>
+ <name lang="de">Folgen des Bergbaus</name>
+ <desc lang="de">
+ Der Cache führt in eine (ehemalige) Bergbauregion. Möglicherweise
+ bestehen Gefahren durch verstürzte Stollenmundlöcher oder es müssen
+ Stollen betreten werden. Entsprechende Ausrüstung und Vorsicht,
+ besonders bei Dunkelheit, wird empfohlen. Historische Bergwerke stehen
+ möglicherweise unter Denkmalschutz.
+ </desc>
+ <name lang="es">Mina abandonada</name>
+ <desc lang="es">
+ Esta cache le llevará a un área de la mina (abandonado). Puede haber
+ peligro con el colapso de túneles o galerías que puede ser necesario para
+ cruzar. Tenga cuidado y use de equipo adecuado, especialmente en la
+ oscuridad. Las minas antiguas pueden ser objeto de preservación histórica.
+ </desc>
+ <name lang="it">Miniere abbandonate</name>
+ <desc lang="it">
+ Questa cache vi porta in una area di miniera (abbandonata). Ci possono
+ essere pericoli per crollo di gallerie, o potrebbe essere necessario
+ attraversare gallerie. Fare attenzione e utilizzate attrezzature adeguate,
+ soprattutto al buio. Le vecchie miniere possono essere oggetto di
+ conservazione storica.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="poisonous-plants" categories="de-dangers">
+ <groundspeak id="17" inc="true" name="Poisonous plants" />
+ <opencaching site_url="http://opencaching.de/" id="16" />
+ <name lang="en">Poisonous plants</name>
+ <desc lang="en">
+ There are poisonous plants near the cache. Take care and prevent
+ children and dogs from touching or eating them.
+ </desc>
+ <name lang="de">giftige Pflanzen</name>
+ <desc lang="de">
+ In der Nähe des Caches gibt es giftige Pflanzen. Achtet also insbesondere
+ darauf, dass Kinder und Hunde diese nicht anfassen oder essen.
+ </desc>
+ <name lang="es">Planta venenosa</name>
+ <desc lang="es">
+ Hay plantas venenosas en las cercanías. Tenga cuidado y asegúrese de que
+ los niños o los perros no las toquen ni tragarlas.
+ </desc>
+ <name lang="it">Piante velenose</name>
+ <desc lang="it">
+ Ci sono piante velenose nelle vicinanze. Fate attenzione e controllate
+ che bambini o cani non le tocchino o le ingoino.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="dangerous-animals" categories="de-dangers">
+ <groundspeak id="18" inc="true" name="Dangerous animals" />
+ <opencaching site_url="http://opencaching.de/" id="17" />
+ <name lang="en">Dangerous animals</name>
+ <desc lang="en">
+ The area is inhabited by possibly dangerous animals, e.g. rabies areas,
+ venomous snakes, scorpions or bears.
+ </desc>
+ <name lang="de">giftige/gefährliche Tiere</name>
+ <desc lang="de">
+ In dem Gebiet sind Wildtiere angesiedelt, die für Menschen eine Gefahr
+ darstellen können, z.B. Tollwutgebiete, giftige Schlangen, Skorpione
+ oder Bären.
+ </desc>
+ <name lang="es">Animales Peligrosos</name>
+ <desc lang="es">
+ Esta zona es frecuentada por los animales potencialmente peligrosos,
+ por ejemplo. zorros rabiosos, serpientes venenosas, escorpiones, osos.
+ </desc>
+ <name lang="it">Animali pericolosi</name>
+ <desc lang="it">
+ Quest area è frequentata da animali potenzialmente pericolosi, ad es.
+ volpi rabide, serpenti velenosi, scorpioni, orsi.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="quick" categories="de-rating">
+ <!-- TODO: There is a groundspeak attribute called "Takes less than
+ 1 hour", is it applicable here? I'm not sure... In OCPL this attribute
+ was called "One-minute cache", and the official description includes
+ a 15 minutes limit. -->
+ <opencaching site_url="http://opencaching.pl/" id="40" />
+ <name lang="en">Quick cache</name>
+ <desc lang="en">
+ It shouldn't take more than 15 minutes to find this cache. Also,
+ there should be a parking nearby.
+ </desc>
+ <name lang="pl">Szybka skrzynka</name>
+ <desc lang="pl">
+ Jej znalezienie nie powinno zająć więcej niż 15 minut oraz jest
+ łatwy dojazd w pobliże skrzynki samochodem.
+ </desc>
+ <desc lang="de">schnell findbar</desc>
+ </attr>
+
+ <attr okapi_attr_id="overnight" categories="de-rating">
+ <opencaching site_url="http://opencaching.de/" id="37" />
+ <name lang="en">Overnight stay necessary</name>
+ <desc lang="en">
+ This cache cannot be done within a single day or a single night.
+ You will have to visit the location for more than one time,
+ or you must stay overnight. Preparation time is not included in this
+ calculation, but only the time on site.
+ </desc>
+ <name lang="de">Übernachtung erforderlich</name>
+ <desc lang="de">
+ Der Geocache kann nicht mit einer einzigen Tages- oder Nachttour gelöst
+ werden. Er muss entweder mehrmals angefahren werden oder es muss vor Ort
+ übernachtet werden. Zeit für Recherchen vorab sind dabei nicht
+ berücksicht, sondern nur die Zeit vor Ort.
+ </desc>
+ <name lang="es">Necesario pernoctar</name>
+ <desc lang="es">
+ No puedrá encontrar este cache en un solo día o durante la noche. Usted
+ tendrá que visitar el lugar más de una vez, o necesitará pasar la noche.
+ El tiempo de preparación no está incluido en este cálculo, sólo el tiempo
+ en el sitio.
+ </desc>
+ <name lang="it">Necessario pernottamento</name>
+ <desc lang="it">
+ Non è possibile trovare questa cache in un solo giorno o una sola notte.
+ Dovrete visitare il percorso per più di una volta, oppure è necessario il
+ pernottamento. Il tempo di preparazione non è incluso in questo calcolo,
+ ma solo il tempo sul sito.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="children6" categories="de-rating">
+ <groundspeak id="6" inc="true" name="Recommended for kids" /> <!-- Not sure if this is correct. -->
+ <opencaching site_url="http://opencaching.pl/" id="41" />
+ <name lang="en">Take your children</name>
+ <desc lang="pl">
+ This search if simple and safe. It's okay to take small children
+ with you.
+ </desc>
+ <name lang="pl">Można zabrać dzieci</name>
+ <desc lang="pl">
+ Jej poszukiwanie jest przyjemne, bezpieczne i można bez obaw
+ wybrać się z małymi dziećmi.
+ </desc>
+ </attr>
+
+ <attr okapi_attr_id="children10" categories="de-rating">
+ <groundspeak id="6" inc="true" name="Recommended for kids" />
+ <opencaching site_url="http://opencaching.de/" id="59" />
+ <name lang="en">Suited for children (10-12 yo)</name>
+ <desc lang="en">
+ This geocache is suitable for children. All challenges can be solved by
+ child in the age of 10 to 12 years and the terrain has no risks
+ (like highways, abysms). There should be a large geocache container with
+ trading items inside and the challenges be interesting.
+ </desc>
+ <name lang="de">kindgerecht (10-12 Jahre)</name>
+ <desc lang="de">
+ Der Geocache ist kindgerecht aufgebaut: Alle Aufgaben sind von Kindern
+ im Alter von 10 bis 12 Jahren selbstständig lösbar und das Gelände ist
+ nicht gefährlich (keine Haupstraßen, Klippen o.ä.). Am Ende des
+ Geocaches sollte sich eine Box mit Tauschgegenständen befinden, und
+ die Aufgaben sollten interessant aufgebaut sein.
+ </desc>
+ <name lang="es">Apto para niños (10-12 años)</name>
+ <desc lang="es">
+ Este geocache se creó para los niños. Todas las tareas se puede
+ completar por los niños entre los años 10 y 12 y el terrno no está
+ exenta de riesgo (tales como carreteras, acantilados). Hay un gra
+ contenedor con intercambio final y las tareas son interesantes.
+ </desc>
+ <name lang="it">Suited for children (10-12 anni)</name>
+ <desc lang="it">
+ Questa geocache è stata creata per i bambini. Tutte i compiti possono
+ essere portati a termine da bambini tra 10 e 12 anni e il terreno non
+ presenta rischi (come autostrade, abissi). C'e un grande contenitore
+ finale con oggetti di scambio e i compiti sono interessanti.
+ </desc>
+ </attr>
+
+</xml>
diff --git a/main/project/attributes_okapi/genattr.jar b/main/project/attributes_okapi/genattr.jar
new file mode 100644
index 0000000..7ee5bc4
--- /dev/null
+++ b/main/project/attributes_okapi/genattr.jar
Binary files differ
diff --git a/main/project/attributes_okapi/genattr.sh b/main/project/attributes_okapi/genattr.sh
new file mode 100644
index 0000000..7cc23be
--- /dev/null
+++ b/main/project/attributes_okapi/genattr.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+java -jar genattr.jar attributes.xml > AttributeParser.java
diff --git a/main/project/attributes_okapi/readme.txt b/main/project/attributes_okapi/readme.txt
new file mode 100644
index 0000000..5382ebe
--- /dev/null
+++ b/main/project/attributes_okapi/readme.txt
@@ -0,0 +1,10 @@
+In the current version of OKAPI (rev. 798) are attributes not returned with a unified id but only with the localized text.
+Luckily a metadata file to prepare the unification of these attributes has already been prepared by the OKAPI project
+(http://code.google.com/p/opencaching-api/source/browse/trunk/etc/attributes.xml), which do not officially publish as a stable definition,
+but which can serve as an easier starting point for the generation of a parser class.
+To allow the representation with icons we need to map these localized texts to our internal ids which is done with a parser
+generated from the aforementioned file. Soo the AttrGen project for more details.
+
+If attributes.xml will be updated, we need of course to check first if it is structurally compatible to the previous version.
+If present it seems to be necessary to remove the BOM at the beginning of the file. Then you can run genattr.sh
+and copy the generated AttributeParser.java to the appropriate location (connector.oc).
diff --git a/main/project/rawimages/c-geo_icon.svg b/main/project/rawimages/c-geo_icon.svg
new file mode 100644
index 0000000..e0cda5d
--- /dev/null
+++ b/main/project/rawimages/c-geo_icon.svg
@@ -0,0 +1,543 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2985"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ width="512"
+ height="512"
+ sodipodi:docname="c-geo_icon.svg"
+ inkscape:export-filename=""
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <metadata
+ id="metadata2991">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs2989">
+ <linearGradient
+ id="linearGradient3837">
+ <stop
+ style="stop-color:#fbf9d4;stop-opacity:1;"
+ offset="0"
+ id="stop3839" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop3841" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3936">
+ <stop
+ style="stop-color:#f7991d;stop-opacity:1;"
+ offset="0"
+ id="stop3938" />
+ <stop
+ style="stop-color:#f8b339;stop-opacity:1;"
+ offset="1"
+ id="stop3940" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3928">
+ <stop
+ id="stop3930"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:0.12849163;" />
+ <stop
+ id="stop3932"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0.0726257;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3863">
+ <stop
+ style="stop-color:#ffc34a;stop-opacity:1;"
+ offset="0"
+ id="stop3865" />
+ <stop
+ style="stop-color:#f9a62f;stop-opacity:1;"
+ offset="1"
+ id="stop3867" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3801">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.1;"
+ offset="0"
+ id="stop3803" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3805" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3890">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3892" />
+ <stop
+ id="stop3900"
+ offset="0.29212967"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop3898"
+ offset="0.35852277"
+ style="stop-color:#d8dada;stop-opacity:1;" />
+ <stop
+ style="stop-color:#d8dada;stop-opacity:1;"
+ offset="1"
+ id="stop3894" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3864">
+ <stop
+ style="stop-color:#aad04a;stop-opacity:1;"
+ offset="0"
+ id="stop3866" />
+ <stop
+ id="stop3872"
+ offset="0.29795828"
+ style="stop-color:#cfdc8d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#98bc40;stop-opacity:1;"
+ offset="0.36036199"
+ id="stop3882" />
+ <stop
+ style="stop-color:#48873e;stop-opacity:1;"
+ offset="1"
+ id="stop3868" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3838">
+ <stop
+ style="stop-color:#61b647;stop-opacity:1;"
+ offset="0"
+ id="stop3840" />
+ <stop
+ style="stop-color:#92c746;stop-opacity:1;"
+ offset="1"
+ id="stop3842" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3828">
+ <stop
+ id="stop3830"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:0.13333334;" />
+ <stop
+ id="stop3832"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0.11111111;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3796">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.05555556;"
+ offset="0"
+ id="stop3798" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.10555556;"
+ offset="1"
+ id="stop3800" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3796"
+ id="linearGradient3802"
+ x1="15.959242"
+ y1="343.29277"
+ x2="176.26119"
+ y2="343.29277"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3796"
+ id="linearGradient3810"
+ x1="335.7388"
+ y1="344.35822"
+ x2="496.04077"
+ y2="344.35822"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3864"
+ id="linearGradient3880"
+ x1="66.473442"
+ y1="197.85721"
+ x2="453.37692"
+ y2="197.85721"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3890"
+ id="linearGradient3896"
+ x1="70.62744"
+ y1="258.14891"
+ x2="435.78817"
+ y2="258.14891"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ id="filter3916"
+ x="-0.73785931"
+ width="2.4757186"
+ y="-0.25739279"
+ height="1.5147856">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.7505801"
+ id="feGaussianBlur3918" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3838"
+ id="radialGradient3922"
+ cx="283.49646"
+ cy="-10.861603"
+ fx="283.49646"
+ fy="-10.861603"
+ r="193.19952"
+ gradientTransform="matrix(-0.66393007,1.0294724,-1.0210616,-0.65850585,497.86851,-252.56237)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3801"
+ id="linearGradient3807"
+ x1="175.76119"
+ y1="344.35821"
+ x2="336.23881"
+ y2="344.35821"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3863"
+ id="linearGradient3869"
+ x1="39.90625"
+ y1="351.5625"
+ x2="175.7036"
+ y2="351.5625"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3863"
+ id="linearGradient3877"
+ x1="39.90625"
+ y1="411.14062"
+ x2="175.75117"
+ y2="411.14062"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3863"
+ id="linearGradient3885"
+ x1="39.90625"
+ y1="294.22113"
+ x2="175.74925"
+ y2="294.22113"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3928"
+ id="linearGradient3934"
+ gradientUnits="userSpaceOnUse"
+ x1="335.7388"
+ y1="344.35822"
+ x2="496.04077"
+ y2="344.35822" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3936"
+ id="linearGradient3942"
+ x1="336.25"
+ y1="304.70312"
+ x2="472.1875"
+ y2="304.70312"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3936"
+ id="linearGradient3950"
+ x1="336.43512"
+ y1="373.8125"
+ x2="472.1875"
+ y2="373.8125"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3936"
+ id="linearGradient3958"
+ x1="336.24496"
+ y1="420.28125"
+ x2="472.1875"
+ y2="420.28125"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3936"
+ id="linearGradient3966"
+ x1="336.25"
+ y1="459.6875"
+ x2="471.8985"
+ y2="459.6875"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3837"
+ id="linearGradient3843"
+ x1="72.743576"
+ y1="272.0433"
+ x2="73.038445"
+ y2="196.93991"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-4.1012061,5.4616772)" />
+ <filter
+ id="filter4143"
+ style="color-interpolation-filters:sRGB;"
+ inkscape:label="Drop Shadow">
+ <feFlood
+ id="feFlood4145"
+ flood-opacity="0.5"
+ flood-color="rgb(255,255,255)"
+ result="flood" />
+ <feComposite
+ in2="SourceGraphic"
+ id="feComposite4147"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur4149"
+ in="composite"
+ stdDeviation="0.7"
+ result="blur" />
+ <feOffset
+ id="feOffset4151"
+ dx="1.5"
+ dy="0"
+ result="offset" />
+ <feComposite
+ in2="offset"
+ id="feComposite4153"
+ in="SourceGraphic"
+ operator="over"
+ result="fbSourceGraphic" />
+ <feColorMatrix
+ result="fbSourceGraphicAlpha"
+ in="fbSourceGraphic"
+ values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+ id="feColorMatrix4297" />
+ <feFlood
+ id="feFlood4299"
+ flood-opacity="0.4"
+ flood-color="rgb(0,0,0)"
+ result="flood"
+ in="fbSourceGraphic" />
+ <feComposite
+ id="feComposite4301"
+ in2="fbSourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur4303"
+ in="composite"
+ stdDeviation="0.8"
+ result="blur" />
+ <feOffset
+ id="feOffset4305"
+ dx="0.4"
+ dy="-2.5"
+ result="offset" />
+ <feComposite
+ id="feComposite4307"
+ in2="offset"
+ in="fbSourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1058"
+ id="namedview2987"
+ showgrid="false"
+ inkscape:zoom="2.4058204"
+ inkscape:cx="271.74005"
+ inkscape:cy="370.37149"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2985"
+ inkscape:snap-bbox="false"
+ inkscape:snap-nodes="true"
+ inkscape:bbox-nodes="false"
+ inkscape:bbox-paths="false"
+ inkscape:object-nodes="true"
+ inkscape:object-paths="true"
+ inkscape:snap-global="false" />
+ <path
+ style="fill:#000000;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:0.7062937"
+ d="m 22.337543,475.26062 0,28.21584 159.595867,-8.22962 161.06544,7.34788 159.00804,-7.34788 0,-272.16532 -57.31343,-5.29048 z"
+ id="path3812"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="m 16.459242,494.95293 0,-303.32032 220.436278,22.92537 102.87027,-21.74971 155.77497,14.69575 0,272.16533 -159.30195,16.45924 -160.47762,-15.87141 z"
+ id="path2998"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient3869);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 39.90625 379.59375 L 100.46875 348.9375 L 39.90625 323.53125 L 39.90625 379.59375 z "
+ id="path3022" />
+ <path
+ style="fill:#fdd069;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 336.25 447.71875 L 175.75 380.46875 L 175.75 455.875 L 175.8125 455.875 L 335.84375 471.6875 L 336.25 471.65625 L 336.25 447.71875 z "
+ id="path3913" />
+ <path
+ style="fill:url(#linearGradient3966);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 336.25 447.71875 L 336.25 471.65625 L 382.53125 467.125 L 336.25 447.71875 z "
+ id="path3824" />
+ <path
+ style="fill:url(#linearGradient3877);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1.0"
+ d="M 175.75118 380.46593 L 110.4375 353.09375 L 39.90625 388.8125 L 39.90625 469.1875 L 175.75059 455.88106 "
+ id="path3020" />
+ <path
+ style="fill:url(#linearGradient3958);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1.0"
+ d="M 336.24497 437.85561 L 401.0625 465.3125 L 472.1875 458.375 L 472.1875 411.65625 L 472.1875 411.65625 L 401.53125 375.25 L 336.24729 403.39996 "
+ id="path3836" />
+ <path
+ style="fill:#fdd069;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 336.24729 403.39996 L 295.9375 420.78125 L 336.24497 437.85561 "
+ id="path3018" />
+ <path
+ style="fill:url(#linearGradient3950);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 472.1875 344.78125 L 410.84375 371.25 L 472.1875 402.84375 L 472.1875 344.78125 z "
+ id="path3016" />
+ <path
+ style="fill:#fdd069;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 336.25 215.5 L 231.9375 238.90625 L 175.75 232.9375 L 175.75 369.90625 L 285.375 416.34375 L 336.25 394.1875 L 336.25 215.5 z "
+ id="path3918" />
+ <path
+ style="fill:url(#linearGradient3942);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 336.25 215.5 L 336.25 394.1875 L 472.1875 334.96875 L 472.1875 229.34375 L 337.5 215.21875 L 336.25 215.5 z "
+ id="path3831" />
+ <path
+ style="fill:url(#linearGradient3885);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1.0"
+ d="M 175.74925 232.94454 L 39.90625 218.53125 L 39.90625 312.375 L 175.74798 369.91102 "
+ id="path3002" />
+ <path
+ style="fill:url(#linearGradient3807);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="m 336.23881,496.12859 -160.47762,-15.87141 0,-272.05717 160.47762,-15.61218 z"
+ id="path3928"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient3934);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="m 495.54076,479.66935 -159.30195,16.45924 0,-303.54076 159.30195,14.91619 z"
+ id="path3026"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient3802);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="m 16.459242,494.95293 159.301948,-14.69575 0,-272.05717 -159.301948,-16.5674 z"
+ id="path3024"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:0.39768341;stroke:none"
+ d="m 442.88428,146.84389 23.48471,20.36727 c 2.79219,2.93915 2.97845,9.95135 1.03915,18.08115 l -10.39147,31.79789 c -2.64524,4.8496 -9.97581,7.27402 -9.97581,7.27402 0,0 2.60526,7.16885 1.87047,11.43062 L 431.03801,303.54719 211.9859,415.98286 c -4.40873,2.49828 -13.14978,2.5487 -15.79502,-0.83132 L 89.158777,293.57139 86.041338,228.93647 z"
+ id="path3924"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:#5c5d5d;fill-opacity:1;stroke:none"
+ d="m 423.82549,175.46728 c 9.40528,3.52698 10.28702,11.16877 10.58094,18.51665 l -17.6349,67.60046 -215.73364,110.51205 c -13.2323,6.03571 -18.60274,3.52699 -24.10104,-3.23306 L 74.360505,252.1791 69.657865,181.93341 c -0.207829,-7.48186 9.405281,-12.34443 9.405281,-12.34443 z"
+ id="path3920"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ style="fill:url(#linearGradient3896);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="m 435.28817,168.41332 -18.81056,76.41791 -220.73019,109.63031 c -6.23488,2.07829 -10.747,1.83787 -14.69576,-1.17566 L 77.887486,234.5442 71.12744,160.47761 z"
+ id="path3884"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#868786;fill-opacity:1;stroke:none"
+ d="m 452.87691,130.92395 c 1.17566,3.96786 -9.35911,40.28156 -9.35911,40.28156 -2.49395,7.58577 -8.6705,10.28703 -8.6705,10.28703 L 201.3318,287.88978 c -7.17011,2.90961 -14.01254,1.62667 -16.45924,-1.0287 L 69.36395,171.64638 c -2.390037,-3.32527 -2.351321,-12.93226 -2.351321,-12.93226 z"
+ id="path3818"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:url(#linearGradient3880);fill-opacity:1;stroke:none"
+ d="m 452.87691,130.92395 -10.53477,36.60762 c -1.36085,4.47005 -5.29048,6.17222 -5.29048,6.17222 l -235.13203,107.5729 c -10.70321,3.94876 -16.16532,-1.17566 -16.16532,-1.17566 L 69.657865,165.18025 c -3.11744,-2.90961 -2.645236,-6.46613 -2.645236,-6.46613 0,0 -1.053122,-22.11238 -0.03919,-45.77105 z"
+ id="path3816"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffd0;fill-opacity:0.94405589;stroke:none;filter:url(#filter3916)"
+ id="path3902"
+ sodipodi:cx="185.59158"
+ sodipodi:cy="226.65034"
+ sodipodi:rx="9.3523197"
+ sodipodi:ry="26.809982"
+ d="m 194.9439,226.65034 a 9.3523197,26.809982 0 1 1 -18.70464,0 9.3523197,26.809982 0 1 1 18.70464,0 z"
+ transform="matrix(0.88331111,0,0,1.0869978,29.761821,-12.444045)" />
+ <path
+ style="fill:url(#radialGradient3922);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="M 327.42135,24.101033 452.04133,125.79564 c 3.52698,4.70264 -1.46957,7.64179 -1.46957,7.64179 l -246.00689,99.93111 c -5.77133,2.79957 -11.57831,0.83438 -14.69575,-1.76349 L 70.53961,121.68083 c -10.580941,-12.05052 5.29047,-17.04708 5.29047,-17.04708 L 311.25603,23.513203 c 9.40528,-3.820896 16.16532,0.58783 16.16532,0.58783 z"
+ id="path3814"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ <g
+ transform="matrix(1.0487801,-0.41271929,0.76389884,0.65287682,0,0)"
+ style="font-size:27.52445984px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient3843);fill-opacity:1;stroke:none;filter:url(#filter4143);font-family:'232MKSDRoundMedium';-inkscape-font-specification:'232MKSDRoundMedium'"
+ id="text3833">
+ <path
+ d="m 9.8964838,251.44327 c -1.6511043,3.04006 -3.9467671,5.43501 -6.8869951,7.18485 -2.94029722,1.74985 -6.1280177,2.62477 -9.5631709,2.62477 l -0.3961345,0 c -5.1527923,0 -9.5621783,-1.81637 -13.2281713,-5.44912 -3.666016,-3.63274 -5.499018,-8.02549 -5.499012,-13.17828 l 0,-20.71088 c -6e-6,-5.15071 1.832996,-9.55959 5.499012,-13.22666 3.665993,-3.66696 8.075379,-5.50046 13.2281713,-5.50052 l 0.3961345,0 c 3.3686269,6e-5 6.52308417,0.87548 9.4633813,2.62628 2.9402281,1.75091 5.2358908,4.1131 6.8869951,7.08658 0.3971008,0.72579 0.5956718,1.51805 0.5957138,2.3768 -4.2e-5,1.3205 -0.4793342,2.46001 -1.4378777,3.41855 -0.9586246,0.95863 -2.0981402,1.43792 -3.4185501,1.43788 -1.9151893,4e-5 -3.3354259,-0.85875 -4.2607139,-2.57639 -1.71762205,-3.10451 -4.3272689,-4.6568 -7.8289485,-4.65684 l -0.3961345,0 c -2.4433557,4e-5 -4.5404473,0.87497 -6.2912813,2.62477 -1.750871,1.74988 -2.626297,3.87974 -2.626281,6.38955 l 0,20.71088 c -1.6e-5,2.44335 0.87541,4.54045 2.626281,6.29129 1.750834,1.75086 3.8479256,2.62629 6.2912813,2.62628 l 0.3961345,0 c 3.5016796,1e-5 6.11132645,-1.58554 7.8289485,-4.75664 0.925288,-1.71758 2.3455246,-2.57637 4.2607139,-2.57639 1.3869363,2e-5 2.559211,0.47881 3.5168278,1.43637 0.957535,0.95759 1.436323,2.13087 1.436366,3.51985 -4.3e-5,0.79228 -0.197606,1.55128 -0.5926902,2.27702 z"
+ style="font-size:99.08805847px"
+ id="path4310" />
+ <path
+ d="m 34.109071,221.22213 c -1.8e-5,1.58458 -0.577588,2.95492 -1.732711,4.11103 -1.155155,1.15619 -2.526001,1.73426 -4.112541,1.73423 -1.584549,3e-5 -2.954891,-0.57804 -4.11103,-1.73423 -1.156155,-1.15611 -1.734228,-2.52645 -1.734222,-4.11103 -6e-6,-1.65102 0.578067,-3.03799 1.734222,-4.16092 1.156139,-1.12284 2.526481,-1.68428 4.11103,-1.68433 1.58654,5e-5 2.957386,0.56149 4.112541,1.68433 1.155123,1.12293 1.732693,2.5099 1.732711,4.16092 z m 0,28.53681 c -1.8e-5,1.65107 -0.577588,3.03855 -1.732711,4.16244 -1.155155,1.12389 -2.526001,1.68584 -4.112541,1.68584 -1.584549,0 -2.954891,-0.56195 -4.11103,-1.68584 -1.156155,-1.12389 -1.734228,-2.51137 -1.734222,-4.16244 -6e-6,-1.58453 0.578067,-2.95487 1.734222,-4.11103 1.156139,-1.15613 2.526481,-1.73421 4.11103,-1.73422 1.58654,1e-5 2.957386,0.57809 4.112541,1.73422 1.155123,1.15616 1.732693,2.5265 1.732711,4.11103 z"
+ style="font-size:99.08805847px"
+ id="path4312" />
+ <path
+ d="m 83.876868,261.8486 c -4.3e-5,5.15277 -1.816918,9.56215 -5.450629,13.22817 -3.633788,3.66599 -8.027046,5.499 -13.179788,5.49902 l -0.396135,0 c -3.435203,-2e-5 -6.622419,-0.89158 -9.561659,-2.67467 -2.93927,-1.78312 -5.234428,-4.16144 -6.885483,-7.13496 -0.39715,-0.72575 -0.595721,-1.51802 -0.595714,-2.3768 -7e-6,-1.32247 0.478781,-2.46249 1.436366,-3.42007 0.957567,-0.95758 2.097586,-1.43636 3.420062,-1.43636 1.981666,0 3.435166,0.85879 4.360504,2.57639 1.651045,3.10455 4.259684,4.65683 7.825924,4.65684 l 0.396135,0 c 2.445321,-1e-5 4.542917,-0.87543 6.292793,-2.62628 1.749813,-1.75086 2.624735,-3.84795 2.624769,-6.29128 l 0,-2.57638 c -3.4e-5,-0.33062 -0.164334,-0.4294 -0.4929,-0.29635 -2.642944,1.38698 -5.451162,2.08046 -8.424662,2.08046 l -0.396135,0 c -5.152792,0 -9.545546,-1.833 -13.178276,-5.49901 -3.632753,-3.666 -5.449124,-8.07538 -5.449118,-13.22817 l 0,-20.11517 c -6e-6,-5.15273 1.816365,-9.56211 5.449118,-13.22817 3.63273,-3.66595 8.025484,-5.49895 13.178276,-5.49901 l 0.396135,0 c 5.152742,6e-5 9.546,1.83306 13.179788,5.49901 3.633711,3.66606 5.450586,8.07544 5.450629,13.22817 z m -9.712855,-19.51945 0,-20.11517 c -3.4e-5,-2.50982 -0.874956,-4.64017 -2.624769,-6.39107 -1.749876,-1.75081 -3.847472,-2.62623 -6.292793,-2.62628 l -0.396135,0 c -2.443356,5e-5 -4.540447,0.87547 -6.291281,2.62628 -1.750871,1.7509 -2.626297,3.88125 -2.626281,6.39107 l 0,20.11517 c -1.6e-5,2.44335 0.87541,4.54044 2.626281,6.29128 1.750834,1.75087 3.847925,2.62629 6.291281,2.62628 l 0.396135,0 c 2.445321,1e-5 4.542917,-0.87541 6.292793,-2.62628 1.749813,-1.75084 2.624735,-3.84793 2.624769,-6.29128 z"
+ style="font-size:99.08805847px"
+ id="path4314" />
+ <path
+ d="m 133.61443,232.22016 c -4e-5,1.387 -0.4627,2.55978 -1.38798,3.51834 -0.92536,0.95861 -2.08151,1.4379 -3.46845,1.43788 l -22.49197,0 c -0.39716,2e-5 -0.59573,0.16533 -0.59571,0.49592 l 0,4.95319 c -2e-5,2.44335 0.87541,4.54045 2.62628,6.29129 1.75083,1.75086 3.84792,2.62629 6.29128,2.62628 l 0.39613,0 c 3.50168,1e-5 6.11133,-1.55228 7.82895,-4.65685 0.92529,-1.71758 2.34553,-2.57637 4.26072,-2.57639 1.38693,2e-5 2.54308,0.47881 3.46844,1.43637 0.92528,0.95759 1.38794,2.09761 1.38798,3.42006 -4e-5,0.85881 -0.19861,1.65107 -0.59571,2.37681 -1.58458,2.97353 -3.84698,5.33522 -6.7872,7.08506 -2.9403,1.74985 -6.12802,2.62477 -9.56318,2.62477 l -0.39613,0 c -5.15279,0 -9.54555,-1.81637 -13.17828,-5.44912 -3.632749,-3.63274 -5.44912,-8.02549 -5.449114,-13.17828 l 0,-20.71088 c -6e-6,-5.15071 1.816365,-9.55959 5.449114,-13.22666 3.63273,-3.66696 8.02549,-5.50046 13.17828,-5.50052 l 0.39613,0 c 5.15275,6e-5 9.54601,1.83356 13.17979,5.50052 3.63371,3.66707 5.45059,8.07595 5.45063,13.22666 z m -9.71285,-5.34933 0,-4.95622 c -4e-5,-2.50981 -0.87496,-4.63967 -2.62477,-6.38955 -1.74988,-1.7498 -3.84747,-2.62473 -6.2928,-2.62477 l -0.39613,0 c -2.44336,4e-5 -4.54045,0.87497 -6.29128,2.62477 -1.75087,1.74988 -2.6263,3.87974 -2.62628,6.38955 l 0,4.95622 c -2e-5,0.33065 0.19855,0.49596 0.59571,0.49593 l 17.04286,0 c 0.39509,3e-5 0.59265,-0.16528 0.59269,-0.49593 z"
+ style="font-size:99.08805847px"
+ id="path4316" />
+ <path
+ d="m 183.35199,242.62549 c -4e-5,5.15279 -1.81692,9.54554 -5.45063,13.17828 -3.63379,3.63275 -8.02705,5.44912 -13.17979,5.44912 l -0.39613,0 c -5.1528,0 -9.54555,-1.81637 -13.17828,-5.44912 -3.63275,-3.63274 -5.44912,-8.02549 -5.44912,-13.17828 l 0,-20.71088 c 0,-5.15071 1.81637,-9.55959 5.44912,-13.22666 3.63273,-3.66696 8.02548,-5.50046 13.17828,-5.50052 l 0.39613,0 c 5.15274,6e-5 9.546,1.83356 13.17979,5.50052 3.63371,3.66707 5.45059,8.07595 5.45063,13.22666 z m -9.71286,0 0,-20.71088 c -3e-5,-2.50981 -0.87495,-4.63967 -2.62477,-6.38955 -1.74987,-1.7498 -3.84747,-2.62473 -6.29279,-2.62477 l -0.39613,0 c -2.44336,4e-5 -4.54045,0.87497 -6.29128,2.62477 -1.75088,1.74988 -2.6263,3.87974 -2.62629,6.38955 l 0,20.71088 c -1e-5,2.44335 0.87541,4.54045 2.62629,6.29129 1.75083,1.75086 3.84792,2.62629 6.29128,2.62628 l 0.39613,0 c 2.44532,1e-5 4.54292,-0.87542 6.29279,-2.62628 1.74982,-1.75084 2.62474,-3.84794 2.62477,-6.29129 z"
+ style="font-size:99.08805847px"
+ id="path4318" />
+ </g>
+</svg>
diff --git a/main/project/rawimages/c_geo_icon_basic_512.png b/main/project/rawimages/c_geo_icon_basic_512.png
deleted file mode 100644
index c4a592f..0000000
--- a/main/project/rawimages/c_geo_icon_basic_512.png
+++ /dev/null
Binary files differ
diff --git a/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png b/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png
deleted file mode 100644
index 1fab340..0000000
--- a/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png
+++ /dev/null
Binary files differ
diff --git a/main/res/drawable-hdpi/actionbar_manual.png b/main/res/drawable-hdpi/actionbar_manual.png
deleted file mode 100644
index 0b0c93c..0000000
--- a/main/res/drawable-hdpi/actionbar_manual.png
+++ /dev/null
Binary files differ
diff --git a/main/res/drawable-hdpi/ic_menu_start_conversation.png b/main/res/drawable-hdpi/ic_menu_start_conversation.png
new file mode 100644
index 0000000..395a5ec
--- /dev/null
+++ b/main/res/drawable-hdpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/main/res/drawable-ldpi/actionbar_manual.png b/main/res/drawable-ldpi/actionbar_manual.png
deleted file mode 100644
index 14af11d..0000000
--- a/main/res/drawable-ldpi/actionbar_manual.png
+++ /dev/null
Binary files differ
diff --git a/main/res/drawable-ldpi/ic_menu_start_conversation.png b/main/res/drawable-ldpi/ic_menu_start_conversation.png
new file mode 100644
index 0000000..1e39928
--- /dev/null
+++ b/main/res/drawable-ldpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/main/res/drawable-mdpi/actionbar_manual.png b/main/res/drawable-mdpi/actionbar_manual.png
deleted file mode 100644
index a71acb3..0000000
--- a/main/res/drawable-mdpi/actionbar_manual.png
+++ /dev/null
Binary files differ
diff --git a/main/res/drawable-mdpi/attribute_easy_climbing.png b/main/res/drawable-mdpi/attribute_easy_climbing.png
new file mode 100644
index 0000000..ecf10b8
--- /dev/null
+++ b/main/res/drawable-mdpi/attribute_easy_climbing.png
Binary files differ
diff --git a/main/res/drawable-mdpi/attribute_geotour.png b/main/res/drawable-mdpi/attribute_geotour.png
new file mode 100644
index 0000000..f1f0c24
--- /dev/null
+++ b/main/res/drawable-mdpi/attribute_geotour.png
Binary files differ
diff --git a/main/res/drawable-mdpi/helper_manual.png b/main/res/drawable-mdpi/helper_manual.png
deleted file mode 100644
index c3c43db..0000000
--- a/main/res/drawable-mdpi/helper_manual.png
+++ /dev/null
Binary files differ
diff --git a/main/res/drawable-mdpi/helper_pocketquery.png b/main/res/drawable-mdpi/helper_pocketquery.png
new file mode 100644
index 0000000..0a24d2f
--- /dev/null
+++ b/main/res/drawable-mdpi/helper_pocketquery.png
Binary files differ
diff --git a/main/res/drawable-mdpi/ic_menu_start_conversation.png b/main/res/drawable-mdpi/ic_menu_start_conversation.png
new file mode 100644
index 0000000..24b6540
--- /dev/null
+++ b/main/res/drawable-mdpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/main/res/drawable/favourite_background_dark.xml b/main/res/drawable/favorite_background_dark.xml
index b8aa8d3..b8aa8d3 100644
--- a/main/res/drawable/favourite_background_dark.xml
+++ b/main/res/drawable/favorite_background_dark.xml
diff --git a/main/res/drawable/favourite_background_green_dark.xml b/main/res/drawable/favorite_background_green_dark.xml
index 3e1b545..3e1b545 100644
--- a/main/res/drawable/favourite_background_green_dark.xml
+++ b/main/res/drawable/favorite_background_green_dark.xml
diff --git a/main/res/drawable/favourite_background_green_light.xml b/main/res/drawable/favorite_background_green_light.xml
index a2070e7..a2070e7 100644
--- a/main/res/drawable/favourite_background_green_light.xml
+++ b/main/res/drawable/favorite_background_green_light.xml
diff --git a/main/res/drawable/favourite_background_light.xml b/main/res/drawable/favorite_background_light.xml
index 60c0b2c..60c0b2c 100644
--- a/main/res/drawable/favourite_background_light.xml
+++ b/main/res/drawable/favorite_background_light.xml
diff --git a/main/res/drawable/favourite_background_orange_dark.xml b/main/res/drawable/favorite_background_orange_dark.xml
index 8730487..8730487 100644
--- a/main/res/drawable/favourite_background_orange_dark.xml
+++ b/main/res/drawable/favorite_background_orange_dark.xml
diff --git a/main/res/drawable/favourite_background_orange_light.xml b/main/res/drawable/favorite_background_orange_light.xml
index 89ef726..89ef726 100644
--- a/main/res/drawable/favourite_background_orange_light.xml
+++ b/main/res/drawable/favorite_background_orange_light.xml
diff --git a/main/res/drawable/favourite_background_red_dark.xml b/main/res/drawable/favorite_background_red_dark.xml
index 2fb580e..2fb580e 100644
--- a/main/res/drawable/favourite_background_red_dark.xml
+++ b/main/res/drawable/favorite_background_red_dark.xml
diff --git a/main/res/drawable/favourite_background_red_light.xml b/main/res/drawable/favorite_background_red_light.xml
index b16cb92..b16cb92 100644
--- a/main/res/drawable/favourite_background_red_light.xml
+++ b/main/res/drawable/favorite_background_red_light.xml
diff --git a/main/res/layout-land/coords.xml b/main/res/layout-land/coords.xml
index 1388187..88e5e76 100644
--- a/main/res/layout-land/coords.xml
+++ b/main/res/layout-land/coords.xml
@@ -10,13 +10,6 @@
<TextView
style="@style/action_bar_title"
android:text="@string/cache_coordinates" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- android:id="@+id/actionBarManualbutton"
- style="@style/action_bar_action"
- android:src="@drawable/actionbar_manual" />
</LinearLayout>
<ScrollView
diff --git a/main/res/layout-land/navigate.xml b/main/res/layout-land/navigate.xml
index aa8b2b4..d07f047 100644
--- a/main/res/layout-land/navigate.xml
+++ b/main/res/layout-land/navigate.xml
@@ -5,23 +5,7 @@
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>
+ <include layout="@layout/actionbar" />
<LinearLayout
android:layout_width="fill_parent"
@@ -44,7 +28,7 @@
android:layout_gravity="center"
android:gravity="center_horizontal"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/cacheinfo"
@@ -57,7 +41,7 @@
android:layout_gravity="center"
android:gravity="center_horizontal"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/heading"
@@ -69,7 +53,7 @@
android:layout_marginLeft="3dip"
android:text="@null"
android:textColor="?text_color"
- android:textSize="26dip" />
+ android:textSize="26sp" />
<TextView
android:id="@+id/distance"
@@ -81,7 +65,7 @@
android:layout_marginRight="3dip"
android:text="@null"
android:textColor="?text_color"
- android:textSize="26dip" />
+ android:textSize="26sp" />
<TextView
android:id="@+id/nav_location"
diff --git a/main/res/layout/about_activity.xml b/main/res/layout/about_activity.xml
index 9325ea0..743630d 100644
--- a/main/res/layout/about_activity.xml
+++ b/main/res/layout/about_activity.xml
@@ -5,16 +5,7 @@
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" />
- </LinearLayout>
+ <include layout="@layout/actionbar"/>
<ScrollView
android:layout_width="fill_parent"
@@ -51,7 +42,7 @@
android:layout_marginTop="5dip"
android:text="@string/quote"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:layout_width="wrap_content"
@@ -62,7 +53,7 @@
android:layout_marginRight="10dip"
android:text="@string/powered_by"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -84,7 +75,7 @@
android:layout_marginRight="10dip"
android:textColor="?text_color"
android:textIsSelectable="true"
- android:textSize="14dip"
+ android:textSize="14sp"
android:textStyle="bold" />
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -136,7 +127,7 @@
android:text="@string/support"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/website"
@@ -153,7 +144,7 @@
android:text="@string/website"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/facebook"
@@ -170,7 +161,7 @@
android:text="@string/facebook"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/twitter"
@@ -187,7 +178,7 @@
android:text="@string/twitter"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/nutshellmanual"
@@ -204,7 +195,24 @@
android:text="@string/nutshellmanual"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
+
+ <TextView
+ android:id="@+id/market"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:layout_marginBottom="5dip"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="10dip"
+ android:clickable="true"
+ android:focusable="true"
+ android:linksClickable="false"
+ android:onClick="market"
+ android:text="@string/market"
+ android:textColor="?text_color"
+ android:textColorLink="?text_color_link"
+ android:textSize="14sp" />
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -226,7 +234,7 @@
android:text="@string/changelog"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="12dip" />
+ android:textSize="12sp" />
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -248,7 +256,7 @@
android:text="@string/contributors"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
</ScrollView>
diff --git a/main/res/layout/actionbar.xml b/main/res/layout/actionbar.xml
new file mode 100644
index 0000000..9a3efa0
--- /dev/null
+++ b/main/res/layout/actionbar.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/action_bar" >
+
+ <include layout="@layout/actionbar_title"/>
+</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/actionbar_button_compass.xml b/main/res/layout/actionbar_button_compass.xml
new file mode 100644
index 0000000..932444b
--- /dev/null
+++ b/main/res/layout/actionbar_button_compass.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <View style="@style/action_bar_separator" />
+
+ <ImageView
+ android:id="@+id/defaultNavigation"
+ style="@style/action_bar_action"
+ android:longClickable="true"
+ android:onClick="goDefaultNavigation"
+ android:src="@drawable/actionbar_compass_dark" />
+
+</merge> \ No newline at end of file
diff --git a/main/res/layout/actionbar_button_map.xml b/main/res/layout/actionbar_button_map.xml
new file mode 100644
index 0000000..9b2138a
--- /dev/null
+++ b/main/res/layout/actionbar_button_map.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <View style="@style/action_bar_separator" />
+
+ <ImageView
+ style="@style/action_bar_action"
+ android:onClick="goMap"
+ android:src="@drawable/actionbar_map" />
+
+</merge> \ No newline at end of file
diff --git a/main/res/layout/actionbar_button_myposition.xml b/main/res/layout/actionbar_button_myposition.xml
new file mode 100644
index 0000000..3604345
--- /dev/null
+++ b/main/res/layout/actionbar_button_myposition.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <View style="@style/action_bar_separator" />
+
+ <ImageSwitcher
+ android:id="@+id/my_position"
+ style="@style/action_bar_action" />
+
+</merge> \ No newline at end of file
diff --git a/main/res/layout/actionbar_button_search.xml b/main/res/layout/actionbar_button_search.xml
new file mode 100644
index 0000000..2aa1a50
--- /dev/null
+++ b/main/res/layout/actionbar_button_search.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <View style="@style/action_bar_separator" />
+
+ <ImageView
+ style="@style/action_bar_action"
+ android:onClick="goSearch"
+ android:src="@drawable/actionbar_search" />
+
+</merge> \ No newline at end of file
diff --git a/main/res/layout/actionbar_progress.xml b/main/res/layout/actionbar_progress.xml
new file mode 100644
index 0000000..a39d103
--- /dev/null
+++ b/main/res/layout/actionbar_progress.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/action_bar_progress"
+ android:visibility="gone" android:id="@+id/actionbar_progress"/> \ No newline at end of file
diff --git a/main/res/layout/actionbar_title.xml b/main/res/layout/actionbar_title.xml
new file mode 100644
index 0000000..4fa5348
--- /dev/null
+++ b/main/res/layout/actionbar_title.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <ImageView
+ style="@style/action_bar_action"
+ android:onClick="goHome" />
+
+ <View style="@style/action_bar_separator" />
+
+ <TextView
+ android:id="@+id/actionbar_title"
+ style="@style/action_bar_title" />
+
+</merge> \ No newline at end of file
diff --git a/main/res/layout/actionbar_title_no_home.xml b/main/res/layout/actionbar_title_no_home.xml
new file mode 100644
index 0000000..6295bdc
--- /dev/null
+++ b/main/res/layout/actionbar_title_no_home.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextView
+ android:id="@+id/actionbar_title"
+ style="@style/action_bar_title" />
+
+</merge> \ No newline at end of file
diff --git a/main/res/layout/addresses.xml b/main/res/layout/addresses.xml
index 2be131d..08f5bc1 100644
--- a/main/res/layout/addresses.xml
+++ b/main/res/layout/addresses.xml
@@ -4,16 +4,7 @@
android:layout_height="fill_parent"
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" />
- </LinearLayout>
+ <include layout="@layout/actionbar"/>
<ListView
android:id="@android:id/list"
diff --git a/main/res/layout/addresses_item.xml b/main/res/layout/addresses_item.xml
index 3ea27ff..dac1768 100644
--- a/main/res/layout/addresses_item.xml
+++ b/main/res/layout/addresses_item.xml
@@ -21,7 +21,7 @@
android:singleLine="false"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="22dip" />
+ android:textSize="22sp" />
<TextView
android:id="@+id/distance"
@@ -34,6 +34,6 @@
android:singleLine="true"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="12dip" />
+ android:textSize="12sp" />
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/attribute_descriptions.xml b/main/res/layout/attribute_descriptions.xml
index 45dd3cd..1e67f72 100644
--- a/main/res/layout/attribute_descriptions.xml
+++ b/main/res/layout/attribute_descriptions.xml
@@ -13,6 +13,6 @@
android:textColor="?text_color"
android:textColorLink="?text_color_link"
android:textIsSelectable="false"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/twitter_authorization_activity.xml b/main/res/layout/authorization_activity.xml
index 97c2236..931441d 100644
--- a/main/res/layout/twitter_authorization_activity.xml
+++ b/main/res/layout/authorization_activity.xml
@@ -5,16 +5,7 @@
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>
+ <include layout="@layout/actionbar"/>
<ScrollView
android:layout_width="fill_parent"
@@ -28,6 +19,7 @@
android:orientation="vertical" >
<TextView
+ android:id="@+id/auth_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
@@ -37,11 +29,11 @@
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:id="@+id/auth_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
@@ -49,7 +41,6 @@
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" />
@@ -61,20 +52,17 @@
<Button
android:id="@+id/start"
- style="@style/button_full"
- android:text="@string/auth_authorize" />
+ style="@style/button_full" />
<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>
diff --git a/main/res/layout/cache_image_item.xml b/main/res/layout/cache_image_item.xml
index 7ed4782..f0e8963 100644
--- a/main/res/layout/cache_image_item.xml
+++ b/main/res/layout/cache_image_item.xml
@@ -24,7 +24,13 @@
android:layout_gravity="left"
android:padding="3dip"
android:textColor="?text_color"
- android:textSize="14dip"
+ android:textSize="14sp"
android:visibility="gone" />
+ <ProgressBar
+ android:id="@+id/progress_bar"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@android:style/Widget.ProgressBar.Small"/>
+
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/cache_information_item.xml b/main/res/layout/cache_information_item.xml
index e9df7f5..5d53340 100644
--- a/main/res/layout/cache_information_item.xml
+++ b/main/res/layout/cache_information_item.xml
@@ -21,7 +21,7 @@
android:text="@null"
android:textColor="?text_color_headline"
android:textIsSelectable="false"
- android:textSize="12dip" />
+ android:textSize="12sp" />
<TextView
android:id="@+id/value"
@@ -33,7 +33,7 @@
android:gravity="center_vertical"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<LinearLayout
android:id="@+id/stars"
@@ -57,7 +57,7 @@
android:gravity="center_vertical"
android:textColor="?text_color_grey"
android:textIsSelectable="false"
- android:textSize="11dip"
+ android:textSize="12sp"
android:visibility="gone" />
</RelativeLayout> \ No newline at end of file
diff --git a/main/res/layout/caches.xml b/main/res/layout/caches.xml
index 147a596..5c3abbc 100644
--- a/main/res/layout/caches.xml
+++ b/main/res/layout/caches.xml
@@ -6,34 +6,11 @@
<LinearLayout style="@style/action_bar" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goHome" />
+ <include layout="@layout/actionbar_title" />
- <View style="@style/action_bar_separator" />
+ <include layout="@layout/actionbar_progress" />
- <TextView
- style="@style/action_bar_title"
- android:clickable="true"
- android:onClick="selectList" />
-
- <ProgressBar
- style="@style/action_bar_progress"
- android:visibility="gone" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goMap"
- android:src="@drawable/actionbar_map" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_button_map" />
</LinearLayout>
<include layout="@layout/filter_bar" />
diff --git a/main/res/layout/caches_footer.xml b/main/res/layout/caches_footer.xml
index 7182488..ed2de18 100644
--- a/main/res/layout/caches_footer.xml
+++ b/main/res/layout/caches_footer.xml
@@ -13,4 +13,4 @@
android:singleLine="true"
android:text="@string/caches_no_cache"
android:textColor="@color/just_white"
- android:textSize="16dip" />
+ android:textSize="16sp" />
diff --git a/main/res/layout/caches_item.xml b/main/res/layout/caches_item.xml
index 8ea0221..44c0fb3 100644
--- a/main/res/layout/caches_item.xml
+++ b/main/res/layout/caches_item.xml
@@ -49,7 +49,7 @@
android:singleLine="true"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="18dip" />
+ android:textSize="18sp" />
<!-- cache attributes and other info -->
@@ -70,7 +70,7 @@
android:singleLine="true"
android:textColor="?text_color_grey"
android:textIsSelectable="false"
- android:textSize="12dip" />
+ android:textSize="12sp" />
<!-- real text based direction and distance -->
@@ -96,7 +96,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color"
- android:textSize="16dip" />
+ android:textSize="16sp" />
<view
android:id="@+id/direction"
@@ -147,14 +147,14 @@
android:src="@drawable/trackable_all" />
<TextView
- android:id="@+id/favourite"
+ android:id="@+id/favorite"
android:layout_width="35dip"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:layout_marginTop="22dip"
- android:background="?favourite"
+ android:background="?favorite"
android:ellipsize="marquee"
android:gravity="center"
android:lines="1"
@@ -165,7 +165,7 @@
android:singleLine="true"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="12dip"
+ android:textSize="12sp"
android:textStyle="bold" />
</RelativeLayout>
diff --git a/main/res/layout/cacheview.xml b/main/res/layout/cacheview.xml
index 89d7152..3afe5f6 100644
--- a/main/res/layout/cacheview.xml
+++ b/main/res/layout/cacheview.xml
@@ -8,29 +8,9 @@
<LinearLayout style="@style/action_bar" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goHome" />
+ <include layout="@layout/actionbar_title" />
- <View style="@style/action_bar_separator" />
-
- <TextView style="@style/action_bar_title" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- android:id="@+id/defaultNavigation"
- style="@style/action_bar_action"
- android:longClickable="true"
- android:onClick="startDefaultNavigation"
- android:src="@drawable/actionbar_compass_dark" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_button_compass" />
</LinearLayout>
<android.support.v4.view.ViewPager
@@ -47,6 +27,6 @@
app:footerColor="#ff888888"
app:footerIndicatorHeight="3dp"
app:footerIndicatorStyle="underline"
- app:textSize="16dp" />
+ app:textSize="16sp" />
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/cacheview_description.xml b/main/res/layout/cacheview_description.xml
index 732ab91..5c05c20 100644
--- a/main/res/layout/cacheview_description.xml
+++ b/main/res/layout/cacheview_description.xml
@@ -20,7 +20,7 @@
android:linksClickable="true"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip"
+ android:textSize="14sp"
android:visibility="gone" />
<!-- Long description -->
@@ -34,7 +34,7 @@
android:linksClickable="true"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip"
+ android:textSize="14sp"
android:visibility="gone" />
<Button
@@ -88,7 +88,7 @@
android:linksClickable="true"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/hint_spoilerlink"
@@ -100,7 +100,7 @@
android:drawablePadding="3dip"
android:text="@string/cache_menu_spoilers"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<!-- Personal note box -->
@@ -128,7 +128,7 @@
android:linksClickable="true"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/edit_personalnote"
diff --git a/main/res/layout/cacheview_details.xml b/main/res/layout/cacheview_details.xml
index 54d4719..484385e 100644
--- a/main/res/layout/cacheview_details.xml
+++ b/main/res/layout/cacheview_details.xml
@@ -72,7 +72,7 @@
android:layout_marginRight="130dip"
android:paddingRight="3dip"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/offline_refresh"
@@ -112,7 +112,7 @@
android:layout_marginRight="130dip"
android:paddingRight="3dip"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/change_list"
@@ -150,7 +150,7 @@
android:layout_marginRight="130dip"
android:paddingRight="3dip"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/add_to_watchlist"
@@ -196,7 +196,7 @@
android:layout_marginRight="130dip"
android:paddingRight="3dip"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/add_to_favpoint"
@@ -241,7 +241,7 @@
android:padding="3dip"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<!-- Map Preview Box -->
diff --git a/main/res/layout/cacheview_logs_item.xml b/main/res/layout/cacheview_logs_item.xml
index b54446e..99822d3 100644
--- a/main/res/layout/cacheview_logs_item.xml
+++ b/main/res/layout/cacheview_logs_item.xml
@@ -17,7 +17,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color"
- android:textSize="18dip" />
+ android:textSize="18sp" />
<LinearLayout
android:id="@+id/detail_box"
@@ -46,7 +46,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color_headline"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/type"
@@ -59,7 +59,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color_headline"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/count"
@@ -72,7 +72,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color_headline"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<ImageView
@@ -92,7 +92,7 @@
android:layout_toRightOf="@id/detail_box"
android:orientation="vertical"
android:paddingLeft="3dip"
- android:textSize="14dip" >
+ android:textSize="14sp" >
<TextView
android:id="@+id/log"
@@ -100,10 +100,10 @@
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_marginTop="22dip"
- android:autoLink="web"
+ android:linksClickable="true"
android:gravity="left"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/log_images"
@@ -114,7 +114,7 @@
android:drawableLeft="?log_img_icon"
android:drawablePadding="3dip"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
</RelativeLayout> \ No newline at end of file
diff --git a/main/res/layout/coords.xml b/main/res/layout/coords.xml
index ddb2f4e..4603360 100644
--- a/main/res/layout/coords.xml
+++ b/main/res/layout/coords.xml
@@ -10,13 +10,6 @@
<TextView
style="@style/action_bar_title"
android:text="@string/cache_coordinates" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- android:id="@+id/actionBarManualbutton"
- style="@style/action_bar_action"
- android:src="@drawable/actionbar_manual" />
</LinearLayout>
<ScrollView
diff --git a/main/res/layout/edit_waypoint_activity.xml b/main/res/layout/edit_waypoint_activity.xml
index 3fbd19e..657e9f4 100644
--- a/main/res/layout/edit_waypoint_activity.xml
+++ b/main/res/layout/edit_waypoint_activity.xml
@@ -5,23 +5,7 @@
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>
+ <include layout="@layout/actionbar" />
<ScrollView
android:layout_width="fill_parent"
diff --git a/main/res/layout/editor.xml b/main/res/layout/editor.xml
deleted file mode 100644
index d556836..0000000
--- a/main/res/layout/editor.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/linearLayout1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
-
- <EditText
- android:id="@+id/editorEditText"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:inputType="textMultiLine"
- android:scrollbars="vertical" >
-
- <requestFocus />
- </EditText>
-
- <Button
- android:id="@+id/editorSave"
- style="@style/button_full"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/editor_save" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/fragment_edit_note.xml b/main/res/layout/fragment_edit_note.xml
new file mode 100644
index 0000000..68e2b2c
--- /dev/null
+++ b/main/res/layout/fragment_edit_note.xml
@@ -0,0 +1,15 @@
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/edit_note"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="vertical">
+
+ <EditText
+ android:id="@+id/note"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:imeOptions="actionDone"/>
+</LinearLayout>
diff --git a/main/res/layout/gpx.xml b/main/res/layout/gpx.xml
index 2be131d..08f5bc1 100644
--- a/main/res/layout/gpx.xml
+++ b/main/res/layout/gpx.xml
@@ -4,16 +4,7 @@
android:layout_height="fill_parent"
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" />
- </LinearLayout>
+ <include layout="@layout/actionbar"/>
<ListView
android:id="@android:id/list"
diff --git a/main/res/layout/gpx_item.xml b/main/res/layout/gpx_item.xml
index df735bc..f0a0647 100644
--- a/main/res/layout/gpx_item.xml
+++ b/main/res/layout/gpx_item.xml
@@ -22,7 +22,7 @@
android:singleLine="true"
android:textColor="?text_color_grey"
android:textIsSelectable="false"
- android:textSize="12dip" />
+ android:textSize="12sp" />
<TextView
android:id="@+id/filename"
@@ -35,6 +35,6 @@
android:singleLine="true"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="22dip" />
+ android:textSize="22sp" />
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/init.xml b/main/res/layout/init.xml
index 26137fc..e784b21 100644
--- a/main/res/layout/init.xml
+++ b/main/res/layout/init.xml
@@ -5,23 +5,7 @@
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>
+ <include layout="@layout/actionbar" />
<ScrollView
android:layout_width="fill_parent"
@@ -44,7 +28,32 @@
style="@style/separator_horizontal_headline"
android:text="@string/init_geocaching" />
</RelativeLayout>
-
+
+ <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/gc_option"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:padding="1dip"
+ 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="14sp"
+ android:textColor="?text_color"
+ android:text="@string/init_gc_activate" />
+ </LinearLayout>
+
<TextView
android:id="@+id/legal_note"
android:layout_width="wrap_content"
@@ -58,7 +67,7 @@
android:text="@string/legal_note"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<EditText
android:id="@+id/username"
@@ -101,14 +110,14 @@
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:padding="3dip"
- android:text="@string/init_oc_username_description"
+ android:text="@string/init_oc_de_description"
android:textColor="?text_color"
android:textSize="14sp" />
- <EditText
- android:id="@+id/oc_username"
- style="@style/edittext_full"
- android:hint="@string/init_oc_username" />
+ <Button
+ android:id="@+id/register_oc_de"
+ style="@style/button_full"
+ android:text="@string/init_register_oc_de" />
<!-- ** -->
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -149,7 +158,7 @@
android:text="@string/about_twitter"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/authorize_twitter"
@@ -190,7 +199,7 @@
android:layout_width="wrap_content"
android:layout_weight="2"
android:text="@string/init_signature_template_button"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/signature_help"
@@ -198,7 +207,7 @@
android:layout_width="wrap_content"
android:layout_weight="1"
android:text="@string/init_signature_help_button"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<CheckBox
@@ -386,7 +395,7 @@
android:text="@string/init_showwaypoint_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<!-- maps -->
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -411,7 +420,7 @@
android:text="@string/init_mapsources_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Spinner
android:id="@+id/mapsource"
@@ -432,7 +441,7 @@
android:text="@string/init_map_directory_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<LinearLayout
android:id="@+id/init_mapdir_group"
@@ -466,7 +475,7 @@
android:padding="3dip"
android:text="@string/init_rendertheme_folder"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<LinearLayout
android:id="@+id/init_themefilegroup"
@@ -513,7 +522,7 @@
android:text="@string/init_gpx_exportdir_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<LinearLayout
android:id="@+id/init_gpx_export_group"
@@ -559,7 +568,7 @@
android:text="@string/init_gpx_importdir_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<LinearLayout
android:id="@+id/init_gpx_import_group"
@@ -612,7 +621,7 @@
android:text="@string/init_altitude_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<!-- ** -->
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -636,7 +645,7 @@
android:text="@string/init_default_navigation_tool_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Spinner
android:id="@+id/default_navigation_tool"
@@ -656,7 +665,7 @@
android:text="@string/init_default_navigation_tool_2_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Spinner
android:id="@+id/default_navigation_tool_2"
@@ -686,7 +695,7 @@
android:text="@string/init_sendToCgeo_name"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<EditText
android:id="@+id/webDeviceName"
@@ -710,7 +719,7 @@
android:text="@string/init_sendToCgeo_description"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/sendToCgeo_register"
@@ -740,7 +749,7 @@
android:text="@null"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<LinearLayout
android:layout_width="fill_parent"
@@ -778,7 +787,7 @@
android:text="@string/init_backup_note"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<!-- ** -->
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -802,7 +811,7 @@
android:text="@string/init_dbonsdcard_note"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<CheckBox
android:id="@+id/dbonsdcard"
@@ -831,7 +840,7 @@
android:text="@string/init_debug_note"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<CheckBox
android:id="@+id/debug"
@@ -840,4 +849,4 @@
</LinearLayout>
</ScrollView>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/main/res/layout/livemapinfo.xml b/main/res/layout/livemapinfo.xml
index 5dd8ccd..1b1e9ea 100644
--- a/main/res/layout/livemapinfo.xml
+++ b/main/res/layout/livemapinfo.xml
@@ -17,7 +17,7 @@
android:layout_height="wrap_content"
android:text="@string/live_map_notification"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<CheckBox
android:id="@+id/live_map_hint_hide"
diff --git a/main/res/layout/main.xml b/main/res/layout/main.xml
index 0f9aff0..40e3d6a 100644
--- a/main/res/layout/main.xml
+++ b/main/res/layout/main.xml
@@ -13,19 +13,7 @@
<TextView style="@style/action_bar_title" />
- <View style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goSearch"
- android:src="@drawable/actionbar_search" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_button_search" />
</LinearLayout>
<fragment
@@ -61,7 +49,7 @@
android:onClick="cgeoFindOnMap"
android:orientation="vertical" >
- <View
+ <ImageView
android:id="@+id/map"
style="@style/icon_mainscreen"
android:background="@drawable/main_live" />
@@ -77,7 +65,7 @@
android:layout_margin="4dip"
android:orientation="vertical" >
- <View
+ <ImageView
android:id="@+id/nearest"
style="@style/icon_mainscreen"
android:background="@drawable/main_nearby_disabled" />
@@ -104,7 +92,7 @@
android:layout_alignParentTop="true"
android:orientation="vertical" >
- <View
+ <ImageView
android:id="@+id/search_offline"
style="@style/icon_mainscreen"
android:background="@drawable/main_stored" />
@@ -130,7 +118,7 @@
android:onClick="cgeoSearch"
android:orientation="vertical" >
- <View
+ <ImageView
android:id="@+id/advanced_button"
style="@style/icon_mainscreen"
android:background="@drawable/main_search" />
@@ -147,7 +135,7 @@
android:onClick="cgeoPoint"
android:orientation="vertical" >
- <View
+ <ImageView
android:id="@+id/any_button"
style="@style/icon_mainscreen"
android:background="@drawable/main_any" />
@@ -164,7 +152,7 @@
android:onClick="cgeoFilter"
android:orientation="vertical" >
- <View
+ <ImageView
android:id="@+id/filter_button"
style="@style/icon_mainscreen"
android:background="@drawable/main_filter" />
@@ -178,41 +166,6 @@
</LinearLayout>
<!-- ** -->
- <RelativeLayout
- android:id="@+id/helper"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="64dip"
- android:layout_marginLeft="16dip"
- android:layout_marginRight="16dip"
- android:background="@drawable/helper_bcg"
- android:visibility="gone" >
-
- <ImageView
- android:layout_width="32dip"
- android:layout_height="32dip"
- android:layout_alignParentLeft="true"
- android:layout_gravity="center"
- android:layout_margin="4dip"
- android:gravity="center"
- android:scaleType="center"
- android:src="@drawable/actionbar_manual" />
-
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_gravity="center"
- android:layout_marginLeft="34dip"
- android:gravity="center"
- android:padding="4dip"
- android:text="@string/helper"
- android:textColor="@color/text_icon"
- android:textSize="14dip" />
- </RelativeLayout>
- <!-- ** -->
-
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/main/res/layout/map_google.xml b/main/res/layout/map_google.xml
index 723b7157..5e4d82d 100644
--- a/main/res/layout/map_google.xml
+++ b/main/res/layout/map_google.xml
@@ -6,30 +6,11 @@
<LinearLayout style="@style/action_bar" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goHome" />
+ <include layout="@layout/actionbar_title" />
- <View style="@style/action_bar_separator" />
+ <include layout="@layout/actionbar_progress" />
- <TextView style="@style/action_bar_title" />
-
- <ProgressBar
- style="@style/action_bar_progress"
- android:visibility="gone" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageSwitcher
- android:id="@+id/my_position"
- style="@style/action_bar_action" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_button_myposition" />
</LinearLayout>
<include layout="@layout/filter_bar" />
@@ -52,7 +33,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="@color/text_icon"
- android:textSize="12dip"
+ android:textSize="12sp"
android:visibility="gone" />
<view
diff --git a/main/res/layout/map_mapsforge.xml b/main/res/layout/map_mapsforge.xml
index f3b183e..f05ddb0 100644
--- a/main/res/layout/map_mapsforge.xml
+++ b/main/res/layout/map_mapsforge.xml
@@ -6,30 +6,11 @@
<LinearLayout style="@style/action_bar" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goHome" />
+ <include layout="@layout/actionbar_title" />
- <View style="@style/action_bar_separator" />
+ <include layout="@layout/actionbar_progress" />
- <TextView style="@style/action_bar_title" />
-
- <ProgressBar
- style="@style/action_bar_progress"
- android:visibility="gone" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageSwitcher
- android:id="@+id/my_position"
- style="@style/action_bar_action" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_button_myposition" />
</LinearLayout>
<include layout="@layout/filter_bar" />
@@ -52,7 +33,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="@color/text_icon"
- android:textSize="12dip"
+ android:textSize="12sp"
android:visibility="gone" />
<view
diff --git a/main/res/layout/map_mapsforge_old.xml b/main/res/layout/map_mapsforge_old.xml
index 44b3387..ff2b9af 100644
--- a/main/res/layout/map_mapsforge_old.xml
+++ b/main/res/layout/map_mapsforge_old.xml
@@ -6,30 +6,11 @@
<LinearLayout style="@style/action_bar" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goHome" />
+ <include layout="@layout/actionbar_title" />
- <View style="@style/action_bar_separator" />
+ <include layout="@layout/actionbar_progress" />
- <TextView style="@style/action_bar_title" />
-
- <ProgressBar
- style="@style/action_bar_progress"
- android:visibility="gone" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageSwitcher
- android:id="@+id/my_position"
- style="@style/action_bar_action" />
-
- <View style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_button_myposition" />
</LinearLayout>
<include layout="@layout/filter_bar" />
@@ -52,7 +33,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="@color/text_icon"
- android:textSize="12dip"
+ android:textSize="12sp"
android:visibility="gone" />
<view
diff --git a/main/res/layout/map_static.xml b/main/res/layout/map_static.xml
index ff0435c..edf6c6e 100644
--- a/main/res/layout/map_static.xml
+++ b/main/res/layout/map_static.xml
@@ -4,16 +4,7 @@
android:layout_height="fill_parent"
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" />
- </LinearLayout>
+ <include layout="@layout/actionbar"/>
<ScrollView
android:layout_width="fill_parent"
diff --git a/main/res/layout/mapfile_item.xml b/main/res/layout/mapfile_item.xml
index c30315a..c665894 100644
--- a/main/res/layout/mapfile_item.xml
+++ b/main/res/layout/mapfile_item.xml
@@ -22,7 +22,7 @@
android:singleLine="true"
android:textColor="?text_color_grey"
android:textIsSelectable="false"
- android:textSize="12dip" />
+ android:textSize="12sp" />
<TextView
android:id="@+id/mapfilename"
@@ -35,6 +35,6 @@
android:singleLine="true"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="22dip" />
+ android:textSize="22sp" />
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/navigate.xml b/main/res/layout/navigate.xml
index 0c95958..9843b2a 100644
--- a/main/res/layout/navigate.xml
+++ b/main/res/layout/navigate.xml
@@ -1,134 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
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" />
+ <LinearLayout
+ android:id="@+id/info1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
- </LinearLayout>
+ <TextView
+ android:id="@+id/destination"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textColor="?text_color"
+ android:textSize="14sp" />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
+ <TextView
+ android:id="@+id/cacheinfo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textColor="?text_color"
+ android:textSize="14sp" />
- <LinearLayout
+ <RelativeLayout
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
+ android:layout_height="30dip" >
<TextView
- android:id="@+id/destination"
+ android:id="@+id/heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_alignParentLeft="true"
+ android:layout_gravity="left"
+ android:layout_marginLeft="3dip"
+ android:text="@null"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="26sp" />
<TextView
- android:id="@+id/cacheinfo"
+ android:id="@+id/distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_alignParentRight="true"
+ android:layout_gravity="right"
+ android:layout_marginRight="3dip"
+ android:text="@null"
android:textColor="?text_color"
- android:textSize="14dip" />
-
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="30dip" >
-
- <TextView
- android:id="@+id/heading"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_gravity="left"
- android:layout_marginLeft="3dip"
- android:text="@null"
- android:textColor="?text_color"
- android:textSize="26dip" />
-
- <TextView
- android:id="@+id/distance"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_gravity="right"
- android:layout_marginRight="3dip"
- android:text="@null"
- android:textColor="?text_color"
- android:textSize="26dip" />
- </RelativeLayout>
- </LinearLayout>
-
- <view
- android:id="@+id/rose"
- android:layout_width="fill_parent"
- android:layout_height="295dip"
- android:layout_centerInParent="true"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="1dip"
- android:layout_marginLeft="1dip"
- android:layout_marginRight="1dip"
- android:layout_marginTop="6dip"
- class="cgeo.geocaching.ui.CompassView"
- android:gravity="center"
- android:keepScreenOn="true"
- android:minHeight="289dip"
- android:minWidth="289dip"
- android:padding="4dip" />
-
- <LinearLayout
+ android:textSize="26sp" />
+ </RelativeLayout>
+ </LinearLayout>
+
+
+ <LinearLayout
+ android:id="@+id/info2"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_marginLeft="6dip"
+ android:layout_marginRight="6dip"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/nav_location"
+ style="@style/location_current"
+ android:text="@string/loc_trying" />
+
+ <RelativeLayout
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginLeft="6dip"
- android:layout_marginRight="6dip"
- android:orientation="vertical" >
+ android:layout_height="16dip" >
<TextView
- android:id="@+id/nav_location"
- style="@style/location_current"
- android:text="@string/loc_trying" />
-
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="16dip" >
-
- <TextView
- android:id="@+id/nav_type"
- style="@style/location_current_type"
- android:textColor="?text_color_grey"
- android:textIsSelectable="false" />
-
- <TextView
- android:id="@+id/nav_accuracy"
- style="@style/location_current_accuracy"
- android:textColor="?text_color_grey"
- android:textIsSelectable="false" />
-
- <TextView
- android:id="@+id/nav_satellites"
- style="@style/location_current_satellites"
- android:textColor="?text_color_grey"
- android:textIsSelectable="false" />
- </RelativeLayout>
- </LinearLayout>
- </RelativeLayout>
-
-</LinearLayout> \ No newline at end of file
+ android:id="@+id/nav_type"
+ style="@style/location_current_type"
+ android:textColor="?text_color_grey"
+ android:textIsSelectable="false" />
+
+ <TextView
+ android:id="@+id/nav_accuracy"
+ style="@style/location_current_accuracy"
+ android:textColor="?text_color_grey"
+ android:textIsSelectable="false" />
+
+ <TextView
+ android:id="@+id/nav_satellites"
+ style="@style/location_current_satellites"
+ android:textColor="?text_color_grey"
+ android:textIsSelectable="false" />
+ </RelativeLayout>
+ </LinearLayout>
+
+ <view
+ android:id="@+id/rose"
+ android:layout_width="fill_parent"
+ android:layout_height="295dip"
+ android:layout_below="@id/info1"
+ android:layout_above="@id/info2"
+ android:layout_centerInParent="true"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="1dip"
+ android:layout_marginLeft="1dip"
+ android:layout_marginRight="1dip"
+ android:layout_marginTop="6dip"
+ class="cgeo.geocaching.ui.CompassView"
+ android:gravity="center"
+ android:keepScreenOn="true"
+ android:minHeight="289dip"
+ android:minWidth="289dip"
+ android:padding="4dip" />
+
+
+</RelativeLayout> \ No newline at end of file
diff --git a/main/res/layout/point.xml b/main/res/layout/point.xml
index 3c133d8..baa568c 100644
--- a/main/res/layout/point.xml
+++ b/main/res/layout/point.xml
@@ -5,23 +5,7 @@
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>
+ <include layout="@layout/actionbar" />
<ListView
android:id="@+id/historyList"
diff --git a/main/res/layout/popup.xml b/main/res/layout/popup.xml
index ff64c91..584eb58 100644
--- a/main/res/layout/popup.xml
+++ b/main/res/layout/popup.xml
@@ -7,25 +7,9 @@
<LinearLayout style="@style/action_bar" >
- <TextView style="@style/action_bar_title" />
+ <include layout="@layout/actionbar_title_no_home" />
- <View style="@style/action_bar_separator" />
-
- <ImageView
- android:id="@+id/defaultNavigation"
- style="@style/action_bar_action"
- android:longClickable="true"
- android:onClick="goDefaultNavigation"
- android:src="@drawable/actionbar_compass_dark" />
-
- <View
- android:id="@+id/separator"
- style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_button_compass" />
</LinearLayout>
<ScrollView
@@ -75,7 +59,7 @@
android:paddingRight="3dip"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<Button
android:id="@+id/offline_refresh"
diff --git a/main/res/layout/recaptcha_dialog.xml b/main/res/layout/recaptcha_dialog.xml
index cbbbd0b..ac9f746 100644
--- a/main/res/layout/recaptcha_dialog.xml
+++ b/main/res/layout/recaptcha_dialog.xml
@@ -29,6 +29,6 @@
android:paddingLeft="3dip"
android:text="@string/caches_recaptcha_explanation"
android:textColor="@color/text_grey_dark"
- android:textSize="12dip" />
+ android:textSize="12sp" />
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/search.xml b/main/res/layout/search.xml
index 6d0bf91..a0a699d 100644
--- a/main/res/layout/search.xml
+++ b/main/res/layout/search.xml
@@ -6,23 +6,7 @@
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>
+ <include layout="@layout/actionbar" />
<ScrollView
android:layout_width="fill_parent"
diff --git a/main/res/layout/spoilers.xml b/main/res/layout/spoilers.xml
index 233972a..2027b7a 100644
--- a/main/res/layout/spoilers.xml
+++ b/main/res/layout/spoilers.xml
@@ -5,16 +5,7 @@
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" />
- </LinearLayout>
+ <include layout="@layout/actionbar"/>
<include layout="@layout/caches_images" />
diff --git a/main/res/layout/status.xml b/main/res/layout/status.xml
index 4b1d55f..ef2a57a 100644
--- a/main/res/layout/status.xml
+++ b/main/res/layout/status.xml
@@ -24,6 +24,6 @@
android:padding="4dip"
android:textColor="@color/text_icon"
android:textIsSelectable="false"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</RelativeLayout> \ No newline at end of file
diff --git a/main/res/layout/touch.xml b/main/res/layout/touch.xml
index 09a8033..7791409 100644
--- a/main/res/layout/touch.xml
+++ b/main/res/layout/touch.xml
@@ -7,24 +7,9 @@
<LinearLayout style="@style/action_bar" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goHome" />
+ <include layout="@layout/actionbar_title" />
- <View style="@style/action_bar_separator" />
-
- <TextView style="@style/action_bar_title" />
-
- <View style="@style/action_bar_separator" />
-
- <ProgressBar
- style="@style/action_bar_progress"
- android:visibility="gone" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_progress" />
</LinearLayout>
<ScrollView
@@ -87,7 +72,7 @@
android:layout_height="wrap_content"
android:layout_gravity="left"
android:gravity="center"
- android:padding="1px" />
+ android:padding="2sp" />
<TextView
android:layout_width="wrap_content"
@@ -97,7 +82,7 @@
android:paddingRight="3dip"
android:text="@string/visit_tweet"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<Button
diff --git a/main/res/layout/trackable_activity.xml b/main/res/layout/trackable_activity.xml
index fe61409..14120e0 100644
--- a/main/res/layout/trackable_activity.xml
+++ b/main/res/layout/trackable_activity.xml
@@ -6,23 +6,7 @@
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>
+ <include layout="@layout/actionbar" />
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
@@ -38,6 +22,6 @@
app:footerColor="#ff888888"
app:footerIndicatorHeight="3dp"
app:footerIndicatorStyle="underline"
- app:textSize="16dp" />
+ app:textSize="16sp" />
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/trackable_details_view.xml b/main/res/layout/trackable_details_view.xml
index c4aac0e..07f4e4e 100644
--- a/main/res/layout/trackable_details_view.xml
+++ b/main/res/layout/trackable_details_view.xml
@@ -41,7 +41,7 @@
android:linksClickable="true"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip"
+ android:textSize="14sp"
android:visibility="gone" />
</LinearLayout>
@@ -69,7 +69,7 @@
android:linksClickable="true"
android:textColor="?text_color"
android:textColorLink="?text_color_link"
- android:textSize="14dip"
+ android:textSize="14sp"
android:visibility="gone" />
</LinearLayout>
diff --git a/main/res/layout/trackable_logs_img.xml b/main/res/layout/trackable_logs_img.xml
deleted file mode 100644
index aaed32b..0000000
--- a/main/res/layout/trackable_logs_img.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?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" >
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left|top"
- android:drawableLeft="?log_img_icon"
- android:drawablePadding="3dip"
- android:textColor="?text_color"
- android:textSize="14dip" />
-
-</LinearLayout> \ 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 52a38a9..d28231c 100644
--- a/main/res/layout/trackable_logs_item.xml
+++ b/main/res/layout/trackable_logs_item.xml
@@ -17,9 +17,10 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color"
- android:textSize="18dip" />
+ android:textSize="18sp" />
<LinearLayout
+ android:id="@+id/detail_box"
android:layout_width="102dip"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
@@ -46,7 +47,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color_headline"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/type"
@@ -59,7 +60,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color_headline"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/location"
@@ -72,7 +73,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color_headline"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<ImageView
@@ -92,7 +93,7 @@
android:layout_marginLeft="102dip"
android:orientation="vertical"
android:padding="3dip"
- android:textSize="14dip" >
+ android:textSize="14sp" >
<TextView
android:id="@+id/log"
@@ -104,7 +105,18 @@
android:gravity="left"
android:padding="3dip"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
+
+ <TextView
+ android:id="@+id/log_images"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left|top"
+ android:layout_marginTop="3dip"
+ android:drawableLeft="?log_img_icon"
+ android:drawablePadding="3dip"
+ android:textColor="?text_color"
+ android:textSize="14sp" />
</LinearLayout>
</RelativeLayout> \ No newline at end of file
diff --git a/main/res/layout/useful_apps.xml b/main/res/layout/useful_apps.xml
deleted file mode 100644
index 2a3d14e..0000000
--- a/main/res/layout/useful_apps.xml
+++ /dev/null
@@ -1,33 +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: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" />
- </LinearLayout>
-
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:padding="4dip" >
-
- <LinearLayout
- android:id="@+id/parent"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
- </LinearLayout>
- </ScrollView>
-
-</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/useful_apps_activity.xml b/main/res/layout/useful_apps_activity.xml
new file mode 100644
index 0000000..84bcf39
--- /dev/null
+++ b/main/res/layout/useful_apps_activity.xml
@@ -0,0 +1,23 @@
+<?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:background="?background_color"
+ android:orientation="vertical" >
+
+ <include layout="@layout/actionbar" />
+
+ <ListView
+ android:id="@+id/apps_list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:cacheColorHint="?background_color"
+ android:divider="?background_color"
+ android:fastScrollEnabled="true"
+ android:footerDividersEnabled="false"
+ android:headerDividersEnabled="false"
+ android:listSelector="?background_color"
+ android:padding="4dip" >
+ </ListView>
+
+</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/useful_apps_item.xml b/main/res/layout/useful_apps_item.xml
index 5c8f6f0..70e7baf 100644
--- a/main/res/layout/useful_apps_item.xml
+++ b/main/res/layout/useful_apps_item.xml
@@ -4,6 +4,7 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="10dip"
+ android:descendantFocusability="blocksDescendants"
android:orientation="vertical" >
<RelativeLayout style="@style/separator_horizontal_layout" >
@@ -43,7 +44,7 @@
android:textColor="?text_color"
android:textColorLink="?text_color_link"
android:textIsSelectable="false"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/visit.xml b/main/res/layout/visit.xml
index 43a3308..e0294da 100644
--- a/main/res/layout/visit.xml
+++ b/main/res/layout/visit.xml
@@ -7,24 +7,9 @@
<LinearLayout style="@style/action_bar" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goHome" />
+ <include layout="@layout/actionbar_title" />
- <View style="@style/action_bar_separator" />
-
- <TextView style="@style/action_bar_title" />
-
- <View style="@style/action_bar_separator" />
-
- <ProgressBar
- style="@style/action_bar_progress"
- android:visibility="gone" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_progress" />
</LinearLayout>
<ScrollView
@@ -88,7 +73,7 @@
android:layout_height="wrap_content"
android:layout_gravity="left"
android:gravity="center"
- android:padding="1px" />
+ android:padding="2sp" />
<TextView
android:layout_width="wrap_content"
@@ -98,7 +83,7 @@
android:paddingRight="3dip"
android:text="@string/visit_tweet"
android:textColor="?text_color"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<Button
@@ -185,7 +170,7 @@
android:layout_weight="1"
android:gravity="right"
android:text="@string/log_tb_changeall"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
diff --git a/main/res/layout/visit_image.xml b/main/res/layout/visit_image.xml
index 7997406..fd8eaea 100644
--- a/main/res/layout/visit_image.xml
+++ b/main/res/layout/visit_image.xml
@@ -7,24 +7,9 @@
<LinearLayout style="@style/action_bar" >
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goHome" />
+ <include layout="@layout/actionbar_title" />
- <View style="@style/action_bar_separator" />
-
- <TextView style="@style/action_bar_title" />
-
- <View style="@style/action_bar_separator" />
-
- <ProgressBar
- style="@style/action_bar_progress"
- android:visibility="gone" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_progress" />
</LinearLayout>
<ScrollView
@@ -98,6 +83,13 @@
android:minLines="5"
android:singleLine="false" />
+ <Spinner
+ android:id="@+id/logImageScale"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:entries="@array/log_image_scales"
+ android:prompt="@string/log_image_scale" />
+
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/main/res/layout/visit_trackable.xml b/main/res/layout/visit_trackable.xml
index 360e553..1eab116 100644
--- a/main/res/layout/visit_trackable.xml
+++ b/main/res/layout/visit_trackable.xml
@@ -27,7 +27,7 @@
android:singleLine="true"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="14dip" />
+ android:textSize="14sp" />
<TextView
android:id="@+id/trackcode"
@@ -41,7 +41,7 @@
android:singleLine="true"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout>
<TextView
@@ -57,6 +57,6 @@
android:singleLine="true"
android:textColor="?text_color"
android:textIsSelectable="false"
- android:textSize="14dip" />
+ android:textSize="14sp" />
</LinearLayout> \ No newline at end of file
diff --git a/main/res/layout/waypoint_item.xml b/main/res/layout/waypoint_item.xml
index 29106d8..17690ff 100644
--- a/main/res/layout/waypoint_item.xml
+++ b/main/res/layout/waypoint_item.xml
@@ -21,7 +21,7 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="?text_color"
- android:textSize="18dp" />
+ android:textSize="18sp" />
<TextView
android:id="@+id/info"
@@ -34,7 +34,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color_headline"
- android:textSize="14dp"
+ android:textSize="14sp"
android:visibility="gone" />
</LinearLayout>
@@ -59,7 +59,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?text_color_headline"
- android:textSize="14dp"
+ android:textSize="14sp"
android:visibility="gone" />
<TextView
@@ -68,7 +68,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:textColor="?text_color"
- android:textSize="14dp"
+ android:textSize="14sp"
android:visibility="gone" />
<View
diff --git a/main/res/layout/waypoint_popup.xml b/main/res/layout/waypoint_popup.xml
index 869ffa0..c8b257c 100644
--- a/main/res/layout/waypoint_popup.xml
+++ b/main/res/layout/waypoint_popup.xml
@@ -7,25 +7,9 @@
<LinearLayout style="@style/action_bar" >
- <TextView style="@style/action_bar_title" />
+ <include layout="@layout/actionbar_title_no_home" />
- <View style="@style/action_bar_separator" />
-
- <ImageView
- android:id="@+id/defaultNavigation"
- style="@style/action_bar_action"
- android:longClickable="true"
- android:onClick="goDefaultNavigation"
- android:src="@drawable/actionbar_compass_dark" />
-
- <View
- android:id="@+id/separator"
- style="@style/action_bar_separator" />
-
- <ImageView
- style="@style/action_bar_action"
- android:onClick="goManual"
- android:src="@drawable/actionbar_manual" />
+ <include layout="@layout/actionbar_button_compass" />
</LinearLayout>
<ScrollView
diff --git a/main/res/menu/abstract_logging_activity.xml b/main/res/menu/abstract_logging_activity.xml
new file mode 100644
index 0000000..e041b37
--- /dev/null
+++ b/main/res/menu/abstract_logging_activity.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_signature"
+ android:icon="@drawable/ic_menu_edit"
+ android:title="@string/init_signature">
+ </item>
+ <item
+ android:id="@+id/menu_templates"
+ android:icon="@drawable/ic_menu_add"
+ android:title="@string/log_add">
+ <menu/> <!-- filled dynamically -->
+ </item>
+ <item
+ android:id="@+id/menu_smilies"
+ android:icon="@drawable/ic_menu_emoticons"
+ android:title="@string/log_smilies">
+ <menu/> <!-- filled dynamically -->
+ </item>
+
+</menu> \ No newline at end of file
diff --git a/main/res/menu/abstract_popup_activity.xml b/main/res/menu/abstract_popup_activity.xml
new file mode 100644
index 0000000..855a756
--- /dev/null
+++ b/main/res/menu/abstract_popup_activity.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_default_navigation"
+ android:icon="@drawable/ic_menu_compass"
+ android:title="@string/cache_menu_navigate"> <!-- will be replaced -->
+ </item>
+ <item
+ android:id="@+id/menu_navigate"
+ android:icon="@drawable/ic_menu_mapmode"
+ android:title="@string/cache_menu_navigate">
+ </item>
+ <item
+ android:id="@+id/menu_log_visit_offline"
+ android:icon="@drawable/ic_menu_edit"
+ android:title="@string/cache_menu_visit_offline">
+ </item>
+ <item
+ android:id="@+id/menu_log_visit"
+ android:icon="@drawable/ic_menu_edit"
+ android:title="@string/cache_menu_visit">
+ </item>
+ <item
+ android:id="@+id/menu_caches_around"
+ android:icon="@drawable/ic_menu_rotate"
+ android:title="@string/cache_menu_around">
+ </item>
+ <item
+ android:id="@+id/menu_show_in_browser"
+ android:icon="@drawable/ic_menu_info_details"
+ android:title="@string/cache_menu_browser">
+ </item>
+
+</menu> \ No newline at end of file
diff --git a/main/res/menu/compass_activity_options.xml b/main/res/menu/compass_activity_options.xml
new file mode 100644
index 0000000..f78aad6
--- /dev/null
+++ b/main/res/menu/compass_activity_options.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_switch_compass_gps"
+ android:icon="@drawable/ic_menu_compass"
+ android:title="@string/use_gps"> <!-- will be replaced in code -->
+ </item>
+ <item
+ android:id="@+id/menu_map"
+ android:icon="@drawable/ic_menu_mapmode"
+ android:title="@string/caches_on_map">
+ </item>
+ <item
+ android:id="@+id/menu_edit_destination"
+ android:icon="@drawable/ic_menu_edit"
+ android:title="@string/destination_set">
+ </item>
+ <item
+ android:id="@+id/menu_select_destination"
+ android:icon="@drawable/ic_menu_myplaces"
+ android:title="@string/destination_select">
+ <menu/> <!-- filled dynamically -->
+ </item>
+ <item
+ android:id="@+id/menu_tts_start"
+ android:icon="@drawable/ic_menu_start_conversation"
+ android:title="@string/tts_start">
+ </item>
+ <item
+ android:id="@+id/menu_tts_stop"
+ android:icon="@drawable/ic_menu_start_conversation"
+ android:title="@string/tts_stop"
+ android:visible="false">
+ </item>
+</menu> \ No newline at end of file
diff --git a/main/res/menu/images_list_context.xml b/main/res/menu/images_list_context.xml
new file mode 100644
index 0000000..0136e19
--- /dev/null
+++ b/main/res/menu/images_list_context.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/image_open_file"
+ android:title="@string/cache_image_open_file">
+ </item>
+ <item
+ android:id="@+id/image_open_browser"
+ android:title="@string/cache_image_open_browser">
+ </item>
+</menu>
diff --git a/main/res/menu/logging_ui.xml b/main/res/menu/logging_ui.xml
new file mode 100644
index 0000000..f345d4a
--- /dev/null
+++ b/main/res/menu/logging_ui.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/menu_log_visit_offline"
+ android:icon="@drawable/ic_menu_edit"
+ android:title="@string/cache_menu_visit_offline">
+ </item>
+ <item
+ android:id="@+id/menu_log_visit"
+ android:icon="@drawable/ic_menu_edit"
+ android:title="@string/cache_menu_visit">
+ </item>
+</menu> \ No newline at end of file
diff --git a/main/res/menu/main_options.xml b/main/res/menu/main_activity_options.xml
index e06e948..e06e948 100644
--- a/main/res/menu/main_options.xml
+++ b/main/res/menu/main_activity_options.xml
diff --git a/main/res/menu/map_activity.xml b/main/res/menu/map_activity.xml
new file mode 100644
index 0000000..d76f5ca
--- /dev/null
+++ b/main/res/menu/map_activity.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_select_mapview"
+ android:icon="@drawable/ic_menu_mapmode"
+ android:title="@string/map_view_map">
+ <menu>
+ <group
+ android:id="@+id/menu_group_map_sources"
+ android:checkableBehavior="single" >
+ </group>
+ </menu>
+ </item>
+ <item
+ android:id="@+id/menu_map_live"
+ android:icon="@drawable/ic_menu_refresh"
+ android:title="@string/map_live_disable">
+ </item>
+ <item
+ android:id="@+id/menu_store_caches"
+ android:enabled="false"
+ android:icon="@drawable/ic_menu_set_as"
+ android:title="@string/caches_store_offline">
+ </item>
+ <item
+ android:id="@+id/submenu_modes"
+ android:icon="@drawable/ic_menu_mark"
+ android:title="@string/map_modes">
+ <menu>
+ <item
+ android:id="@+id/menu_trail_mode"
+ android:icon="@drawable/ic_menu_trail"
+ android:title="@string/map_trail_hide">
+ </item>
+ <item
+ android:id="@+id/menu_circle_mode"
+ android:icon="@drawable/ic_menu_circle"
+ android:title="@string/map_circles_hide">
+ </item>
+ <item
+ android:id="@+id/menu_theme_mode"
+ android:icon="@drawable/ic_menu_preferences"
+ android:title="@string/map_theme_select">
+ </item>
+ </menu>
+ </item>
+ <item
+ android:id="@+id/submenu_strategy"
+ android:icon="@drawable/ic_menu_preferences"
+ android:title="@string/map_strategy">
+ <menu>
+ <group
+ android:id="@+id/menu_group_strategy"
+ android:checkableBehavior="single" >
+ <item
+ android:id="@+id/menu_strategy_fastest"
+ android:checkable="true"
+ android:title="@string/map_strategy_fastest">
+ </item>
+ <item
+ android:id="@+id/menu_strategy_fast"
+ android:checkable="true"
+ android:title="@string/map_strategy_fast">
+ </item>
+ <item
+ android:id="@+id/menu_strategy_auto"
+ android:checkable="true"
+ android:title="@string/map_strategy_auto">
+ </item>
+ <item
+ android:id="@+id/menu_strategy_detailed"
+ android:checkable="true"
+ android:title="@string/map_strategy_detailed">
+ </item>
+ </group>
+ </menu>
+ </item>
+ <item
+ android:id="@+id/menu_as_list"
+ android:icon="@drawable/ic_menu_agenda"
+ android:title="@string/map_as_list">
+ </item>
+
+</menu> \ No newline at end of file
diff --git a/main/res/menu/navigate_any_point_activity_options.xml b/main/res/menu/navigate_any_point_activity_options.xml
new file mode 100644
index 0000000..9207e94
--- /dev/null
+++ b/main/res/menu/navigate_any_point_activity_options.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/menu_navigate"
+ android:icon="@drawable/ic_menu_mapmode"
+ android:title="@string/cache_menu_navigate">
+ </item>
+ <item
+ android:id="@+id/menu_default_navigation"
+ android:icon="@drawable/ic_menu_compass"
+ android:title="@string/cache_menu_navigate"> <!-- will be replaced in code -->
+ </item>
+ <item
+ android:id="@+id/menu_caches_around"
+ android:icon="@drawable/ic_menu_rotate"
+ android:title="@string/cache_menu_around">
+ </item>
+ <item
+ android:id="@+id/menu_clear_history"
+ android:icon="@drawable/ic_menu_delete"
+ android:title="@string/search_clear_history">
+ </item>
+
+</menu> \ No newline at end of file
diff --git a/main/res/menu/search_activity_options.xml b/main/res/menu/search_activity_options.xml
new file mode 100644
index 0000000..68eb569
--- /dev/null
+++ b/main/res/menu/search_activity_options.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/menu_search_own_caches"
+ android:icon="@drawable/ic_menu_myplaces"
+ android:title="@string/search_own_caches">
+ </item>
+
+
+</menu> \ No newline at end of file
diff --git a/main/res/menu/settings_activity_options.xml b/main/res/menu/settings_activity_options.xml
new file mode 100644
index 0000000..ba75f91
--- /dev/null
+++ b/main/res/menu/settings_activity_options.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/menu_clear"
+ android:icon="@drawable/ic_menu_delete"
+ android:title="@string/init_clear">
+ </item>
+</menu> \ No newline at end of file
diff --git a/main/res/menu/static_maps_activity_options.xml b/main/res/menu/static_maps_activity_options.xml
new file mode 100644
index 0000000..29410dd
--- /dev/null
+++ b/main/res/menu/static_maps_activity_options.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/menu_refresh"
+ android:icon="@drawable/ic_menu_refresh"
+ android:title="@string/cache_offline_refresh">
+ </item>
+</menu> \ No newline at end of file
diff --git a/main/res/menu/trackable_activity.xml b/main/res/menu/trackable_activity.xml
new file mode 100644
index 0000000..ddf45f6
--- /dev/null
+++ b/main/res/menu/trackable_activity.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_log_touch"
+ android:icon="@drawable/ic_menu_agenda"
+ android:title="@string/trackable_log_touch">
+ </item>
+ <item
+ android:id="@+id/menu_browser_trackable"
+ android:icon="@drawable/ic_menu_info_details"
+ android:title="@string/trackable_browser_open">
+ </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 8bff251..715f949 100644
--- a/main/res/values-cs/strings.xml
+++ b/main/res/values-cs/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Nastavení</string>
<string name="helpers">Užitečné aplikace</string>
<string name="about">O aplikaci</string>
- <string name="helper">Chceš zjistit více o <b>c:geo</b>?\nMrkni na snadno čitelný návod.</string>
<string name="latitude">Zeměpisná šířka</string>
<string name="longitude">Zeměpisná délka</string>
@@ -90,7 +89,7 @@
<string name="log_post">Odeslat Log</string>
<string name="log_post_rate">Odeslat Log a hlasovat</string>
<string name="log_post_no_rate">Odeslat Log a nehlasovat</string>
- <string name="log_post_not_possible">Načítání stránky s Logy…</string>
+ <string name="log_post_not_possible">Načítání stránky s Logovacím formulářem…</string>
<string name="log_add">Přidat</string>
<string name="log_rating">Hodnocení</string>
<string name="log_no_rating">Bez hodnocení</string>
@@ -154,7 +153,6 @@
<string name="err_detail_cache_find">c:geo nemůže najít geokeš</string>
<string name="err_detail_cache_find_some">c:geo nemůže najít tuto geokeš.</string>
<string name="err_detail_cache_find_any">c:geo nemůže najít žádnou geokeš.</string>
- <string name="err_detail_cache_find_next">c:geo nemůže najít další geokeše.</string>
<string name="err_detail_cache_forgot">c:geo zapomnělo, jakou keš chceš zobrazit.</string>
<string name="err_detail_google_maps_limit_reached">c:geo nemůže stáhnout statické mapy. Možná byl dosažen limit Google map.</string>
<string name="err_detail_no_spoiler">c:geo nenašlo žádný obrázek pro tuto keš.</string>
@@ -175,7 +173,7 @@
<string name="err_missing_device_name">Před registrací prosím zadej název zařízení.</string>
<string name="err_favorite_failed">Označení oblíbenosti keše selhalo.</string>
<string name="err_select_logimage_failed">Výběr obrázku pro zápis selhal.</string>
- <string name="err_aquire_image_failed">Získání obrázku selhalo.</string>
+ <string name="err_acquire_image_failed">Získání obrázku selhalo.</string>
<string name="err_tb_display">c:geo nemůže zobrazit sledovatelný předmět. Je to opravdu sledovatelný předmět?</string>
<string name="err_tb_details_open">c:geo nemůže otevřít podrobnosti ke sledovatelnému předmětu.</string>
@@ -267,7 +265,6 @@
<string name="caches_downloading">Stahování keší…\nETA:</string>
<string name="caches_eta_ltm">Méně než minutu</string>
<plurals name="caches_eta_mins">
- <item quantity="zero">minut</item>
<item quantity="one">minuta</item>
<item quantity="few">minuty</item>
<item quantity="other">minuty</item>
@@ -323,7 +320,7 @@
<string name="caches_filter_track">Se sledovatelnými předměty</string>
<string name="caches_filter_clear">Vymazat filtry</string>
<string name="caches_filter_modified">S upravenými souřadnicemi</string>
- <string name="caches_filter_origin">Originální</string>
+ <string name="caches_filter_origin">Původ keše</string>
<string name="caches_removing_from_history">Čištění Historie…</string>
<string name="caches_clear_offlinelogs">Smazat offline Logy</string>
<string name="caches_clear_offlinelogs_progress">Mazání offline logů</string>
@@ -364,8 +361,6 @@
<string name="init_gc_activate">Aktivace Geocaching.com na Aktivní mapě a ve vyhledávání</string>
<string name="init_oc">opencaching.de</string>
<string name="init_oc_activate">Aktivace opencaching.de na Aktivní mapě a ve vyhledávání</string>
- <string name="init_oc_username_description">Zadej své uživatelské jméno pro opencaching.de kvůli možnosti označovat nálezy.</string>
- <string name="init_oc_username">Zadej své uživatelské jméno</string>
<string name="init_gcvote">GCvote.com</string>
<string name="init_twitter">Twitter</string>
<string name="init_username">Uživatelské jméno</string>
@@ -409,7 +404,6 @@
<string name="init_offline_wp">Ukládat statické mapy k bodům trasy pro offline použití</string>
<string name="init_save_log_img">Ukládat 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">Povolit Offline logování\n(Při logování nezobrazovat online logovací obrazovku a neodesílat Log na server)</string>
<string name="init_choose_list">Ptát se na seznam pro uložení keše</string>
<string name="init_livelist">Zobrazovat směr v seznamu keší</string>
@@ -495,7 +489,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Žádná keš</item>
<item quantity="one">Jedna keš</item>
<item quantity="other">%1$d keší</item>
</plurals>
@@ -515,7 +508,6 @@
<string name="cache_attributes">Atributy</string>
<string name="cache_inventory">Inventář</string>
<string name="cache_log_offline">Offline Log</string>
- <string name="cache_log_images_loading">Načítání obrázků z logů…</string>
<string name="cache_log_images_title">Obrázky z Logů</string>
<string name="cache_log_image_default_title">Fotografie</string>
<string name="cache_personal_note">Osobní poznámka</string>
@@ -554,7 +546,7 @@
<string name="cache_dialog_loading_details_status_gcvote">Načítání GCVote</string>
<string name="cache_dialog_loading_details_status_elevation">Načítání údajů o nadmořské výšce</string>
<string name="cache_dialog_loading_details_status_cache">Ukládání do mezipaměti</string>
- <string name="cache_dialog_loading_details_status_render">Renderování zobrazení</string>
+ <string name="cache_dialog_loading_details_status_render">Vykreslování pohledu</string>
<string name="cache_dialog_offline_save_title">Offline</string>
<string name="cache_dialog_offline_save_message">Ukládání keše pro offline použití…</string>
<string name="cache_dialog_offline_drop_title">Offline</string>
@@ -565,10 +557,10 @@
<string name="cache_dialog_watchlist_add_message">Přidávání keše do tvého Watchlistu…</string>
<string name="cache_dialog_watchlist_remove_title">Watchlist</string>
<string name="cache_dialog_watchlist_remove_message">Odstraňování keše z tvého Watchlistu…</string>
- <string name="cache_dialog_favourite_add_title">Oblíbené</string>
- <string name="cache_dialog_favourite_add_message">Přidávání keše do Oblíbených…</string>
- <string name="cache_dialog_favourite_remove_title">Oblíbené</string>
- <string name="cache_dialog_favourite_remove_message">Odstraňování keše z Oblíbených…</string>
+ <string name="cache_dialog_favorite_add_title">Oblíbené</string>
+ <string name="cache_dialog_favorite_add_message">Přidávání keše do Oblíbených…</string>
+ <string name="cache_dialog_favorite_remove_title">Oblíbené</string>
+ <string name="cache_dialog_favorite_remove_message">Odstraňování keše z Oblíbených…</string>
<string name="cache_menu_navigate">Navigovat</string>
<string name="cache_menu_navigation_drive">Navigace (Řízení)</string>
<string name="cache_menu_navigation_walk">Navigace (Chůze)</string>
@@ -587,6 +579,7 @@
<string name="cache_menu_around">Keš v okolí</string>
<string name="cache_menu_event">Přidat do kalendáře</string>
<string name="cache_menu_details">Detaily</string>
+ <string name="cache_menu_refresh">Obnovit</string>
<string name="cache_menu_share">Sdílet keš</string>
<string name="cache_menu_move_list">Přesunout do jiného seznamu</string>
<string name="cache_menu_gcc">GCC</string>
@@ -610,7 +603,7 @@
<string name="cache_rating">Hodnocení</string>
<string name="cache_own_rating">Vlastní hodnocení</string>
<string name="cache_rating_of">z</string>
- <string name="cache_favourite">Oblíbená</string>
+ <string name="cache_favorite">Oblíbená</string>
<string name="cache_owner">Zakladatel</string>
<string name="cache_hidden">Skryta</string>
<string name="cache_event">Datum</string>
@@ -618,9 +611,7 @@
<string name="cache_coordinates">Souřadnice</string>
<string name="cache_coordinates_original">Původní souřadnice</string>
<string name="cache_spoiler_images_title">Obrázky s nápovědou</string>
- <string name="cache_spoiler_images_loading">Načítání obrázků s nápovědou…</string>
<string name="cache_images_title">Obrázky</string>
- <string name="cache_images_loading">Načítání obrázků…</string>
<string name="cache_log_types">Typy zápisů</string>
<string name="cache_coordinates_no">Tato keš nemá souřadnice.</string>
<string name="cache_clear_history">Vymazat historii</string>
@@ -823,8 +814,6 @@
<string name="license_dismiss">Zamítnout</string>
<!-- helpers -->
- <string name="helper_manual_title">Manuál</string>
- <string name="helper_manual_description">Komplexní příručka aplikace c:geo obsahující popis všech možností této aplikace (včetně těch skrytých).</string>
<string name="helper_calendar_title">c:geo modul kalendáře</string>
<string name="helper_calendar_missing">c:geo modul kalendáře není nainstalován.</string>
<string name="helper_calendar_description">Umožňuje exportovat události keší do tvého kalendáře.</string>
@@ -1050,12 +1039,12 @@
<string name="legal_note">Pro používání služeb Geocaching.com musíš souhlasit s podmínkami použití <a href="http://www.geocaching.com/about/termsofuse.aspx">společnosti Groundspeak</a></string>
<string name="quote">Učinit Geocaching lehčí a uživatelé línější.</string>
<string name="powered_by">carnero</string>
- <string name="support">Podpora: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string>
- <string name="website">Stránka: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">Stránka c:geo</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Návod: <a href="http://manual.cgeo.org/">c:geo v Nutshell</a></string>
- <string name="about_go4cache">Služba <b>Go 4 Cache</b> zobrazuje ostatní geokačery na mapě (v <b>c:geo</b> nebo v prohlížeči) v reálném čase. Může zobrazovat - na příklad - jakou keš zrovna hledají. Připojením se k <b>Go 4 Cache</b> získá aplikace <b>c:geo</b> povolení zveřejňovat tvou polohu při geocachingu (pouze když je <b>c:geo</b> spuštěno).</string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Podpora: <a href="">support@cgeo.org</a></string>
+ <string name="website">Stránka: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">Stránka c:geo</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Návod: <a href="">c:geo v Nutshell</a></string>
<string name="about_twitter">Má <b>c:geo</b> publikovat nový status na Twitteru vždy, když zaloguješ keš?</string>
<string name="about_auth_1">Následující proces dovoluje aplikaci <b>c:geo</b> přístup na Twitter - pokud budeš souhlasit.</string>
<string name="about_auth_2">Klepnutím na tlačítko \"Zahájit autorizaci\" bude proces zahájen. Tento proces otevře webový prohlížeč s Twitterem. Přihlaš se na této stránce a povol <b>c:geu</b> přístup k tvému účtu. Pokud je to povoleno, Twitter ti ukáže číselný PIN kód. Tento PIN kód musíš zadat do <b>c:geo</b> a potvrdit. To je vše.</string>
diff --git a/main/res/values-da/strings.xml b/main/res/values-da/strings.xml
index 9332b9f..3ff6756 100644
--- a/main/res/values-da/strings.xml
+++ b/main/res/values-da/strings.xml
@@ -165,9 +165,8 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Ingen cache</item>
<item quantity="one">En cache</item>
- <item quantity="other">%1$d Cacher</item>
+ <item quantity="other">%1$d cacher</item>
</plurals>
<string name="cache_offline">Offline</string>
<string name="cache_offline_refresh">Genindlæs</string>
@@ -208,6 +207,7 @@
<string name="cache_menu_around">Cacher i nærheden</string>
<string name="cache_menu_event">Tilføj til kalender</string>
<string name="cache_menu_details">Detaljer</string>
+ <string name="cache_menu_refresh">Genindlæs</string>
<string name="cache_status">Status</string>
<string name="cache_status_offline_log">Log gemt</string>
<string name="cache_status_found">Fundet</string>
diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml
index dd40100..d5ed34a 100644
--- a/main/res/values-de/strings.xml
+++ b/main/res/values-de/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Einstellungen</string>
<string name="helpers">Nützliche Apps</string>
<string name="about">Über c:geo</string>
- <string name="helper">Um mehr über <b>c:geo</b> zu erfahren\neinfach die Bedienungsanleitung öffnen.</string>
<string name="latitude">Breitengrad</string>
<string name="longitude">Längengrad</string>
@@ -34,6 +33,7 @@
<string name="ape">Project Ape-Cache</string>
<string name="gchq">Groundspeak HQ</string>
<string name="gps">GPS Cache Exhibit</string>
+ <string name="block">Groundspeak Block Party</string>
<string name="unknown">Unbekannter Typ</string>
<!-- cache sizes -->
@@ -73,6 +73,7 @@
<string name="log_maintenance_needed">Benötigt Wartung</string>
<string name="log_update">Geänderte Koordinaten</string>
<string name="log_archived">Archiviert</string>
+ <string name="log_unarchived">Aus dem Archiv geholt</string>
<string name="log_needs_archived">Sollte archiviert werden</string>
<string name="log_discovered">Gesehen</string>
<string name="log_reviewer">Review(er)-Anmerkung</string>
@@ -125,7 +126,15 @@
<string name="log_image_camera">Neu</string>
<string name="log_image_caption">Überschrift</string>
<string name="log_image_description">Beschreibung</string>
-
+ <string name="log_image_scale">Skalierung</string>
+ <string-array name="log_image_scales">
+ <item>Keine Skalierung</item>
+ <item>512 px</item>
+ <item>640 px</item>
+ <item>800 px</item>
+ <item>1024 px</item>
+ </string-array>
+
<!-- translation -->
<string name="translate_to_sys_lang">Übersetze in %s</string>
<string name="translate_to_english">Übersetze in Englisch</string>
@@ -153,7 +162,6 @@
<string name="err_detail_cache_find">c:geo konnte keinen Cache finden.</string>
<string name="err_detail_cache_find_some">c:geo konnte diesen Cache nicht finden.</string>
<string name="err_detail_cache_find_any">c:geo konnte keine Caches finden.</string>
- <string name="err_detail_cache_find_next">c:geo konnte die nächsten Caches nicht finden.</string>
<string name="err_detail_cache_forgot">c:geo hat vergessen, welcher Cache aufgerufen werden sollte.</string>
<string name="err_detail_google_maps_limit_reached">c:geo kann die statischen Karten nicht herunterladen. Google Maps Limit könnte erreicht sein.</string>
<string name="err_detail_no_spoiler">c:geo hat kein Hinweisbild für diesen Cache gefunden.</string>
@@ -172,7 +180,10 @@
<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>
<string name="err_missing_device_name">Vor der Registrierung muss ein Name für das Endgerät festlegt werden.</string>
-
+ <string name="err_favorite_failed">Ändern des Favoriten-Status ist fehlgeschlagen.</string>
+ <string name="err_select_logimage_failed">Auswahl eines Bildes für das Log ist fehlgeschlagen.</string>
+ <string name="err_acquire_image_failed">Erstellen eines Fotos ist fehlgeschlagen.</string>
+
<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_forgot_saw">c:geo hat vergessen, welcher Trackable gesehen wurde.</string>
@@ -194,6 +205,7 @@
<string name="err_log_load_data_still">c:geo lädt gerade die benötigten Daten. Bitte kurz warten.</string>
<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_logimage_post_failed">Es scheint dass Ihr Logfoto nicht hochgeladen werden konnte. Bitte prüfen Sie es auf Geocaching.com nach.</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>
@@ -223,6 +235,8 @@
<string name="info_log_saved">Log erfolgreich gespeichert.</string>
<string name="info_log_cleared">Log wurde geleert.</string>
<string name="info_log_type_changed">Logtyp wurde verändert!</string>
+ <string name="info_select_logimage_cancelled">Foto Auswahl oder Erstellung abgebrochen.</string>
+ <string name="info_stored_image">Neues Foto gespeichert nach:</string>
<string name="info_storing_static_maps">Versuche, statische Karten zu speichern</string>
@@ -260,7 +274,6 @@
<string name="caches_downloading">Lade Caches…\nGeschätzte Zeit: </string>
<string name="caches_eta_ltm">Weniger als eine Minute</string>
<plurals name="caches_eta_mins">
- <item quantity="zero">Minuten</item>
<item quantity="one">Minute</item>
<item quantity="other">Minuten</item>
</plurals>
@@ -353,10 +366,11 @@
<!-- init -->
<string name="init_geocaching">Geocaching.com</string>
+ <string name="init_gc_activate">Geocaching.com auf Live-Karte und für die Suche aktivieren</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_oc_de_description">Autorisiere c:geo dazu auf opencaching.de zuzugreifen um Caches zu suchen und nach deinen Funden zu filtern.</string>
+ <string name="init_register_oc_de">c:geo autorisieren</string>
<string name="init_gcvote">GCvote.com</string>
<string name="init_twitter">Twitter</string>
<string name="init_username">Benutzername</string>
@@ -380,6 +394,7 @@
<string name="init_signature_template_datetime">Datum &amp; Zeit</string>
<string name="init_signature_template_user">Benutzer</string>
<string name="init_signature_template_number">Nummer</string>
+ <string name="init_signature_template_owner">Besitzer</string>
<string name="init_details">Cache Details</string>
<string name="init_ratingwanted">Lade Cache-Bewertung von GCvote.com</string>
<string name="init_elevationwanted">Lade Höhe des Caches</string>
@@ -468,7 +483,7 @@
<string name="sendToCgeo_download_fail">c:geo konnte Caches nicht laden. Entweder besteht keine Internetverbindung oder send2c:geo funktioniert nicht.</string>
<string name="sendToCgeo_no_registration">c:geo konnte Caches nicht laden. Registrierung für send2c:geo ungültig. Bitte in Einstellungen neu registrieren.</string>
- <!-- auth -->
+ <!-- auth twitter -->
<string name="auth_twitter">Twitter</string>
<string name="auth_authorize">c:geo autorisieren</string>
<string name="auth_start">Starte Autorisierung</string>
@@ -479,10 +494,25 @@
<string name="auth_dialog_pin_title">PIN Code</string>
<string name="auth_dialog_pin_message">Bitte den Twitter-PIN-Code eingeben, dies ist notwendig um die Autorisierung abzuschließen.</string>
<string name="auth_dialog_completed">c:geo ist nun autorisiert, Tweets bei Twitter zu erstellen.</string>
+ <string name="about_auth_1">Der folgende Prozess erlaubt es <b>c:geo</b> auf den persönlichen Twitter-Account zuzugreifen, wenn zugestimmt wird.</string>
+ <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>
+
+ <!-- auth opencaching -->
+ <string name="auth_ocde">opencaching.de</string>
+ <string name="auth_authorize_oc">c:geo autorisieren</string>
+ <string name="auth_start_oc">Starte Autorisierung</string>
+ <string name="auth_again_oc">Neustarten</string>
+ <string name="auth_pin_hint_oc">%s-PIN</string>
+ <string name="auth_finish_oc">Fertig</string>
+ <string name="auth_dialog_wait_oc">Warten auf %s…</string>
+ <string name="auth_dialog_pin_title_oc">PIN Code</string>
+ <string name="auth_dialog_pin_message_oc">Bitte den %s-PIN-Code eingeben, dies ist notwendig um die Autorisierung abzuschließen.</string>
+ <string name="auth_dialog_completed_oc">c:geo ist nun autorisiert, caches zu laden und auf %s zu loggen.</string>
+ <string name="about_auth_1_oc">Der folgende Prozess erlaubt es <b>c:geo</b> auf den persönlichen %s-Account zuzugreifen, wenn zugestimmt wird.</string>
+ <string name="about_auth_2_oc">Ein Klick auf \"Starte Autorisierung\" öffnet eine %s-Seite in einem Browserfenster. Durch die Anmeldung und die Bestätigung wird <b>c:geo</b> ermöglicht, auf den persönlichen Account zuzugreifen. Wird dies bestätigt, nennt %s eine numerische PIN, diese muss kopiert und in <b>c:geo</b> eingefügt werden. Das ist alles.</string>
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Kein Cache</item>
<item quantity="one">Ein Cache</item>
<item quantity="other">%1$d Caches</item>
</plurals>
@@ -502,11 +532,12 @@
<string name="cache_attributes">Attribute</string>
<string name="cache_inventory">Inventar</string>
<string name="cache_log_offline">Offline-Log</string>
- <string name="cache_log_images_loading">Lade Logbild…</string>
<string name="cache_log_images_title">Logbild</string>
<string name="cache_log_image_default_title">Bild</string>
<string name="cache_personal_note">Persönliche Notiz</string>
<string name="cache_personal_note_edit">Bearbeiten</string>
+ <string name="cache_personal_note_unstored">Cache noch nicht gespeichert</string>
+ <string name="cache_personal_note_store">Der Cache wird zunächst gespeichert, damit persönliche Notizen möglich sind.</string>
<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 %s korrekt angezeigt werden.</string>
@@ -551,10 +582,10 @@
<string name="cache_dialog_watchlist_add_message">Füge den Cache deiner Watchlist hinzu…</string>
<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_dialog_favourite_add_title">Favorit</string>
- <string name="cache_dialog_favourite_add_message">Füge den Cache als dein Favorit hinzu…</string>
- <string name="cache_dialog_favourite_remove_title">Favorit</string>
- <string name="cache_dialog_favourite_remove_message">Entferne den Cache von deinen Favoriten…</string>
+ <string name="cache_dialog_favorite_add_title">Favorit</string>
+ <string name="cache_dialog_favorite_add_message">Füge den Cache zu Favoriten hinzu…</string>
+ <string name="cache_dialog_favorite_remove_title">Favorit</string>
+ <string name="cache_dialog_favorite_remove_message">Entferne den Cache von deinen Favoriten…</string>
<string name="cache_menu_navigate">Navigieren</string>
<string name="cache_menu_navigation_drive">Navigation (Fahren)</string>
<string name="cache_menu_navigation_walk">Navigation (Gehen)</string>
@@ -573,11 +604,13 @@
<string name="cache_menu_around">Caches im Umkreis</string>
<string name="cache_menu_event">Zum Kalender hinzufügen</string>
<string name="cache_menu_details">Details</string>
+ <string name="cache_menu_refresh">Aktualisieren</string>
<string name="cache_menu_share">Weiterleiten</string>
<string name="cache_menu_move_list">Auf andere Liste verschieben</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">Gespeicherter Log</string>
<string name="cache_status_found">Gefunden</string>
@@ -585,6 +618,8 @@
<string name="cache_status_disabled">Deaktiviert</string>
<string name="cache_status_premium">Nur für Premium-Mitglieder</string>
<string name="cache_status_not_premium">Für alle Mitglieder</string>
+ <string name="cache_status_stored">Gespeichert</string>
+ <string name="cache_status_not_stored">Nicht gespeichert</string>
<string name="cache_geocode">Geocode</string>
<string name="cache_name">Name</string>
<string name="cache_type">Typ</string>
@@ -595,7 +630,7 @@
<string name="cache_rating">Bewertung</string>
<string name="cache_own_rating">Eigene Bewertung</string>
<string name="cache_rating_of">von</string>
- <string name="cache_favourite">Favorit</string>
+ <string name="cache_favorite">Favorit</string>
<string name="cache_owner">Besitzer</string>
<string name="cache_hidden">Versteckt</string>
<string name="cache_event">Zeitangabe</string>
@@ -603,8 +638,7 @@
<string name="cache_coordinates">Koordinaten</string>
<string name="cache_coordinates_original">Ursprüngliche Koordinaten</string>
<string name="cache_spoiler_images_title">Hinweisbilder</string>
- <string name="cache_spoiler_images_loading">Lade Hinweisbilder…</string>
- <string name="cache_images_loading">Lade Bilder…</string>
+ <string name="cache_images_title">Bilder</string>
<string name="cache_log_types">Logs</string>
<string name="cache_coordinates_no">Dieser Cache hat keine Koordinaten.</string>
<string name="cache_clear_history">Verlauf leeren</string>
@@ -806,8 +840,6 @@
<string name="license_dismiss">Ablehnen</string>
<!-- helpers -->
- <string name="helper_manual_title">Anleitung</string>
- <string name="helper_manual_description">Umfangreiche Anleitung für c:geo mit Beschreibung aller Möglichkeiten dieser App (auch versteckte).</string>
<string name="helper_calendar_title">c:geo Kalender Add-on</string>
<string name="helper_calendar_missing">c:geo Kalender Add-on nicht installiert</string>
<string name="helper_calendar_description">Ermöglicht die Übernahme von Event-Caches in den Kalender.</string>
@@ -819,7 +851,9 @@
<string name="helper_bluetoothgps_description">Ermöglicht ein externes GPS zu verwenden, um die Standortgenauigkeit zu erhöhen und die Batterie zu schonen.</string>
<string name="helper_barcode_title">Barcode-Scanner</string>
<string name="helper_barcode_description">Es gibt GreaseMonkey-Scripte und Webseiten, die Geocodes als Strichcode darstellen können. Bei Verwendung dieser Skripte kann c:geo über diese App den Geocode eines Caches direkt vom Bildschirm des Computers ablesen.</string>
-
+ <string name="helper_pocketquery_title">Pocket Query Creator</string>
+ <string name="helper_pocketquery_description">Ermöglicht das einfache Erzeugen und Herunterladen von Pocket Queries basierend auf der aktuellen Position oder einem auf der Karte gewählten Punkt. Setzt eine Premiummitgliedschaft bei geocaching.com voraus.</string>
+
<!-- add-ons -->
<string name="addon_missing_title">Add-On fehlt</string>
<string name="addon_download_prompt">Jetzt im Google Play Store herunterladen</string>
@@ -984,6 +1018,8 @@
<string name="attribute_swamp_no">Nicht sumpfig / kein matschiges Gelände</string>
<string name="attribute_hills_yes">Hügeliges Gelände</string>
<string name="attribute_hills_no">Kein hügeliges Gelände</string>
+ <string name="attribute_easy_climbing_yes">Einfaches Klettern</string>
+ <string name="attribute_easy_climbing_no">Kein einfaches Klettern</string>
<string name="attribute_poi_yes">Interessanter Ort</string>
<string name="attribute_poi_no">Uninteressanter Ort</string>
<string name="attribute_moving_target_yes">Bewegliches Ziel</string>
@@ -1028,19 +1064,20 @@
<string name="attribute_ask_owner_no">Keine Startbedingungen beim Owner erfragen</string>
<string name="attribute_unknown_yes">Unbekannte Attribute vorhanden</string>
<string name="attribute_unknown_no">Keine unbekannten Attribute</string>
+ <string name="attribute_geotour_yes">Teil einer GeoTour</string>
+ <string name="attribute_geotour_no">Kein Teil einer GeoTour</string>
<!-- next things -->
<string name="legal_note">Um die Dienste von geocaching.com nutzen zu können, müssen die <a href="http://www.geocaching.com/about/termsofuse.aspx">Groundspeak-Nutzungsbedingungen</a> (englisch) akzeptiert werden.</string>
<string name="quote">Um Geocachen einfacher zu machen, um es Anwendern bequemer zu machen.</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">Webseite: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Benutzung: <a href="http://manual.cgeo.org/">c:geo Kurzanleitung</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Support: <a href="">support@cgeo.org</a></string>
+ <string name="website">Webseite: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo page</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Benutzung: <a href="">c:geo Kurzanleitung</a></string>
<string name="about_twitter">Soll jeder neue Fund auf Twitter veröffentlicht werden, wenn er über <b>c:geo</b> geloggt wird?</string>
- <string name="about_auth_1">Der folgende Prozess erlaubt es <b>c:geo</b> auf den persönlichen Twitter-Account zuzugreifen, wenn zugestimmt wird.</string>
- <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" tools:ignore="UnusedResources">Neuer Release verfügbar.\nKlicken zum Installieren.</string>
@@ -1049,6 +1086,17 @@
<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>
+ <!-- text-to-speech for compass view -->
+ <string name="tts_service">Sprechender Kompass</string>
+ <string name="tts_start">Starte Sprache</string>
+ <string name="tts_stop">Stoppe Sprache</string>
+ <string name="tts_kilometers">%s Kilometer</string>
+ <string name="tts_meters">%s Meter</string>
+ <string name="tts_miles">%s Meilen</string>
+ <string name="tts_feet">%s Fuß</string>
+ <string name="tts_oclock">%s Uhr</string>
+
+ <!-- various -->
<string name="clipboard_copy_ok">In Zwischenablage kopiert</string>
<plurals name="days_ago">
<item quantity="one">gestern</item>
diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml
index 7215d72..f5a84ea 100644
--- a/main/res/values-es/strings.xml
+++ b/main/res/values-es/strings.xml
@@ -10,7 +10,8 @@
<string name="settings">Ajustes</string>
<string name="helpers">¿Qué instalar?</string>
<string name="about">Sobre c:geo</string>
- <string name="helper">Si quieres aprender cosas sobre <b>c:geo</b>?\nEcha un ojo a nuestro manual.</string>
+ <string name="latitude">Latitud</string>
+ <string name="longitude">Longitud</string>
<!-- actionbar -->
<string name="action_bar_share_title">Compartir enlace a escondite</string>
@@ -19,19 +20,20 @@
<string name="all_types">Todos los escondites</string>
<string name="traditional">Tradicionales</string>
<string name="multi">Multis</string>
- <string name="mystery">Desconocidos</string>
+ <string name="mystery">Desconocidos/Mistery</string>
<string name="letterbox">Buzón híbrido</string>
- <string name="event">Por pistas</string>
- <string name="mega">Mega-eventos</string>
+ <string name="event">Eventos</string>
+ <string name="mega">Mega-Eventos</string>
<string name="earth">Educativos (Earth)</string>
- <string name="cito">Limpieza de escondites</string>
+ <string name="cito">Eventos Limpieza(CITO)</string>
<string name="webcam">Webcams</string>
<string name="virtual">Virtuales</string>
<string name="wherigo">Wherigo</string>
- <string name="lostfound">Perdidos y encontrados</string>
+ <string name="lostfound">Eventos Perdidos y Encontrados</string>
<string name="ape">Proyecto APE</string>
<string name="gchq">Groundspeak HQ</string>
- <string name="gps">Exhibición de escondites GPS </string>
+ <string name="gps">Exhibición de escondites GPS</string>
+ <string name="unknown">De tipo desconocido</string>
<!-- cache sizes -->
<string name="cache_size_micro">micro</string>
@@ -46,36 +48,43 @@
<!-- waypoints -->
<string name="wp_final">Ubicación final</string>
<string name="wp_stage">Etapa de multi escondite</string>
- <string name="wp_puzzle">Preguntar sin contestar</string>
+ <string name="wp_puzzle">Preguntar a contestar</string>
<string name="wp_pkg">Zona de aparcamiento</string>
<string name="wp_trailhead">Sendero</string>
<string name="wp_waypoint">Punto de referencia</string>
+ <string name="wp_original">Coordenadas originales</string>
<!-- logs -->
<string name="log_found">Encontrado</string>
<string name="log_dnf">No encontrado</string>
<string name="log_note">Nota</string>
<string name="log_published">Publicado</string>
- <string name="log_enabled">Activo</string>
- <string name="log_disabled">Inactivo</string>
- <string name="log_attend">Iré</string>
+ <string name="log_enabled">Activado</string>
+ <string name="log_disabled">Desactivado</string>
+ <string name="log_attend">Asistiré</string>
<string name="log_attended">Asistí</string>
- <string name="log_retrieved">Obtenido</string>
- <string name="log_placed">Colocado</string>
- <string name="log_grabbed">Guardado en alguna parte</string>
+ <string name="log_retrieved">Recogido</string>
+ <string name="log_placed">Depositado</string>
+ <string name="log_grabbed">Recogido de alguna parte</string>
+ <string name="log_movecollection">Mover a la colección</string>
+ <string name="log_moveinventory">Mover al inventario</string>
<string name="log_maintained">Mantenimiento efectuado</string>
<string name="log_maintenance_needed">Necesita mantenimiento</string>
<string name="log_update">Coordenadas actualizadas</string>
<string name="log_archived">Archivado</string>
+ <string name="log_unarchived">Desarchivado</string>
<string name="log_needs_archived">Necesita ser archivado</string>
<string name="log_discovered">Descubierto</string>
<string name="log_reviewer">Nota del revisor</string>
+ <string name="log_retractlisting">Retirar ficha del escondite</string>
+ <string name="log_marked_missing">Marcado como perdido</string>
<string name="log_tb_nothing">No hacer nada</string>
- <string name="log_tb_visit">Visita</string>
- <string name="log_tb_drop">Colocar aquí</string>
+ <string name="log_tb_visit">Visitado</string>
+ <string name="log_tb_drop">Dejar aquí</string>
<string name="log_tb_changeall">Cambiar todo</string>
<string name="log_save">Guardar</string>
- <string name="log_saving">Guardando registo…</string>
+ <string name="log_saving">Enviando registo…</string>
+ <string name="log_saving_and_uploading">Enviando registro y subiendo imagen…</string>
<string name="log_clear">Limpiar</string>
<string name="log_post">Enviar registro</string>
<string name="log_post_rate">Enviar registro y puntuación</string>
@@ -84,27 +93,45 @@
<string name="log_rating">Puntuación</string>
<string name="log_no_rating">Sin puntuación</string>
<string name="log_stars_1">1 estrella</string>
-<string name="log_stars_15">1,5 estrellas</string>
+ <string name="log_stars_15">1,5 estrellas</string>
<string name="log_stars_2">2 estrellas</string>
- <string name="log_stars_25">2,5 estrellas</string>
+ <string name="log_stars_25">2,5 estrellas</string>
<string name="log_stars_3">3 estrellas</string>
- <string name="log_stars_35">3,5 estrellas</string>
+ <string name="log_stars_35">3,5 estrellas</string>
<string name="log_stars_4">4 estrellas</string>
- <string name="log_stars_45">4,5 estrellas</string>
+ <string name="log_stars_45">4,5 estrellas</string>
<string name="log_stars_5">5 estrellas</string>
-<string name="log_stars_1_description">poor</string>
- <string name="log_stars_15_description">fairly poor</string>
- <string name="log_stars_2_description">below average</string>
- <string name="log_stars_25_description">not so bad</string>
- <string name="log_stars_3_description">average </string>
- <string name="log_stars_35_description">not bad at all</string>
- <string name="log_stars_4_description">better than average</string>
- <string name="log_stars_45_description">very good</string>
- <string name="log_stars_5_description">awesome</string>
+ <string name="log_stars_1_description">malísimo</string>
+ <string name="log_stars_15_description">muy malo</string>
+ <string name="log_stars_2_description">malo</string>
+ <string name="log_stars_25_description">un poco malo</string>
+ <string name="log_stars_3_description">aceptable</string>
+ <string name="log_stars_35_description">algo bueno</string>
+ <string name="log_stars_4_description">bueno</string>
+ <string name="log_stars_45_description">muy bueno</string>
+ <string name="log_stars_5_description">buenísimo</string>
<string name="log_webcam">Foto de webcam tomada</string>
<string name="log_new_log">Registro</string>
<string name="log_new_log_text">Texto del registro</string>
<string name="log_announcement">Aviso</string>
+ <string name="log_today">Hoy</string>
+ <string name="log_yesterday">Ayer</string>
+ <string name="log_smilies">Emoticonos</string>
+ <string name="log_image">Imagen</string>
+ <string name="log_image_attach">Adjuntar imagen</string>
+ <string name="log_image_edit">Editar imagen</string>
+ <string name="log_image_stored">Galería</string>
+ <string name="log_image_camera">Tomar foto</string>
+ <string name="log_image_caption">Título</string>
+ <string name="log_image_description">Descripción</string>
+ <string name="log_image_scale">Redimensionamiento</string>
+ <string-array name="log_image_scales">
+ <item>Sin redimensionar</item>
+ <item>512 px</item>
+ <item>640 px</item>
+ <item>800 px</item>
+ <item>1024 px</item>
+ </string-array>
<!-- errors, warnings, info toasts -->
<string name="err_none">Aceptar</string>
@@ -123,7 +150,6 @@
<string name="err_detail_cache_find">Lo siento, c:geo no puede encontrar escondites</string>
<string name="err_detail_cache_find_some">Lo siento, c:geo no puede encontrar ese escondite.</string>
<string name="err_detail_cache_find_any">Lo siento, c:geo no puede encontrar algunos escondites.</string>
- <string name="err_detail_cache_find_next">Lo siento, c:geo no puede encontrar los siguientes escondites.</string>
<string name="err_detail_cache_forgot">Lo siento, c:geo ha olvidado el escondite que quieres.</string>
<string name="err_detail_no_spoiler">c:geo no ha encontrado imágenes/pista para este escondite.</string>
<string name="err_detail_no_map_static">c:geo no ha encontrado mapas estáticos para este escondite.</string>
@@ -251,6 +277,7 @@
<string name="caches_drop_all_ask">¿Quieres borrar todos los escondites guardados en el dispositivo?</string>
<string name="caches_drop_stored">Descartar guardados</string>
<string name="caches_drop_progress">Borrando escondites</string>
+ <string name="caches_drop_all_and_list">Descartar todos y borrar lista</string>
<string name="caches_refresh_selected">Actualizar seleccionados</string>
<string name="caches_refresh_all">Actualizar todos</string>
<string name="caches_move_selected">Mover seleccionados</string>
@@ -263,7 +290,7 @@
<string name="caches_recaptcha_continue">Continuar</string>
<string name="caches_filter">Filtrar</string>
<string name="caches_filter_title">Filtrar por</string>
- <string name="caches_filter_size">tamaó</string>
+ <string name="caches_filter_size">tamaño</string>
<string name="caches_filter_type">tipo</string>
<string name="caches_filter_track">con rastreables</string>
<string name="caches_filter_clear">limpiar filtros</string>
@@ -381,7 +408,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Sin escondites</item>
<item quantity="one">Un escondite</item>
<item quantity="other">%1$d Escondites</item>
</plurals>
@@ -401,8 +427,7 @@
<string name="cache_attributes">Atributos</string>
<string name="cache_inventory">Inventario</string>
<string name="cache_log_offline">Registro desconectado</string>
- <string name="cache_log_images_loading">Cargando imagen de registro…</string>
- <string name="cache_log_images_title">Imagen de resgistro</string>
+ <string name="cache_log_images_title">Imagen de registro</string>
<string name="cache_log_image_default_title">Foto</string>
<string name="cache_personal_note">Nota personal</string>
<string name="cache_description">Descripción</string>
@@ -439,6 +464,7 @@
<string name="cache_menu_around">Alrededores</string>
<string name="cache_menu_event">Añadir a calendario</string>
<string name="cache_menu_details">Detalles</string>
+ <string name="cache_menu_refresh">Actualizar</string>
<string name="cache_menu_share">Compartir escondite</string>
<string name="cache_menu_move_list">Mover a otra lista</string>
<string name="cache_menu_gcc">GCC</string>
@@ -457,14 +483,13 @@
<string name="cache_terrain">Terreno</string>
<string name="cache_rating">Puntuación</string>
<string name="cache_rating_of">de</string>
- <string name="cache_favourite">Favorito</string>
+ <string name="cache_favorite">Favorito</string>
<string name="cache_owner">Propietario</string>
<string name="cache_hidden">Oculto</string>
<string name="cache_event">Fecha</string>
<string name="cache_location">Ubicación</string>
<string name="cache_coordinates">Coordenadas</string>
<string name="cache_spoiler_images_title">Imágenes reveladoras</string>
- <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_clear_history">Borrar historial</string>
@@ -600,8 +625,6 @@
<string name="license_dismiss">Descartar</string>
<!-- helpers -->
- <string name="helper_manual_title">Manual</string>
- <string name="helper_manual_description">Sencillo manual de c:geo que contiene todas las capacidades de este programa (incluidas las ocultas).</string>
<string name="helper_locus_title">Locus</string>
<string name="helper_locus_description">Sencilla aplicación que muestra mapas en línea y permite descargarlos para ser usados sin conexión (sólo mapas no vectoriales). También permite registrar el recorrido, gestionar puntos de interés y más funciones interesantes.</string>
@@ -754,11 +777,12 @@
<string name="legal_note">Para utilizar los servicios de Geocaching.com, debes aceptar las <a href="http://www.geocaching.com/about/termsofuse.aspx">condiciones de Groundspeak</a>.</string>
<string name="quote">Para hacer el geocaching más sencillo, para hacer a los usuarios más vagos.</string>
- <string name="support">Soporte: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string>
- <string name="website">Web: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Manual: <a href="http://itw.bidix.info/cgeo/">c:geo en breve</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Soporte: <a href="">support@cgeo.org</a></string>
+ <string name="website">Web: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo page</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Manual: <a href="">c:geo en breve</a></string>
<string name="about_twitter">¿Debe <b>c:geo</b> publicar el nuevo estado en Twitter cuando registras un escondite?</string>
<string name="about_auth_1">El siguiente proceso permite a <b>c:geo</b> acceder a Twitter - si estás de acuerdo.</string>
diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml
index 122c33b..69fa863 100644
--- a/main/res/values-fr/strings.xml
+++ b/main/res/values-fr/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Paramètres</string>
<string name="helpers">Aide à l\'installation</string>
<string name="about">À propos de c:geo</string>
- <string name="helper">Voulez-vous en savoir plus au sujet de <b>c:geo</b> ?\nLisez notre manuel (en anglais).</string>
<string name="latitude">Latitude</string>
<string name="longitude">Longitude</string>
@@ -34,6 +33,7 @@
<string name="ape">Project ape cache</string>
<string name="gchq">Groundspeak hq</string>
<string name="gps">GPS cache exhibit</string>
+ <string name="block">Fête locale Groundspeak</string>
<string name="unknown">Type inconnu</string>
<!-- cache sizes -->
@@ -126,6 +126,14 @@
<string name="log_image_camera">Nouvelle</string>
<string name="log_image_caption">Légende</string>
<string name="log_image_description">Description</string>
+ <string name="log_image_scale">Mise à l\'échelle</string>
+ <string-array name="log_image_scales">
+ <item>Taille originale</item>
+ <item>512 px</item>
+ <item>640 px</item>
+ <item>800 px</item>
+ <item>1024 px</item>
+ </string-array>
<!-- translation -->
<string name="translate_to_sys_lang">Traduire en %s</string>
@@ -154,7 +162,6 @@
<string name="err_detail_cache_find">c:geo ne peut pas trouver de caches</string>
<string name="err_detail_cache_find_some">c:geo ne peut pas trouver cette cache.</string>
<string name="err_detail_cache_find_any">c:geo ne peut pas trouver de caches.</string>
- <string name="err_detail_cache_find_next">c:geo ne peut pas trouver les caches suivantes.</string>
<string name="err_detail_cache_forgot">c:geo a oublié la cache demandée.</string>
<string name="err_detail_google_maps_limit_reached">c:geo n\'a pas pu charger les cartes statiques. La limite de Google Maps est peut être temporairement atteinte.</string>
<string name="err_detail_no_spoiler">c:geo n\'a pas trouvé d\'image indice pour cette cache.</string>
@@ -175,7 +182,7 @@
<string name="err_missing_device_name">Veuillez saisir un nom pour votre appareil avant l\'enregistrement.</string>
<string name="err_favorite_failed">c:geo ne peut pas changer le status de favori.</string>
<string name="err_select_logimage_failed">La sélection d\'une image pour la note a échoué.</string>
- <string name="err_aquire_image_failed">L\'acquisition d\'une nouvelle image pour la note a échoué.</string>
+ <string name="err_acquire_image_failed">L\'acquisition d\'une nouvelle image pour la note a échoué.</string>
<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>
@@ -362,8 +369,6 @@
<string name="init_gc_activate">Utiliser Geocaching.com pour la carte active et les recherches.</string>
<string name="init_oc">opencaching.de</string>
<string name="init_oc_activate">Utiliser opencaching.de pour la carte active et les recherches.</string>
- <string name="init_oc_username_description">Entrer votre nom d\'utilisateur opencaching.de afin de pouvoir marquer vos trouvailles.</string>
- <string name="init_oc_username">Entrer votre nom d\'utilisateur</string>
<string name="init_gcvote">GCvote.com</string>
<string name="init_twitter">Twitter</string>
<string name="init_username">Identifiant</string>
@@ -492,7 +497,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">aucune cache</item>
<item quantity="one">une cache</item>
<item quantity="other">%1$d caches</item>
</plurals>
@@ -512,11 +516,12 @@
<string name="cache_attributes">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>
<string name="cache_log_images_title">Image de la visite</string>
<string name="cache_log_image_default_title">Photo</string>
<string name="cache_personal_note">Note personnelle</string>
<string name="cache_personal_note_edit">Éditer</string>
+ <string name="cache_personal_note_unstored">Cache non sauvegardée localement</string>
+ <string name="cache_personal_note_store">La cache va être sauvegardée localement avant d\'autoriser les notes personnelles.</string>
<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 %s pour être affichées correctement.</string>
@@ -562,10 +567,10 @@
<string name="cache_dialog_watchlist_add_message">Ajout de la cache à votre liste de suivi…</string>
<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_dialog_favourite_add_title">Favori</string>
- <string name="cache_dialog_favourite_add_message">Ajout de la cache à vos favoris…</string>
- <string name="cache_dialog_favourite_remove_title">Favori</string>
- <string name="cache_dialog_favourite_remove_message">Suppression de la cache de vos favoris…</string>
+ <string name="cache_dialog_favorite_add_title">Favori</string>
+ <string name="cache_dialog_favorite_add_message">Ajout de la cache à vos favoris…</string>
+ <string name="cache_dialog_favorite_remove_title">Favori</string>
+ <string name="cache_dialog_favorite_remove_message">Suppression de la cache de vos favoris…</string>
<string name="cache_menu_navigate">Navigation</string>
<string name="cache_menu_navigation_drive">Navigation (voiture)</string>
<string name="cache_menu_navigation_walk">Navigation (piéton)</string>
@@ -584,6 +589,7 @@
<string name="cache_menu_around">Alentours</string>
<string name="cache_menu_event">Ajouter à l\'agenda</string>
<string name="cache_menu_details">Détails</string>
+ <string name="cache_menu_refresh">Recharger</string>
<string name="cache_menu_share">Partager la cache</string>
<string name="cache_menu_move_list">Déplacer dans une autre liste</string>
<string name="cache_menu_gcc">GCC</string>
@@ -597,6 +603,8 @@
<string name="cache_status_disabled">Désactivée</string>
<string name="cache_status_premium">Membres privilégiés seulement</string>
<string name="cache_status_not_premium">Pour tous les membres</string>
+ <string name="cache_status_stored">Stockée</string>
+ <string name="cache_status_not_stored">Non stockée</string>
<string name="cache_geocode">Code gc</string>
<string name="cache_name">Nom</string>
<string name="cache_type">Type</string>
@@ -607,7 +615,7 @@
<string name="cache_rating">Note</string>
<string name="cache_own_rating">Note personnelle</string>
<string name="cache_rating_of">de</string>
- <string name="cache_favourite">Favori</string>
+ <string name="cache_favorite">Favori</string>
<string name="cache_owner">Propriétaire</string>
<string name="cache_hidden">Cachée</string>
<string name="cache_event">Date</string>
@@ -615,9 +623,7 @@
<string name="cache_coordinates">Coordonnées</string>
<string name="cache_coordinates_original">Coordonnées d\'origine</string>
<string name="cache_spoiler_images_title">Images indices</string>
- <string name="cache_spoiler_images_loading">Chargement des images indices…</string>
<string name="cache_images_title">Images</string>
- <string name="cache_images_loading">Chargement des images…</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_clear_history">Effacer l\'historique</string>
@@ -820,8 +826,6 @@
<string name="license_dismiss">Rejeter</string>
<!-- helpers -->
- <string name="helper_manual_title">Manuel</string>
- <string name="helper_manual_description">Manuel complet pour c:geo contenant la description de toutes les fonctionnalités de cette application (y compris celle secrètes).</string>
<string name="helper_calendar_title">Module supplémentaire c:geo agenda</string>
<string name="helper_calendar_missing">Module supplémentaire c:geo agenda non installé</string>
<string name="helper_calendar_description">Permet d\'exporter les événements liés aux caches dans le calendrier Android.</string>
@@ -998,6 +1002,8 @@
<string name="attribute_swamp_no">Pas de marais</string>
<string name="attribute_hills_yes">Endroit vallonné</string>
<string name="attribute_hills_no">Pas d\'endroit vallonné</string>
+ <string name="attribute_easy_climbing_yes">Escalade facile</string>
+ <string name="attribute_easy_climbing_no">Pas d\'escalade facile</string>
<string name="attribute_poi_yes">Point d\'intérêt</string>
<string name="attribute_poi_no">Pas de point d\'intérêt</string>
<string name="attribute_moving_target_yes">Cible mouvante</string>
@@ -1047,11 +1053,13 @@
<string name="legal_note">Pour utiliser les services de Geocaching.com, vous devez accepter les termes et conditions de la <a href="http://www.geocaching.com/about/termsofuse.aspx">mise en garde de Groundspeak</a>.</string>
<string name="quote">Pour faciliter le géocaching.</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">site: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">page c:geo</a></string>
- <string name="twitter">twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Manuel: <a href="http://manual.cgeo.org/">c:geo en bref</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">support: <a href="">support@cgeo.org</a></string>
+ <string name="website">site: <a href="">cgeo.org</a></string>
+ <string name="facebook">facebook: <a href="">page c:geo</a></string>
+ <string name="twitter">twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Manuel: <a href="">c:geo en bref</a></string>
+ <string name="market">Android: <a href="">c:geo sur Google Play</a></string>
<string name="about_twitter">Voulez-vous publier un nouveau statut sur Twitter à chaque nouvelle cache découverte sous <b>c:geo</b>?</string>
<string name="about_auth_1">Le processus suivant permet à <b>c:geo</b> d\'accéder à votre compte Twitter - si vous acceptez.</string>
<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>
@@ -1063,10 +1071,20 @@
<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>
+ <!-- text-to-speech for compass view -->
+ <string name="tts_service">Boussole parlante</string>
+ <string name="tts_start">Commencer à parler</string>
+ <string name="tts_stop">Arrêter de parler</string>
+ <string name="tts_kilometers">%s kilomètres</string>
+ <string name="tts_meters">%s mètres</string>
+ <string name="tts_miles">%s milles</string>
+ <string name="tts_feet">%s pieds</string>
+ <string name="tts_oclock">%s heures</string>
+
+ <!-- various -->
<string name="clipboard_copy_ok">Copié dans le presse-papiers</string>
<plurals name="days_ago">
<item quantity="one">hier</item>
<item quantity="other">il y a %d jours</item>
</plurals>
-
</resources>
diff --git a/main/res/values-hu/strings.xml b/main/res/values-hu/strings.xml
index ac2a088..17eb247 100644
--- a/main/res/values-hu/strings.xml
+++ b/main/res/values-hu/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Beállítások</string>
<string name="helpers">Hasznos segédprogramok</string>
<string name="about">A c:geo-ról</string>
- <string name="helper">Szeretnél többet megtudni a <b>c:geo</b>-ról?\nNézd meg a kézikönyvünket.</string>
<string name="latitude">Szélesség</string>
<string name="longitude">Hosszúság</string>
@@ -141,7 +140,6 @@
<string name="err_detail_cache_find">Sajnáljuk, a c:geo nem találja a geoládát.</string>
<string name="err_detail_cache_find_some">Sajnáljuk, a c:geo nem találja azt a geoládát.</string>
<string name="err_detail_cache_find_any">Sajnáljuk, a c:geo nem talál geoládákat.</string>
- <string name="err_detail_cache_find_next">Sajnáljuk, a c:geo nem találja a következő geoládákat.</string>
<string name="err_detail_cache_forgot">Sajnáljuk, a c:geo elfelejtette melyik geoládát szeretnéd.</string>
<string name="err_detail_google_maps_limit_reached">A c:geonak nem sikerült letölteni a statikus térképeket. Lehet hogy elérted a Google Maps limitjét.</string>
<string name="err_detail_no_spoiler">A c:geo nem talált spoiler képeket ehhez a ládához.</string>
@@ -248,10 +246,6 @@
<string name="caches_more_caches_currently">jelenleg</string>
<string name="caches_downloading">Ládák letöltése…\nkb.: </string>
<string name="caches_eta_ltm">Kevesebb mint egy perc</string>
- <plurals name="caches_eta_mins">
- <item quantity="one">minute</item>
- <item quantity="other">perc</item>
- </plurals>
<string name="caches_store_offline">Offlineba mentés</string>
<string name="caches_store_selected">Kijelöltek mentése</string>
<string name="caches_history">Előzmények</string>
@@ -463,8 +457,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Nincs megtalálás</item>
- <item quantity="one">Megtalálás</item>
<item quantity="other">%1$d Megtalálások</item>
</plurals>
<string name="cache_offline">Offline</string>
@@ -483,7 +475,6 @@
<string name="cache_attributes">Tulajdonságok</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>
<string name="cache_log_images_title">Bejegyzés kép</string>
<string name="cache_log_image_default_title">Fotó</string>
<string name="cache_personal_note">Személyes megjegyzés</string>
@@ -503,7 +494,6 @@
<string name="cache_waypoints">Útpontok</string>
<plurals name="waypoints">
- <item quantity="one">1 Útpontok</item>
<item quantity="other">%d Útpontok</item>
</plurals>
<string name="cache_waypoints_add">Útpont hozzáadása</string>
@@ -545,6 +535,7 @@
<string name="cache_menu_around">Közeli ládák</string>
<string name="cache_menu_event">Hozzáadás a naptárhoz</string>
<string name="cache_menu_details">Részletek</string>
+ <string name="cache_menu_refresh">Frissítés</string>
<string name="cache_menu_share">Láda megosztása</string>
<string name="cache_menu_move_list">Mozgatás másik listára</string>
<string name="cache_menu_gcc">GCC</string>
@@ -569,7 +560,7 @@
<string name="cache_rating">Osztályzat</string>
<string name="cache_own_rating">Saját értékelés</string>
<string name="cache_rating_of">/</string>
- <string name="cache_favourite">Kedvenc</string>
+ <string name="cache_favorite">Kedvenc</string>
<string name="cache_owner">Tulajdonos</string>
<string name="cache_hidden">Elrejtve</string>
<string name="cache_event">Dátum</string>
@@ -577,9 +568,7 @@
<string name="cache_coordinates">Koordináták</string>
<string name="cache_coordinates_original">Eredeti koordináták</string>
<string name="cache_spoiler_images_title">Spoiler képek</string>
- <string name="cache_spoiler_images_loading">Spoiler képek betöltése…</string>
<string name="cache_images_title">Képek</string>
- <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_clear_history">Előzmények törlése</string>
@@ -762,8 +751,6 @@
<string name="license_dismiss">Elutasítás</string>
<!-- helpers -->
- <string name="helper_manual_title">Kézikönyv</string>
- <string name="helper_manual_description">Részletes kézikönyv a c:geo-hoz amiben az összes lehetőség leírása szerepel. (még a rejtettek is).</string>
<string name="helper_calendar_title">c:geo naptár add-on</string>
<string name="helper_calendar_missing">c:geo naptár add-on nincs telepítve.</string>
<string name="helper_calendar_description">Lehetővé teszi a geoládák exportálását az eszközöd naptárába.</string>
@@ -942,11 +929,12 @@
<string name="legal_note">A geocaching.com szolgáltatásainak használatához, el kell fogadnod ezeket a feltételeket:<a href="http://www.geocaching.com/about/termsofuse.aspx">Groundspeak disclaimer</a> </string>
<string name="quote">Hogy a geocaching könnyebb legyen a felhasználók pedig lustábbak.</string>
<string name="powered_by">carnero</string>
- <string name="support">Támogatás: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string>
- <string name="website">Weboldal: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Kézikönyv: <a href="http://manual.cgeo.org/">A c:geo dióhéjban</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Támogatás: <a href="">support@cgeo.org</a></string>
+ <string name="website">Weboldal: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo page</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Kézikönyv: <a href="">A c:geo dióhéjban</a></string>
<string name="about_twitter">Akarod, hogy <b>c:geo</b> új bejegyzést írjon Twitterre mindig mikor egy ládát megtalálsz?</string>
<string name="about_auth_1">A következő folyamat engedélyezi a <b>c:geo</b>-nak, hogy hozzáférjen a Twitterhez – ha jóváhagyod.</string>
<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>
@@ -960,7 +948,6 @@
<string name="clipboard_copy_ok">Kimásolva a vágólapra</string>
<plurals name="days_ago">
- <item quantity="one">tegnap</item>
<item quantity="other">%d nappal ezelőtt</item>
</plurals>
</resources>
diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml
index af45b6f3..aeb2e2d 100644
--- a/main/res/values-it/strings.xml
+++ b/main/res/values-it/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Settaggi</string>
<string name="helpers">Apps utili</string>
<string name="about">Info c:geo</string>
- <string name="helper">Vuoi imparare di più su <b>c:geo</b>?\nLeggi il semplice manuale.</string>
<string name="latitude">Latitudine</string>
<string name="longitude">Longitudine</string>
@@ -85,6 +84,7 @@
<string name="log_tb_changeall">Cambia tutto</string>
<string name="log_save">Salva</string>
<string name="log_saving">Invio log…</string>
+ <string name="log_saving_and_uploading">Invio log e immagine…</string>
<string name="log_clear">Azzera</string>
<string name="log_post">Invia log</string>
<string name="log_post_rate">Invia log + voto</string>
@@ -118,6 +118,21 @@
<string name="log_today">Oggi</string>
<string name="log_yesterday">Ieri</string>
<string name="log_smilies">Smile</string>
+ <string name="log_image">Immagine</string>
+ <string name="log_image_attach">Aggiungi immagine</string>
+ <string name="log_image_edit">Modifica immagine</string>
+ <string name="log_image_stored">Esistente</string>
+ <string name="log_image_camera">Nuova</string>
+ <string name="log_image_caption">Didascalia</string>
+ <string name="log_image_description">Descrizione</string>
+ <string name="log_image_scale">Ridimensiona</string>
+ <string-array name="log_image_scales">
+ <item>Dimensioni originali</item>
+ <item>512 px</item>
+ <item>640 px</item>
+ <item>800 px</item>
+ <item>1024 px</item>
+ </string-array>
<!-- translation -->
<string name="translate_to_sys_lang">Traduci in %s</string>
@@ -146,7 +161,6 @@
<string name="err_detail_cache_find">c:geo non trova il geocache</string>
<string name="err_detail_cache_find_some">c:geo non trova quel geocache.</string>
<string name="err_detail_cache_find_any">c:geo non trova nessun geocache.</string>
- <string name="err_detail_cache_find_next">c:geo non trova il prossimo geocache.</string>
<string name="err_detail_cache_forgot">c:geo ha dimenticato quale geocache hai richiesto.</string>
<string name="err_detail_google_maps_limit_reached">c:geo non riesce a scaricare le mappe statiche. Forse raggiunto il limite di google map. Riprova domani.</string>
<string name="err_detail_no_spoiler">c:geo non trova alcuna immagine spoiler per questo cache.</string>
@@ -167,6 +181,8 @@
<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_select_logimage_failed">La selezione dell\'immagine per il log è fallita.</string>
+ <string name="err_acquire_image_failed">Acquisizione immagine fallita.</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>
@@ -189,6 +205,7 @@
<string name="err_log_load_data_still">c:geo sta ancora caricando i dati necessari per salvare il log. Per cortesia attendere ancora un pochino.</string>
<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_logimage_post_failed">Sembra la l\'immagine non sia stata caricata. Si prega di controllare su Geocaching.com.</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>
@@ -218,6 +235,8 @@
<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_select_logimage_cancelled">Selezione o cattura immagine annnulata.</string>
+ <string name="info_stored_image">Nuova immagine salvata su:</string>
<string name="info_storing_static_maps">Tento di salvare la static map</string>
@@ -293,7 +312,7 @@
<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>
- <string name="caches_move_all">Muovi tutte</string>
+ <string name="caches_move_all">Muovi tutti</string>
<string name="caches_map_locus">Locus</string>
<string name="caches_map_locus_export">Esporta in Locus</string>
<string name="caches_recaptcha_title">reCAPTCHA</string>
@@ -307,7 +326,10 @@
<string name="caches_filter_track">Con oggetti trackables</string>
<string name="caches_filter_clear">Rimuovi filtri</string>
<string name="caches_filter_modified">Con coordinate modificate</string>
+ <string name="caches_filter_origin">Origine</string>
<string name="caches_removing_from_history">Rimozione dalla cronologia…</string>
+ <string name="caches_clear_offlinelogs">Cancella i log offline</string>
+ <string name="caches_clear_offlinelogs_progress">Cancellazione logs offline</string>
<!-- caches lists -->
<string name="list_menu">Lista</string>
@@ -340,10 +362,9 @@
<!-- init -->
<string name="init_geocaching">Geocaching.com</string>
+ <string name="init_gc_activate">Attiva Geocaching.com su mappa live e nelle ricerche</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>
@@ -386,7 +407,8 @@
<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_log_offline">Quando salvi log, fallo sempre offline (non visualizzerà lo schermo di log online, non invierà subito il log)</string>
+ <string name="init_log_offline">Attiva log offline (non visualizzerà lo schermo di log online, non invierà subito il log)</string>
+ <string name="init_choose_list">Chiedi la lista quando salvi un cache</string>
<string name="init_livelist">Visualizza in che direzione sono i cache, nelle liste</string>
<string name="init_altitude">Correzione di altitudine</string>
<string name="init_altitude_description">Se il GPS restituisce un\'errata altitudine, puoi correggerla inserendo un valore positivo o negativo, in metri.</string>
@@ -437,6 +459,12 @@
<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>
+ <!-- map sources -->
+ <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>
+ <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_name">Nome dispositivo:</string>
@@ -464,9 +492,8 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Nessun cache</item>
<item quantity="one">Un cache</item>
- <item quantity="other">%1$d Cache</item>
+ <item quantity="other">%1$d cache</item>
</plurals>
<string name="cache_offline">Offline</string>
<string name="cache_offline_refresh">Aggiorna</string>
@@ -484,10 +511,11 @@
<string name="cache_attributes">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>
<string name="cache_log_images_title">Immagini Log</string>
<string name="cache_log_image_default_title">Foto</string>
<string name="cache_personal_note">Note personali</string>
+ <string name="cache_personal_note_unstored">Cache non salvati</string>
+ <string name="cache_personal_note_store">Il cache verrà prima salvato per abilitare le note personali.</string>
<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 %s per vederla correttamente.</string>
@@ -499,6 +527,9 @@
<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_list_text">Lista:</string>
+ <string name="cache_list_change">Sposta</string>
+ <string name="cache_list_unknown">Non in una lista</string>
<string name="cache_images">Immagini</string>
<string name="cache_waypoints">Waypoints</string>
@@ -530,10 +561,10 @@
<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_dialog_favorite_add_title">Preferiti</string>
+ <string name="cache_dialog_favorite_add_message">Aggiungi il cache ai tuoi preferiti…</string>
+ <string name="cache_dialog_favorite_remove_title">Preferiti</string>
+ <string name="cache_dialog_favorite_remove_message">Rimozione cache dai tuoi preferiti…</string>
<string name="cache_menu_navigate">Naviga</string>
<string name="cache_menu_navigation_drive">Naviga (in auto)</string>
<string name="cache_menu_navigation_walk">Naviga (a piedi)</string>
@@ -552,6 +583,7 @@
<string name="cache_menu_around">Cache qui intorno</string>
<string name="cache_menu_event">Aggiungi al calendario</string>
<string name="cache_menu_details">Dettagli</string>
+ <string name="cache_menu_refresh">Aggiorna</string>
<string name="cache_menu_share">Condividi cache</string>
<string name="cache_menu_move_list">Muovi in un\'altra lista</string>
<string name="cache_menu_gcc">GCC</string>
@@ -575,7 +607,7 @@
<string name="cache_rating">Voto</string>
<string name="cache_own_rating">Il tuo voto</string>
<string name="cache_rating_of">di</string>
- <string name="cache_favourite">Popolarità</string>
+ <string name="cache_favorite">Popolarità</string>
<string name="cache_owner">Proprietario</string>
<string name="cache_hidden">Nascosto il</string>
<string name="cache_event">Data</string>
@@ -583,9 +615,7 @@
<string name="cache_coordinates">Coordinate</string>
<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_clear_history">Cancella cronologia</string>
@@ -656,6 +686,7 @@
<string name="waypoint_edit_title">Modifica waypoint</string>
<string name="waypoint_add_title">Aggiungi waypoint</string>
<string name="waypoint_note">Note</string>
+ <string name="waypoint_visited">Visitato</string>
<string name="waypoint_save">Salva</string>
<string name="waypoint_loading">Caricamento waypoint…</string>
<string name="waypoint_do_not_touch_cache_coordinates">Nessuna modifica alle coordinate cache</string>
@@ -783,8 +814,6 @@
<string name="license_dismiss">Chiudi</string>
<!-- helpers -->
- <string name="helper_manual_title">Manual</string>
- <string name="helper_manual_description">Manuale dettagliato di c:geo che contiene la descrizione di tutte le possibilità offerte da questa applicazione, comprese quelle nascoste (in inglese).</string>
<string name="helper_calendar_title">c:geo calendario add-on</string>
<string name="helper_calendar_missing">c:geo calendario add-on non installato</string>
<string name="helper_calendar_description">Permette di esportare gli eventi cache nel calendario del tuo dispositivo.</string>
@@ -816,10 +845,7 @@
<string name="export_gpx_info">Il file GPX sarà esportato in %1$s con data ed ora correnti come nome file.</string>
<string name="export_gpx_to">Invia il GPX esportato a</string>
-<!-- attribute unknown -->
- <string name="attribute_unknown_yes">(attributo sconosciuto) permesso</string>
- <string name="attribute_unknown_no">(attributo sconosciuto) non permesso</string>
- <!-- attributes (permissions -> allowed, not allowed) -->
+ <!-- GC attributes -->
<string name="attribute_dogs_yes">Cani permessi</string>
<string name="attribute_dogs_no">Cani NON permessi</string>
<string name="attribute_bicycles_yes">Biciclette permesse</string>
@@ -838,8 +864,6 @@
<string name="attribute_campfires_no">Fuochi da campo NON permessi</string>
<string name="attribute_rv_yes">Camper/roulotte permessi</string>
<string name="attribute_rv_no">Camper/roulotte NON permessi</string>
-
- <!-- attributes (conditions -> yes, no) -->
<string name="attribute_kids_yes">Raccomandato per bambini</string>
<string name="attribute_kids_no">Non raccomandato per bambini</string>
<string name="attribute_onehour_yes">Richiede meno di un\'ora</string>
@@ -892,8 +916,6 @@
<string name="attribute_landf_no">Non è un tour \"Lost and found\"</string>
<string name="attribute_partnership_yes">Cache di gruppo</string>
<string name="attribute_partnership_no">Cache non di gruppo</string>
-
- <!-- attributes (equipment -> required, not required) -->
<string name="attribute_fee_yes">Accesso o parcheggio a pagamento</string>
<string name="attribute_fee_no">Accesso o parcheggio non a pagamento</string>
<string name="attribute_rappelling_yes">Richiesta attrezzatura da arrampicata</string>
@@ -916,8 +938,6 @@
<string name="attribute_wirelessbeacon_no">Segnalatore radio non necessario</string>
<string name="attribute_treeclimbing_yes">Richiede di salire su un albero</string>
<string name="attribute_treeclimbing_no">Non richiede di salire su un albero</string>
-
- <!-- attributes (hazards -> present, not present) -->
<string name="attribute_poisonoak_yes">Piante velenose</string>
<string name="attribute_poisonoak_no">Piante non velenose</string>
<string name="attribute_dangerousanimals_yes">Animali pericolosi</string>
@@ -934,8 +954,6 @@
<string name="attribute_danger_no">Area non pericolosa</string>
<string name="attribute_thorn_yes">Rovi</string>
<string name="attribute_thorn_no">Senza rovi</string>
-
- <!-- attributes (facilities -> yes, no) -->
<string name="attribute_wheelchair_yes">Accessibile con sedia a rotelle</string>
<string name="attribute_wheelchair_no">Non accessibile con sedia a rotelle</string>
<string name="attribute_parking_yes">Parcheggio</string>
@@ -958,16 +976,79 @@
<string name="attribute_fuel_no">Lontano da pompa carburante</string>
<string name="attribute_food_yes">Vicino a punto ristoro</string>
<string name="attribute_food_no">Lontano da punti ristoro</string>
+
+ <string name="attribute_oc_only_yes">Loggabile solo su Opencaching</string>
+ <string name="attribute_oc_only_no">Loggabile non solo su Opencaching</string>
+ <string name="attribute_link_only_yes">Hyperlink solo verso un altro portale di cache</string>
+ <string name="attribute_link_only_no">Non solo hyperlink ad un altro portale di cache</string>
+ <string name="attribute_letterbox_yes">Lettera (richiede francobollo)</string>
+ <string name="attribute_letterbox_no">No lettera (non richiede francobollo)</string>
+ <string name="attribute_railway_yes">Ferrovia attiva nelle vicinanze</string>
+ <string name="attribute_railway_no">Nessuna ferrovia nelle vicinanze</string>
+ <string name="attribute_syringe_yes">Pronto soccorso disponibile</string>
+ <string name="attribute_syringe_no">Pronto soccorso non disponibile</string>
+ <string name="attribute_swamp_yes">Paludoso</string>
+ <string name="attribute_swamp_no">Non paludoso</string>
+ <string name="attribute_hills_yes">Area collinare</string>
+ <string name="attribute_hills_no">Area non collinare</string>
+ <string name="attribute_easy_climbing_yes">Facile scalata</string>
+ <string name="attribute_easy_climbing_no">Nessuna facile scalata</string>
+ <string name="attribute_poi_yes">Punto di interesse</string>
+ <string name="attribute_poi_no">Nessun punto di interesse</string>
+ <string name="attribute_moving_target_yes">Obiettivo in movimento</string>
+ <string name="attribute_moving_target_no">Obiettivo non in movimento</string>
+ <string name="attribute_webcam_yes">Webcam</string>
+ <string name="attribute_webcam_no">No webcam</string>
+ <string name="attribute_inside_yes">Con aree interne (cave, edifici etc.)</string>
+ <string name="attribute_inside_no">Senza aree interne</string>
+ <string name="attribute_in_water_yes">In acqua</string>
+ <string name="attribute_in_water_no">Non in acqua</string>
+ <string name="attribute_no_gps_yes">Senza GPS (lettere, cistes, carta e bussola…)</string>
+ <string name="attribute_no_gps_no">Con GPS</string>
+ <string name="attribute_overnight_yes">Necessario permanere di notte</string>
+ <string name="attribute_overnight_no">Permanenza notturna non necessaria</string>
+ <string name="attribute_specific_times_yes">Disponibile solo in certi orari</string>
+ <string name="attribute_specific_times_no">Disponibile a tutte le ore</string>
+ <string name="attribute_day_yes">Solo di giorno</string>
+ <string name="attribute_day_no">Non solo di giorno</string>
+ <string name="attribute_tide_yes">Marea</string>
+ <string name="attribute_tide_no">Senza marea</string>
+ <string name="attribute_all_seasons_yes">Tutte le stagioni</string>
+ <string name="attribute_all_seasons_no">Non in tutte le stagioni</string>
+ <string name="attribute_breeding_yes">Stagione di riproduzione / natura protetta</string>
+ <string name="attribute_breeding_no">Disponibile anche in stagione di riproduzione / natura protetta</string>
+ <string name="attribute_snow_proof_yes">Nascondiglio a prova di neve</string>
+ <string name="attribute_snow_proof_no">Nascondiglio non a prova di neve</string>
+ <string name="attribute_compass_yes">Bussola</string>
+ <string name="attribute_compass_no">Senza bussola</string>
+ <string name="attribute_cave_yes">Equipaggiamento da caverna</string>
+ <string name="attribute_cave_no">Senza equipaggiamento da caverna</string>
+ <string name="attribute_aircraft_yes">Aircraft</string>
+ <string name="attribute_aircraft_no">Senza aircraft</string>
+ <string name="attribute_investigation_yes">Investigazione</string>
+ <string name="attribute_investigation_no">Senza investigazione</string>
+ <string name="attribute_puzzle_yes">Puzzle / Mystery</string>
+ <string name="attribute_puzzle_no">No puzzle / mystery</string>
+ <string name="attribute_arithmetic_yes">Problema aritmetico</string>
+ <string name="attribute_arithmetic_no">Problema non aritmetico</string>
+ <string name="attribute_other_cache_yes">Cache di altro tipo</string>
+ <string name="attribute_other_cache_no">Cache non di altro tipo</string>
+ <string name="attribute_ask_owner_yes">Chiedere al proprietario per le condizioni di partenza</string>
+ <string name="attribute_ask_owner_no">Non chiedere al proprietario per le condizioni di partenza</string>
+ <string name="attribute_unknown_yes">Attributo sconosciuto</string>
+ <string name="attribute_unknown_no">Senza attributo sconosciuto</string>
<!-- next things -->
<string name="legal_note">Per usare i servizi di Geocaching.com, si applicano i termini e le condizioni del <a href="http://www.geocaching.com/about/termsofuse.aspx">Contratto Groundspeak</a> che deve essere approvato dall\'utente.</string>
<string name="quote">Per rendere il geocaching più facile e rendere gli utenti più pigri.</string>
<string name="powered_by">carnero</string>
- <string name="support">Supporto: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string>
- <string name="website">Sito: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">pagina c:geo </a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Manuale: <a href="http://manual.cgeo.org/">c:geo in a Nutshell</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Supporto: <a href="">support@cgeo.org</a></string>
+ <string name="website">Sito: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">pagina c:geo </a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Manuale: <a href="">c:geo in a Nutshell</a></string>
+ <string name="market">Android: <a href="">c:geo su Google Play</a></string>
<string name="about_twitter">Può <b>c:geo</b> pubblicare su Twitter ogni volta che logghi un cache?</string>
<string name="about_auth_1">La procesura seguente autorizza <b>c:geo</b> ad accedere a Twitter - se confermato.</string>
<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>
@@ -979,6 +1060,15 @@
<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>
+ <!-- text-to-speech for compass view -->
+ <string name="tts_service">Bussola parlante</string>
+ <string name="tts_start">Start voce</string>
+ <string name="tts_stop">Stop voce</string>
+ <string name="tts_kilometers">%s chilometri</string>
+ <string name="tts_meters">%s metri</string>
+ <string name="tts_oclock">%s precisi</string>
+
+ <!-- various -->
<string name="clipboard_copy_ok">Copiato nella clipboard</string>
<plurals name="days_ago">
<item quantity="one">ieri</item>
diff --git a/main/res/values-ja/strings.xml b/main/res/values-ja/strings.xml
index b916828..9e19b84 100644
--- a/main/res/values-ja/strings.xml
+++ b/main/res/values-ja/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">設定</string>
<string name="helpers">役に立つアプリ</string>
<string name="about">c:geoについて</string>
- <string name="helper"><b>c:geo</b>についてもっと知りたい?\nマニュアル(英語)を読んでね。</string>
<string name="latitude">緯度</string>
<string name="longitude">経度</string>
@@ -146,7 +145,6 @@
<string name="err_detail_cache_find">キャッシュ情報が見つかりません。</string>
<string name="err_detail_cache_find_some">キャッシュ情報が見つかりません。</string>
<string name="err_detail_cache_find_any">キャッシュ情報が一つも見つかりません。</string>
- <string name="err_detail_cache_find_next">次のキャッシュ情報が見つかりません。</string>
<string name="err_detail_cache_forgot">c:geo forgot which geocache you want.</string>
<string name="err_detail_google_maps_limit_reached">オフライン用の地図のダウンロードに失敗しました。大量のデータをダウンロードしたと判断されGoogleマップ側に制限されたかもしれません。</string>
<string name="err_detail_no_spoiler">このキャッシュのスポイラー画像を見つけることができませんでした。</string>
@@ -255,7 +253,6 @@
<string name="caches_downloading">キャッシュ情報をダウンロード中…\n残り時間: </string>
<string name="caches_eta_ltm">1分以内</string>
<plurals name="caches_eta_mins">
- <item quantity="one">分</item>
<item quantity="other">分</item>
</plurals>
<string name="caches_store_offline">オフライン用に保存</string>
@@ -345,8 +342,6 @@
<string name="init_geocaching">Geocaching.com</string>
<string name="init_oc">opencaching.de</string>
<string name="init_oc_activate">オンライン地図や検索でopencaching.deも使用する</string>
- <string name="init_oc_username_description">見つけたキャッシュなどをマークするにはopencaching.deのユーザ名を入力してください。</string>
- <string name="init_oc_username">ユーザ名</string>
<string name="init_gcvote">GCvote.com</string>
<string name="init_twitter">Twitter</string>
<string name="init_username">ユーザ名</string>
@@ -474,8 +469,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">キャッシュがありません</item>
- <item quantity="one">1つのキャッシュ</item>
<item quantity="other">%1$d 個のキャッシュ</item>
</plurals>
<string name="cache_offline">オフライン</string>
@@ -494,7 +487,6 @@
<string name="cache_attributes">属性</string>
<string name="cache_inventory">目録</string>
<string name="cache_log_offline">オフラインログ</string>
- <string name="cache_log_images_loading">添付画像をロード中…</string>
<string name="cache_log_images_title">ログの添付画像</string>
<string name="cache_log_image_default_title">写真</string>
<string name="cache_personal_note">パーソナルノート</string>
@@ -514,7 +506,6 @@
<string name="cache_waypoints">ウェイポイント</string>
<plurals name="waypoints">
- <item quantity="one">1 ウェイポイント</item>
<item quantity="other">%d ウェイポイント</item>
</plurals>
<string name="cache_waypoints_add">ウェイポイントを追加</string>
@@ -541,10 +532,10 @@
<string name="cache_dialog_watchlist_add_message">ウォッチリストに追加中…</string>
<string name="cache_dialog_watchlist_remove_title">ウォッチリスト</string>
<string name="cache_dialog_watchlist_remove_message">ウォッチリストから削除中…</string>
- <string name="cache_dialog_favourite_add_title">お気に入り</string>
- <string name="cache_dialog_favourite_add_message">お気に入りに追加中…</string>
- <string name="cache_dialog_favourite_remove_title">お気に入り</string>
- <string name="cache_dialog_favourite_remove_message">お気に入りから削除中…</string>
+ <string name="cache_dialog_favorite_add_title">お気に入り</string>
+ <string name="cache_dialog_favorite_add_message">お気に入りに追加中…</string>
+ <string name="cache_dialog_favorite_remove_title">お気に入り</string>
+ <string name="cache_dialog_favorite_remove_message">お気に入りから削除中…</string>
<string name="cache_menu_navigate">ナビゲーション</string>
<string name="cache_menu_navigation_drive">ナビゲーション(自動車)</string>
<string name="cache_menu_navigation_walk">ナビゲーション(徒歩)</string>
@@ -563,6 +554,7 @@
<string name="cache_menu_around">近くのキャッシュ</string>
<string name="cache_menu_event">カレンダーに登録</string>
<string name="cache_menu_details">詳細</string>
+ <string name="cache_menu_refresh">更新</string>
<string name="cache_menu_share">キャッシュを共有</string>
<string name="cache_menu_move_list">他のリストに移動</string>
<string name="cache_menu_gcc">GCC</string>
@@ -587,7 +579,7 @@
<string name="cache_rating">評価</string>
<string name="cache_own_rating">Own Rating</string>
<string name="cache_rating_of">/</string>
- <string name="cache_favourite">お気に入り</string>
+ <string name="cache_favorite">お気に入り</string>
<string name="cache_owner">所有者</string>
<string name="cache_hidden">隠した日</string>
<string name="cache_event">イベント日付</string>
@@ -595,9 +587,7 @@
<string name="cache_coordinates">座標</string>
<string name="cache_coordinates_original">オリジナル座標</string> <!-- 「初公開時の座標」の方がいいかも -->
<string name="cache_spoiler_images_title">スポイラー画像</string>
- <string name="cache_spoiler_images_loading">スポイラー画像をロード中…</string>
<string name="cache_images_title">画像</string>
- <string name="cache_images_loading">画像をロード中…</string>
<string name="cache_log_types">ログタイプ</string>
<string name="cache_coordinates_no">このキャッシュに座標値はありません。</string>
<string name="cache_clear_history">全履歴を削除</string>
@@ -796,8 +786,6 @@
<string name="license_dismiss">閉じる</string>
<!-- helpers -->
- <string name="helper_manual_title">マニュアル</string>
- <string name="helper_manual_description">c:geoのマニュアル(英語)はこのアプリでできる事(隠れ機能も)の全てについて書いてあります。</string>
<string name="helper_calendar_title">c:geo - カレンダープラグイン</string>
<string name="helper_calendar_missing">c:geo - カレンダープラグインはインストールされていません。</string>
<string name="helper_calendar_description">イベントキャッシュをカレンダーアプリに登録することができます。</string>
@@ -976,11 +964,12 @@
<string name="legal_note">Geocaching.comを使うには<a href="http://www.geocaching.com/about/termsofuse.aspx">Groundspeak 利用規約</a>(英語)に同意している必要があります。</string>
<string name="quote">To make geocaching easier, to make users lazier.</string>
<string name="powered_by">carnero</string>
- <string name="support">サポート: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string>
- <string name="website">Webサイト: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">マニュアル: <a href="http://manual.cgeo.org/">c:geo マニュアル</a>(英語)</string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">サポート: <a href="">support@cgeo.org</a></string>
+ <string name="website">Webサイト: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo page</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">マニュアル: <a href="">c:geo マニュアル</a>(英語)</string>
<string name="about_twitter">キャッシュのログを書いたら<b>c:geo</b>にTwitterでつぶやいてほしい?</string>
<string name="about_auth_1"><b>c:geo</b>がTwitterにアクセスする許可を得るには次のようにしてください。</string>
<string name="about_auth_2">「認証を開始する」ボタンを押すとブラウザでTwitterのページが開きます。そのページにログインすれば<b>c:geo</b>があなたのアカウントにアクセルする許可が得られます。ログインに成功したら数字のPINコードが表示されるので、この下の入力欄にコピー&amp;ペーストして「完了」ボタンを押してください。</string>
@@ -994,7 +983,6 @@
<string name="clipboard_copy_ok">クリップボードにコピーしました</string>
<plurals name="days_ago">
- <item quantity="one">昨日</item>
<item quantity="other">%d日前</item>
</plurals>
</resources>
diff --git a/main/res/values-nb/strings.xml b/main/res/values-nb/strings.xml
index 1cf6bf5..1319137 100644
--- a/main/res/values-nb/strings.xml
+++ b/main/res/values-nb/strings.xml
@@ -96,7 +96,6 @@
<string name="err_detail_cache_find">Beklager, c:geo klarte ikke å finne geocachen</string>
<string name="err_detail_cache_find_some">Beklager, c:geo klarte ikke å finne den forespurte cachen.</string>
<string name="err_detail_cache_find_any">Beklager, c:geo klarte ikke finne geocacher..</string>
- <string name="err_detail_cache_find_next">Beklager, c:geo klarte ikke å finne den neste geocachen.</string>
<string name="err_detail_cache_forgot">Beklager, c:geo glemte hvilken cache du ønsket.</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>
@@ -236,9 +235,8 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Ingen cacher</item>
<item quantity="one">Én cache</item>
- <item quantity="other">%1$d Cacher</item>
+ <item quantity="other">%1$d cacher</item>
</plurals>
<string name="cache_offline">Offline</string>
<string name="cache_offline_refresh">Oppdater</string>
@@ -280,6 +278,7 @@
<string name="cache_menu_around">Cacher i nærheten</string>
<string name="cache_menu_event">Eksporter til kalender</string>
<string name="cache_menu_details">Detaljer</string>
+ <string name="cache_menu_refresh">Oppdater</string>
<string name="cache_status">Status</string>
<string name="cache_status_offline_log">Logg lagret</string>
<string name="cache_status_found">Funnet</string>
diff --git a/main/res/values-nl/strings.xml b/main/res/values-nl/strings.xml
index 9453601..8c92509 100644
--- a/main/res/values-nl/strings.xml
+++ b/main/res/values-nl/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Instellingen</string>
<string name="helpers">Wat te installeren</string>
<string name="about">Over c:geo</string>
- <string name="helper">Wil je meer weten over <b>c:geo</b>?\nKijk dan in de (makkelijk te lezen) handleiding.</string>
<string name="latitude">Breedtegraad</string>
<string name="longitude">Lengtegraad</string>
@@ -146,7 +145,6 @@
<string name="err_detail_cache_find">Sorry, c:geo kan de geocache niet vinden.</string>
<string name="err_detail_cache_find_some">Sorry, c:geo kan die geocache niet vinden.</string>
<string name="err_detail_cache_find_any">Sorry, c:geo kan geen enkele geocache vinden.</string>
- <string name="err_detail_cache_find_next">Sorry, c:geo kan de volgende cache niet vinden.</string>
<string name="err_detail_cache_forgot">Sorry, c:geo is kwijt welke geocache je wilde openen.</string>
<string name="err_detail_google_maps_limit_reached">c:geo kon de statische kaarten niet downloaden. Wellicht dat de Google Maps limiet is bereikt.</string>
<string name="err_detail_no_spoiler">c:geo Heeft geen spoiler images gevonden voor deze cache.</string>
@@ -347,8 +345,6 @@
<string name="init_geocaching">Geocaching.com</string>
<string name="init_oc">opencaching.de</string>
<string name="init_oc_activate">Activeer opencaching.de op live-kaart en in zoekopdrachten.</string>
- <string name="init_oc_username_description">Vul je opencaching.de gebruikersnaam in op caches als gevonden te markeren.</string>
- <string name="init_oc_username">Vul gebruikersnaam in</string>
<string name="init_gcvote">GCvote.com</string>
<string name="init_twitter">Twitter</string>
<string name="init_username">Gebruikersnaam</string>
@@ -477,7 +473,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Geen cache</item>
<item quantity="one">Een cache</item>
<item quantity="other">%1$d Caches</item>
</plurals>
@@ -497,7 +492,6 @@
<string name="cache_attributes">Attributen</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>
<string name="cache_log_images_title">Logafbeelding</string>
<string name="cache_log_image_default_title">Foto</string>
<string name="cache_personal_note">Persoonlijke aantekening</string>
@@ -547,10 +541,10 @@
<string name="cache_dialog_watchlist_add_message">Voeg cache toe aan watchlist…</string>
<string name="cache_dialog_watchlist_remove_title">Watchlist</string>
<string name="cache_dialog_watchlist_remove_message">Verwijder cache van watchlist…</string>
- <string name="cache_dialog_favourite_add_title">Favoriet</string>
- <string name="cache_dialog_favourite_add_message">Voeg cache toe aan favorieten…</string>
- <string name="cache_dialog_favourite_remove_title">Favoriet</string>
- <string name="cache_dialog_favourite_remove_message">Verwijder cache van je favorieten…</string>
+ <string name="cache_dialog_favorite_add_title">Favoriet</string>
+ <string name="cache_dialog_favorite_add_message">Voeg cache toe aan favorieten…</string>
+ <string name="cache_dialog_favorite_remove_title">Favoriet</string>
+ <string name="cache_dialog_favorite_remove_message">Verwijder cache van je favorieten…</string>
<string name="cache_menu_navigate">Navigeer</string>
<string name="cache_menu_navigation_drive">Navigeer (rijden)</string>
<string name="cache_menu_navigation_walk">Navigeer (lopen)</string>
@@ -569,6 +563,7 @@
<string name="cache_menu_around">Caches rondom</string>
<string name="cache_menu_event">Toevoegen aan kalender</string>
<string name="cache_menu_details">Details</string>
+ <string name="cache_menu_refresh">Verversen</string>
<string name="cache_menu_share">Deel cache</string>
<string name="cache_menu_move_list">Verplaats naar andere lijst</string>
<string name="cache_menu_gcc">GCC</string>
@@ -592,7 +587,7 @@
<string name="cache_rating">Waardering</string>
<string name="cache_own_rating">Eigen waardering</string>
<string name="cache_rating_of">van</string>
- <string name="cache_favourite">Favoriet</string>
+ <string name="cache_favorite">Favoriet</string>
<string name="cache_owner">Eigenaar</string>
<string name="cache_hidden">Verstopt</string>
<string name="cache_event">Datum</string>
@@ -600,9 +595,7 @@
<string name="cache_coordinates">Coördinaten</string>
<string name="cache_coordinates_original">Originele coordinaten</string>
<string name="cache_spoiler_images_title">Spoiler afbeeldingen</string>
- <string name="cache_spoiler_images_loading">Spoiler afbeeldingen laden…</string>
<string name="cache_images_title">Afbeeldingen</string>
- <string name="cache_images_loading">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_clear_history">Maak geschiedenis leeg</string>
@@ -804,8 +797,6 @@
<string name="license_dismiss">Afwijzen</string>
<!-- helpers -->
- <string name="helper_manual_title">Handleiding</string>
- <string name="helper_manual_description">Uitgebreide handleiding voor c:geo welke alle mogelijkheden van deze applicatie uitlegt (ook de verborgen mogelijkheden).</string>
<string name="helper_calendar_title">c:geo kalender add-on</string>
<string name="helper_calendar_missing">c:geo kalender add-on niet geinstalleerd.</string>
<string name="helper_calendar_description">Maakt het mogelijk om Geocaching events in je kalender op te slaan.</string>
@@ -1031,11 +1022,12 @@
<string name="legal_note">Voor het gebruik van de diensten van Geocaching.com, dient akkoord te worden gegaan met de <a href="http://www.geocaching.com/about/termsofuse.aspx">Groundspeak voorwaarden</a>.</string>
<string name="quote">Om geocahing makkelijker te maken en gebruikers luier te maken.</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 page</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Handleiding: <a href="http://manual.cgeo.org/">c:geo in een notendop</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">support:<a href="">support@cgeo.org</a></string>
+ <string name="website">website: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo page</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Handleiding: <a href="">c:geo in een notendop</a></string>
<string name="about_twitter">Moet <b>c:geo</b> elke cache vondst publiceren naar Twitter?</string>
<string name="about_auth_1">Het volgende proces staat <b>c:geo</b> toe om Twitter toegang te verkrijgen bij goedkeuring.</string>
<string name="about_auth_2">Klik op de \"autoriseer c:geo\" knop om het proces te starten. Dit proces zal een browser openen met een Twitter pagina. Login op deze pagina en sta <b>c:geo</b> toegang tot je account toe. Bij goedkeuring laat Twitter een numerieke PIN code zien. Deze PIN dien je te plakken en te bevestigen in <b>c:geo</b>.</string>
diff --git a/main/res/values-pl/strings.xml b/main/res/values-pl/strings.xml
index 49e8c6b..f4f3b46 100644
--- a/main/res/values-pl/strings.xml
+++ b/main/res/values-pl/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Ustawienia</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 obsługi.</string>
<string name="latitude">Szerokość geograficzna</string>
<string name="longitude">Długość geograficzna</string>
@@ -126,6 +125,7 @@
<string name="log_image_camera">Nowy</string>
<string name="log_image_caption">Podpis</string>
<string name="log_image_description">Opis</string>
+ <string name="log_image_scale">Skalowanie obrazu</string>
<!-- translation -->
<string name="translate_to_sys_lang">Przetłumacz na %s</string>
@@ -154,7 +154,6 @@
<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_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>
@@ -175,7 +174,7 @@
<string name="err_missing_device_name">Proszę podać nazwę urządzenia przed zarejestrowaniem.</string>
<string name="err_favorite_failed">Zmiana statusu skrzynki ulubiona nie powiodła się.</string>
<string name="err_select_logimage_failed">Nie można wybrać obrazu.</string>
- <string name="err_aquire_image_failed">NIe można pobrać obrazu.</string>
+ <string name="err_acquire_image_failed">Nie można pobrać obrazu.</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>
@@ -363,8 +362,6 @@
<string name="init_gc_activate">Aktywuj Geocaching.com na aktualnej mapie i w wyszukiwaniu</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>
@@ -511,7 +508,6 @@
<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ęć 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>
@@ -562,10 +558,10 @@
<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_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_dialog_favorite_add_title">Ulubione</string>
+ <string name="cache_dialog_favorite_add_message">Dodaję skrzynkę do listy ulubionych…</string>
+ <string name="cache_dialog_favorite_remove_title">Ulubione</string>
+ <string name="cache_dialog_favorite_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>
@@ -584,6 +580,7 @@
<string name="cache_menu_around">Skrzynki w okręgu</string>
<string name="cache_menu_event">Dodaj do kalendarza</string>
<string name="cache_menu_details">Szczegóły</string>
+ <string name="cache_menu_refresh">Odśwież</string>
<string name="cache_menu_share">Podziel się skrzynką</string>
<string name="cache_menu_move_list">Przenieś do innej listy</string>
<string name="cache_menu_gcc">GCC</string>
@@ -597,6 +594,8 @@
<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_status_stored">Zapisano</string>
+ <string name="cache_status_not_stored">Nie zapisano</string>
<string name="cache_geocode">GC-kod</string>
<string name="cache_name">Nazwa</string>
<string name="cache_type">Typ</string>
@@ -607,7 +606,7 @@
<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">Ulubiona</string>
+ <string name="cache_favorite">Ulubiona</string>
<string name="cache_owner">Właściciel</string>
<string name="cache_hidden">Ukryta</string>
<string name="cache_event">Data</string>
@@ -615,9 +614,7 @@
<string name="cache_coordinates">Współrzędne</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_clear_history">Usuń historię</string>
@@ -818,8 +815,6 @@
<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 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>
@@ -996,6 +991,8 @@
<string name="attribute_swamp_no">Brak bagien lub mokradeł</string>
<string name="attribute_hills_yes">Pagórki</string>
<string name="attribute_hills_no">Brak pagórków</string>
+ <string name="attribute_easy_climbing_yes">Łatwa wspinaczka </string>
+ <string name="attribute_easy_climbing_no">Nie jest to łatwa wspinaczka</string>
<string name="attribute_poi_yes">Ciekawe miejsce</string>
<string name="attribute_poi_no">Brak ciekawych miejsc</string>
<string name="attribute_moving_target_yes">Skrzynka moblina</string>
@@ -1045,11 +1042,12 @@
<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">Podręcznik: <a href="http://manual.cgeo.org/">c:geo skrócona instrukcja obsługi</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Support: <a href="">support@cgeo.org</a></string>
+ <string name="website">Website: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo strona</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Podręcznik: <a href="">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>
diff --git a/main/res/values-pt/strings.xml b/main/res/values-pt/strings.xml
index 5f67281..f00a835 100644
--- a/main/res/values-pt/strings.xml
+++ b/main/res/values-pt/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Definições</string>
<string name="helpers">Apps Úteis</string>
<string name="about">Sobre c:geo</string>
- <string name="helper">Quer aprender acerca do <b>c:geo</b>?\nVeja o nosso prático manual.</string>
<string name="latitude">Latitude</string>
<string name="longitude">Longitude</string>
@@ -142,7 +141,6 @@
<string name="err_detail_cache_find">O c:geo não encontra a geocache</string>
<string name="err_detail_cache_find_some">O c:geo não encontra essa geocache.</string>
<string name="err_detail_cache_find_any">O c:geo não encontra qualquer geocache.</string>
- <string name="err_detail_cache_find_next">O c:geo não encontra as próximas geocaches.</string>
<string name="err_detail_cache_forgot">O c:geo esqueceu a geocache pretendida.</string>
<string name="err_detail_google_maps_limit_reached">O c:geo falhou no download dos mapas. Talvez o tenha atingido o limite do Google Maps.</string>
<string name="err_detail_no_spoiler">O c:geo não encontrou images spoiler para esta cache.</string>
@@ -464,7 +462,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Nenhuma cache</item>
<item quantity="one">Uma cache</item>
<item quantity="other">%1$d Caches</item>
</plurals>
@@ -484,7 +481,6 @@
<string name="cache_attributes">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>
<string name="cache_log_images_title">Imagem do registo</string>
<string name="cache_log_image_default_title">Foto</string>
<string name="cache_personal_note">Nota pessoal</string>
@@ -549,6 +545,7 @@
<string name="cache_menu_around">Caches próximas</string>
<string name="cache_menu_event">Adicionar ao calendário</string>
<string name="cache_menu_details">Detalhes</string>
+ <string name="cache_menu_refresh">Actualizar</string>
<string name="cache_menu_share">Partilhar cache</string>
<string name="cache_menu_move_list">Mover para outra lista</string>
<string name="cache_menu_gcc">GCC</string>
@@ -572,7 +569,7 @@
<string name="cache_rating">Pontuação</string>
<string name="cache_own_rating">A minha pontuação</string>
<string name="cache_rating_of">de</string>
- <string name="cache_favourite">Favorita</string>
+ <string name="cache_favorite">Favorita</string>
<string name="cache_owner">Dono</string>
<string name="cache_hidden">Escondida</string>
<string name="cache_event">Data</string>
@@ -580,9 +577,7 @@
<string name="cache_coordinates">Coordenadas</string>
<string name="cache_coordinates_original">Coordenadas originais</string>
<string name="cache_spoiler_images_title">Imagens spoiler</string>
- <string name="cache_spoiler_images_loading">A carregar imagens spoiler…</string>
<string name="cache_images_title">Imagens</string>
- <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_clear_history">Apagar histórico</string>
@@ -766,8 +761,6 @@
<string name="license_dismiss">Dispensar</string>
<!-- helpers -->
- <string name="helper_manual_title">Manual</string>
- <string name="helper_manual_description">Manual prático do c:geo, que contém a descrição de todas as funcionalidades desta aplicação (mesmo as que estão escondidas).</string>
<string name="helper_calendar_title">Add on calendário para c:geo </string>
<string name="helper_calendar_missing">Add on calendário para o c:geo não está instalado.</string>
<string name="helper_calendar_description">Permite exportar caches evento para o calendário do seu dispositivo.</string>
@@ -943,11 +936,12 @@
<string name="legal_note">Para utilizar os serviços de Geocaching.com, tem de concordar com os termos e condições da <a href="http://www.geocaching.com/about/termsofuse.aspx">declaração Groundspeak</a>.</string>
<string name="quote">Para tornar o geocaching mais fácil, para tornar os utilizadores mais preguiçosos.</string>
<string name="powered_by">carnero</string>
- <string name="support">Suporte: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string>
- <string name="website">Site na internet: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">página do c:geo</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Manual: <a href="http://manual.cgeo.org/">o essencial do c:geo</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Suporte: <a href="">support@cgeo.org</a></string>
+ <string name="website">Site na internet: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">página do c:geo</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Manual: <a href="">o essencial do c:geo</a></string>
<string name="about_twitter">O <b>c:geo</b> deve publicar no Twitter de cada vez que uma cache for registada?</string>
<string name="about_auth_1">O processo seguinte permite ao <b>c:geo</b> aceder ao Twitter - se concordar.</string>
<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>
diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml
index d8e2414..1e71350 100644
--- a/main/res/values-sk/strings.xml
+++ b/main/res/values-sk/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Nastavenie</string>
<string name="helpers">Pomocné aplikácie</string>
<string name="about">O aplikácii</string>
- <string name="helper">Chcete sa dozvedieť viac o <b>c:geo</b>?\nPozrite si manuál.</string>
<string name="latitude">Zemepisná šírka</string>
<string name="longitude">Zemepisná dĺžka</string>
@@ -141,7 +140,6 @@
<string name="err_detail_cache_find">Prepáčte, c:geo nemôže nájsť skrýšu</string>
<string name="err_detail_cache_find_some">Prepáčte, c:geo nemôže nájsť požadovanú skrýšu.</string>
<string name="err_detail_cache_find_any">Prepáčte, c:geo nemôže nájsť žiadnu skrýšu.</string>
- <string name="err_detail_cache_find_next">Prepáčte, c:geo nemôže nájsť ďalšiu skrýšu.</string>
<string name="err_detail_cache_forgot">Prepáčte, c:geo zabudlo, akú skrýšu chcete zobraziť.</string>
<string name="err_detail_google_maps_limit_reached">c:geo sa nepodarilo prevziať statické mapy. Je možné, že bol dosiahnutý limit Google mapy.</string>
<string name="err_detail_no_spoiler">c:geo nenašla pre túto skrýšu žiaden spoilerový obrázok.</string>
@@ -464,7 +462,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">žiadna skrýša</item>
<item quantity="one">jedna skrýša</item>
<item quantity="other">%1$d skrýš</item>
</plurals>
@@ -484,7 +481,6 @@
<string name="cache_attributes">Atribúty</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>
<string name="cache_log_images_title">Obrázok z logu</string>
<string name="cache_log_image_default_title">Fotografia</string>
<string name="cache_personal_note">Osobná poznámka</string>
@@ -547,6 +543,7 @@
<string name="cache_menu_around">Skrýše v okolí</string>
<string name="cache_menu_event">Pridať do kalendára</string>
<string name="cache_menu_details">Detaily</string>
+ <string name="cache_menu_refresh">Obnoviť</string>
<string name="cache_menu_share">Zdielať skrýšu</string>
<string name="cache_menu_move_list">Presunúť do iného zoznamu</string>
<string name="cache_menu_gcc">GCC</string>
@@ -571,7 +568,7 @@
<string name="cache_rating">Hodnotenie</string>
<string name="cache_own_rating">Vlastné hodnotenie</string>
<string name="cache_rating_of">z</string>
- <string name="cache_favourite">Obľúbené</string>
+ <string name="cache_favorite">Obľúbené</string>
<string name="cache_owner">Vlastník</string>
<string name="cache_hidden">Skrytá</string>
<string name="cache_event">Dátum</string>
@@ -579,9 +576,7 @@
<string name="cache_coordinates">Súradnice</string>
<string name="cache_coordinates_original">Pôvodné súradnice</string>
<string name="cache_spoiler_images_title">Spoilerové obrázky</string>
- <string name="cache_spoiler_images_loading">Načítanie spoilerových obrázkov…</string>
<string name="cache_images_title">Obrázky</string>
- <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_clear_history">Vymazať históriu</string>
@@ -767,8 +762,6 @@
<string name="license_dismiss">Zamietnutie</string>
<!-- helpers -->
- <string name="helper_manual_title">Manuál</string>
- <string name="helper_manual_description">Obsiahly manuál pre c:geo, ktorý obsahuje popisy všetkých možností tejto aplikácie (dokonca i skrytých).</string>
<string name="helper_calendar_title">Doplnok c:geo calendar</string>
<string name="helper_calendar_missing">Doplnok c:geo calendar nie je nainštalovaný</string>
<string name="helper_calendar_description">Umožní vám exportovať skrýše udalostí do kalendára na vašom zariadení.</string>
@@ -947,11 +940,12 @@
<string name="legal_note">Pred používaním služieb serveru Geocaching.com je potrebné súhlasiť s <a href="http://www.geocaching.com/about/disclaimer.aspx">licenčnou dohodou Groundspeaku</a>.</string>
<string name="quote">Pre jednoduchšie hľadanie skrýš a používateľov lenivších.</string>
<string name="powered_by">carnero</string>
- <string name="support">Podpora: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string>
- <string name="website">Web: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Manuál: <a href="http://manual.cgeo.org/">c:geo v kocke</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Podpora: <a href="">support@cgeo.org</a></string>
+ <string name="website">Web: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo page</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Manuál: <a href="">c:geo v kocke</a></string>
<string name="about_twitter">Chcete, aby <b>c:geo</b> napísalo na váš Twitter vždy keď zapíšete nájdenie skrýše?</string>
<string name="about_auth_1">Pomocou nasledujúceho procesu môžete aplikácii <b>c:geo</b> umožniť odosielanie príspevkov na váš Twitter. </string>
<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>
diff --git a/main/res/values-sv/strings.xml b/main/res/values-sv/strings.xml
index d3be9ff..6644ce6 100644
--- a/main/res/values-sv/strings.xml
+++ b/main/res/values-sv/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Inställningar</string>
<string name="helpers">Bra program att installera</string>
<string name="about">Om c:geo</string>
- <string name="helper">Vill du lära dig mer om <b>c:geo</b>?\nLäs manualen (på engelska).</string>
<string name="latitude">Latitud</string>
<string name="longitude">Longitud</string>
@@ -34,6 +33,7 @@
<string name="ape">Projekt APE cache</string>
<string name="gchq">Groundspeak HQ</string>
<string name="gps">GPS cache utställning</string>
+ <string name="block">Groundspeak Gatufest</string>
<string name="unknown">Okänd typ</string>
<!-- cache sizes -->
@@ -126,6 +126,14 @@
<string name="log_image_camera">Ny</string>
<string name="log_image_caption">Bildtext</string>
<string name="log_image_description">Beskrivning</string>
+ <string name="log_image_scale">Skalning</string>
+ <string-array name="log_image_scales">
+ <item>Ingen skalning</item>
+ <item>512 px</item>
+ <item>640 px</item>
+ <item>800 px</item>
+ <item>1024 px</item>
+ </string-array>
<!-- translation -->
<string name="translate_to_sys_lang">Översätt till %s</string>
@@ -154,7 +162,6 @@
<string name="err_detail_cache_find">Tyvärr kan c:geo inte hitta geocache</string>
<string name="err_detail_cache_find_some">Tyvärr kan c:geo inte hitta geocachen.</string>
<string name="err_detail_cache_find_any">Tyvärr kan c:geo inte hitta någon geocache.</string>
- <string name="err_detail_cache_find_next">Tyvärr kan c:geo inte hitta nästa geocache.</string>
<string name="err_detail_cache_forgot">Tyvärr glömde c:geo vilken geocache du ville se.</string>
<string name="err_detail_google_maps_limit_reached">c:geo kunde inte hämta kartor. Eventuellt kan Google Maps gräns ha uppnåtts.</string>
<string name="err_detail_no_spoiler">c:geo hittade inga spoiler bilder för den här cachen.</string>
@@ -176,7 +183,7 @@
<string name="err_favorite_failed">Misslyckades att ändra favoritstatus.</string>
<string name="err_select_logimage_failed">Misslyckades att välja bild till loggen.</string>
- <string name="err_aquire_image_failed">Hämtning av bilden misslyckades.</string>
+ <string name="err_acquire_image_failed">Hämtning av bilden misslyckades.</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_forgot_saw">Tyvärr glömde c:geo vilken trackable du såg.</string>
@@ -362,8 +369,6 @@
<string name="init_gc_activate">Aktivera Geocaching.com i live-kartor och sökningar</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>
@@ -374,7 +379,7 @@
<string name="init_login_popup_working">Testar inloggning mot gc.com…</string>
<string name="init_login_popup_ok">Inloggning OK</string>
<string name="init_login_popup_failed">Inloggning misslyckades</string>
- <string name="init_login_popup_failed_reason">Inloggning misslyckades pga </string>
+ <string name="init_login_popup_failed_reason">Inloggning misslyckades:</string>
<string name="init_twitter_authorize">Inställningar för Twitter</string>
<string name="init_twitter_publish">Publicera status när en cache hittats</string>
<string name="init_signature">Signatur</string>
@@ -492,7 +497,6 @@
<!-- cache -->
<plurals name="cache_counts">
- <item quantity="zero">Ingen cache</item>
<item quantity="one">En cache</item>
<item quantity="other">%1$d cacher</item>
</plurals>
@@ -512,11 +516,12 @@
<string name="cache_attributes">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>
<string name="cache_log_images_title">Loggbild</string>
<string name="cache_log_image_default_title">Foto</string>
<string name="cache_personal_note">Personlig anteckning</string>
<string name="cache_personal_note_edit">Redigera</string>
+ <string name="cache_personal_note_unstored">Cachen ej sparad</string>
+ <string name="cache_personal_note_store">Cachen kommera tt sparas först för att kunna hantera personlig anteckning.</string>
<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 %s.</string>
@@ -562,10 +567,10 @@
<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_dialog_favorite_add_title">Favorit</string>
+ <string name="cache_dialog_favorite_add_message">Lägger till cachen till dina favoriter…</string>
+ <string name="cache_dialog_favorite_remove_title">Favorit</string>
+ <string name="cache_dialog_favorite_remove_message">Tar bort cachen från dina favoriter…</string>
<string name="cache_menu_navigate">Navigera</string>
<string name="cache_menu_navigation_drive">Navigering (med bil)</string>
<string name="cache_menu_navigation_walk">Navigering (till fots)</string>
@@ -584,6 +589,7 @@
<string name="cache_menu_around">Cacher i närheten</string>
<string name="cache_menu_event">Lägg till i kalender</string>
<string name="cache_menu_details">Detaljer</string>
+ <string name="cache_menu_refresh">Uppdatera</string>
<string name="cache_menu_share">Skicka länk</string>
<string name="cache_menu_move_list">Flytta till annan lista</string>
<string name="cache_menu_gcc">GCC</string>
@@ -597,6 +603,8 @@
<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_status_stored">Sparad</string>
+ <string name="cache_status_not_stored">Ej sparad</string>
<string name="cache_geocode">GC-kod</string>
<string name="cache_name">Namn</string>
<string name="cache_type">Typ</string>
@@ -607,7 +615,7 @@
<string name="cache_rating">Betyg</string>
<string name="cache_own_rating">Eget betyg</string>
<string name="cache_rating_of">av</string>
- <string name="cache_favourite">Favorit</string>
+ <string name="cache_favorite">Favorit</string>
<string name="cache_owner">Ägare</string>
<string name="cache_hidden">Gömd</string>
<string name="cache_event">Datum</string>
@@ -615,9 +623,7 @@
<string name="cache_coordinates">Koordinater</string>
<string name="cache_coordinates_original">Ursprungliga koordinater</string>
<string name="cache_spoiler_images_title">Spoiler bilder</string>
- <string name="cache_spoiler_images_loading">Laddar spoiler bilder…</string>
<string name="cache_images_title">Bilder</string>
- <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_clear_history">Rensa historik</string>
@@ -819,8 +825,6 @@
<string name="license_dismiss">Avbryt</string>
<!-- helpers -->
- <string name="helper_manual_title">Manual</string>
- <string name="helper_manual_description">En utförlig manual för c:geo som beskriver alla möjligheter och ger en hel del tips. Manualen finns enbart på engelska.</string>
<string name="helper_calendar_title">c:geo kalendertillägg</string>
<string name="helper_calendar_missing">c:geo kalendertillägg är inte installerat</string>
<string name="helper_calendar_description">Gör det möjligt att exportera event till din kalender.</string>
@@ -854,10 +858,15 @@
<!-- next things -->
<string name="legal_note">För att använda tjänster hos Geocaching.com, måste regler och villkor i <a href="http://www.geocaching.com/about/termsofuse.aspx">Groundspeaks avtal</a> godkännas.</string>
- <string name="support">Support: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string>
- <string name="website">Hemsida: <a href="http://cgeo.org/">cgeo.org</a></string>
- <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
+ <string name="quote">To make geocaching easier, to make users lazier.</string>
+ <string name="powered_by">carnero</string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Support: <a href="">support@cgeo.org</a></string>
+ <string name="website">Hemsida: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Manual: <a href="">c:geo in a Nutshell</a></string>
+ <string name="market">Android: <a href="">c:geo på Google Play</a></string>
<string name="about_twitter">Ska <b>c:geo</b> publicera ny status på Twitter varje gång en cache loggas?</string>
<string name="about_auth_1">Nedan tillåter du <b>c:geo</b> att ansluta till Twitter.</string>
<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>
@@ -869,7 +878,18 @@
<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>
+ <!-- text-to-speech for compass view -->
+ <string name="tts_service">Talande kompass</string>
+ <string name="tts_start">Starta tal</string>
+ <string name="tts_stop">Stoppa tal</string>
+ <string name="tts_kilometers">%s kilometer</string>
+ <string name="tts_meters">%s meter</string>
+ <string name="tts_miles">%s eng. mil</string>
+ <string name="tts_feet">%s fot</string>
+ <string name="tts_oclock">Klockan %s</string>
+
+ <!-- various -->
+ <string name="clipboard_copy_ok">Kopierat till urklipp</string>
<plurals name="days_ago">
<item quantity="one">igår</item>
<item quantity="other">%d dagar sedan</item>
diff --git a/main/res/values/.gitignore b/main/res/values/.gitignore
new file mode 100644
index 0000000..1f65bef
--- /dev/null
+++ b/main/res/values/.gitignore
@@ -0,0 +1 @@
+/ocde_okapi.xml
diff --git a/main/res/values/attrs.xml b/main/res/values/attrs.xml
index 558c353..092d307 100644
--- a/main/res/values/attrs.xml
+++ b/main/res/values/attrs.xml
@@ -22,10 +22,10 @@
<attr name="button" format="integer" />
<attr name="input" format="integer" />
<attr name="inventory" format="integer" />
- <attr name="favourite" format="integer" />
- <attr name="favourite_r" format="integer" />
- <attr name="favourite_o" format="integer" />
- <attr name="favourite_g" format="integer" />
+ <attr name="favorite" format="integer" />
+ <attr name="favorite_r" format="integer" />
+ <attr name="favorite_o" format="integer" />
+ <attr name="favorite_g" format="integer" />
<attr name="close" format="integer" />
<attr name="log_img_icon" format="integer" />
<attr name="actionbar_compass" format="integer" />
diff --git a/main/res/values/cache_attributes.xml b/main/res/values/cache_attributes.xml
index 815e007..c392b6f 100644
--- a/main/res/values/cache_attributes.xml
+++ b/main/res/values/cache_attributes.xml
@@ -69,10 +69,14 @@
<item>frontyard_no</item>
<item>teamwork_yes</item>
<item>teamwork_no</item>
+
+ <!-- attributes (specials -> yes, no) -->
<item>landf_yes</item>
<item>landf_no</item>
<item>partnership_yes</item>
<item>partnership_no</item>
+ <item>geotour_yes</item>
+ <item>geotour_no</item>
<!-- attributes (equipment -> required, not required) -->
<item>fee_yes</item>
diff --git a/main/res/values/dimens.xml b/main/res/values/dimens.xml
index 051f73f..1c1c47c 100644
--- a/main/res/values/dimens.xml
+++ b/main/res/values/dimens.xml
@@ -3,4 +3,8 @@
<dimen name="actionbar_height">45dip</dimen>
<dimen name="actionbar_separator_height">37dip</dimen>
<dimen name="actionbar_separator_width">2dip</dimen>
+
+ <!-- Dimensions for Samsung Multi-Window support -->
+ <dimen name="app_defaultsize_w">632.0dip</dimen>
+ <dimen name="app_defaultsize_h">598.0dip</dimen>
</resources>
diff --git a/main/res/values/ids.xml b/main/res/values/ids.xml
deleted file mode 100644
index cfb09cd..0000000
--- a/main/res/values/ids.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources>
- <item type="id" name="actionbar_title" />
- <item type="id" name="actionbar_progress" />
-</resources>
diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml
index 5f56ebb..69f9ca3 100644
--- a/main/res/values/strings.xml
+++ b/main/res/values/strings.xml
@@ -10,7 +10,6 @@
<string name="settings">Settings</string>
<string name="helpers">Useful apps</string>
<string name="about">About c:geo</string>
- <string name="helper">Do you want to learn about <b>c:geo</b>?\nCheck our easy to read manual.</string>
<string name="latitude">Latitude</string>
<string name="longitude">Longitude</string>
@@ -34,6 +33,7 @@
<string name="ape">Project APE Cache</string>
<string name="gchq">Groundspeak HQ</string>
<string name="gps">GPS Adventures Exhibit</string>
+ <string name="block">Groundspeak Block Party</string>
<string name="unknown">Unknown Type</string>
<!-- cache sizes -->
@@ -126,6 +126,14 @@
<string name="log_image_camera">New</string>
<string name="log_image_caption">Caption</string>
<string name="log_image_description">Description</string>
+ <string name="log_image_scale">Scaling</string>
+ <string-array name="log_image_scales">
+ <item>No scaling</item>
+ <item>512 px</item>
+ <item>640 px</item>
+ <item>800 px</item>
+ <item>1024 px</item>
+ </string-array>
<!-- translation -->
<string name="translate_to_sys_lang">Translate to %s</string>
@@ -154,7 +162,6 @@
<string name="err_detail_cache_find">c:geo can\'t find geocache</string>
<string name="err_detail_cache_find_some">c:geo can\'t find that geocache.</string>
<string name="err_detail_cache_find_any">c:geo can\'t find any geocache.</string>
- <string name="err_detail_cache_find_next">c:geo can\'t find next geocaches.</string>
<string name="err_detail_cache_forgot">c:geo forgot which geocache you want.</string>
<string name="err_detail_google_maps_limit_reached">c:geo failed to download static maps. Maybe google maps limit is reached.</string>
<string name="err_detail_no_spoiler">c:geo found no spoiler images for this cache.</string>
@@ -175,7 +182,7 @@
<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_select_logimage_failed">Selecting an image for the log failed.</string>
- <string name="err_aquire_image_failed">Acquiring an image failed.</string>
+ <string name="err_acquire_image_failed">Acquiring an image 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>
@@ -362,8 +369,8 @@
<string name="init_gc_activate">Activate Geocaching.com on live-map and in searches</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_oc_de_description">Authorize c:geo with opencaching.de to search for caches and access/filter your found caches.</string>
+ <string name="init_register_oc_de">Authorize c:geo</string>
<string name="init_gcvote">GCvote.com</string>
<string name="init_twitter">Twitter</string>
<string name="init_username">Username</string>
@@ -477,8 +484,7 @@
<string name="sendToCgeo_download_fail">c:geo failed to download caches. No internet connection or send2c:geo is down.</string>
<string name="sendToCgeo_no_registration">c:geo failed to download caches. Registration for send2c:geo expired. Please register in settings.</string>
-
- <!-- auth -->
+ <!-- auth twitter -->
<string name="auth_twitter">Twitter</string>
<string name="auth_authorize">Authorize c:geo</string>
<string name="auth_start">Start authorization</string>
@@ -489,12 +495,28 @@
<string name="auth_dialog_pin_title">PIN code</string>
<string name="auth_dialog_pin_message">Please type in PIN code provided by the Twitter website. It is mandatory to complete the authorization.</string>
<string name="auth_dialog_completed">c:geo is now authorized to post on Twitter.</string>
+ <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>
+
+ <!-- auth opencaching -->
+ <string name="auth_ocde">opencaching.de</string>
+ <string name="auth_authorize_oc">Authorize c:geo</string>
+ <string name="auth_start_oc">Start authorization</string>
+ <string name="auth_again_oc">Start again</string>
+ <string name="auth_pin_hint_oc">PIN assigned by %s</string>
+ <string name="auth_finish_oc">Finish</string>
+ <string name="auth_dialog_wait_oc">Waiting for %s…</string>
+ <string name="auth_dialog_pin_title_oc">PIN code</string>
+ <string name="auth_dialog_pin_message_oc">Please type in PIN code provided by the %s website. It is mandatory to complete the authorization.</string>
+ <string name="auth_dialog_completed_oc">c:geo is now authorized to interact with %s.</string>
+ <string name="about_auth_1_oc">The following process allows <b>c:geo</b> to access %s - if agreed.</string>
+ <string name="about_auth_2_oc">A click on the \"authorize c:geo\" button will start the process. This process will open up a web browser with a %s page. Login on this page and allow <b>c:geo</b> to access your account. If this is accepted, %s will show up a numeric PIN code. This PIN must be pasted into <b>c:geo</b> and confirmed. That\'s all.</string>
<!-- cache -->
<plurals name="cache_counts">
<item quantity="zero">No cache</item>
<item quantity="one">One cache</item>
- <item quantity="other">%1$d Caches</item>
+ <item quantity="other">%1$d caches</item>
</plurals>
<string name="cache_offline">Offline</string>
<string name="cache_offline_refresh">Refresh</string>
@@ -512,11 +534,12 @@
<string name="cache_attributes">Attributes</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>
<string name="cache_log_images_title">Log images</string>
<string name="cache_log_image_default_title">Photo</string>
<string name="cache_personal_note">Personal note</string>
<string name="cache_personal_note_edit">Edit</string>
+ <string name="cache_personal_note_unstored">Cache not stored</string>
+ <string name="cache_personal_note_store">The cache will be stored first to enable personal notes.</string>
<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 %s to be seen correctly.</string>
@@ -562,10 +585,10 @@
<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_dialog_favorite_add_title">Favorite</string>
+ <string name="cache_dialog_favorite_add_message">Adding cache to your favorites…</string>
+ <string name="cache_dialog_favorite_remove_title">Favorite</string>
+ <string name="cache_dialog_favorite_remove_message">Removing cache from your favorites…</string>
<string name="cache_menu_navigate">Navigate</string>
<string name="cache_menu_navigation_drive">Navigation (Driving)</string>
<string name="cache_menu_navigation_walk">Navigation (Walking)</string>
@@ -584,6 +607,7 @@
<string name="cache_menu_around">Caches around</string>
<string name="cache_menu_event">Add to calendar</string>
<string name="cache_menu_details">Details</string>
+ <string name="cache_menu_refresh">Refresh</string>
<string name="cache_menu_share">Share cache</string>
<string name="cache_menu_move_list">Move to other list</string>
<string name="cache_menu_gcc">GCC</string>
@@ -597,6 +621,8 @@
<string name="cache_status_disabled">Disabled</string>
<string name="cache_status_premium">Premium Members only</string>
<string name="cache_status_not_premium">All Members Access</string>
+ <string name="cache_status_stored">Stored</string>
+ <string name="cache_status_not_stored">Not stored</string>
<string name="cache_geocode">Geo code</string>
<string name="cache_name">Name</string>
<string name="cache_type">Type</string>
@@ -607,7 +633,7 @@
<string name="cache_rating">Rating</string>
<string name="cache_own_rating">Own Rating</string>
<string name="cache_rating_of">of</string>
- <string name="cache_favourite">Favorite</string>
+ <string name="cache_favorite">Favorite</string>
<string name="cache_owner">Owner</string>
<string name="cache_hidden">Hidden</string>
<string name="cache_event">Date</string>
@@ -615,9 +641,7 @@
<string name="cache_coordinates">Coordinates</string>
<string name="cache_coordinates_original">Original Coordinates</string>
<string name="cache_spoiler_images_title">Spoiler images</string>
- <string name="cache_spoiler_images_loading">Loading spoiler images…</string>
<string name="cache_images_title">Images</string>
- <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_clear_history">Clear history</string>
@@ -820,8 +844,6 @@
<string name="license_dismiss">Dismiss</string>
<!-- helpers -->
- <string name="helper_manual_title">Manual</string>
- <string name="helper_manual_description">Comprehensive manual for c:geo that contains description of all possibilities of this application (even hidden ones).</string>
<string name="helper_calendar_title">c:geo calendar add-on</string>
<string name="helper_calendar_missing">c:geo calendar add-on not installed.</string>
<string name="helper_calendar_description">Enables you to export event caches into the calendar on your device.</string>
@@ -833,7 +855,9 @@
<string name="helper_bluetoothgps_description">Allows you to use an external GPS receiver to get more precise location and can spare battery of your device.</string>
<string name="helper_barcode_title">Barcode Scanner</string>
<string name="helper_barcode_description">There are Greasemonkey scripts and websites which allow to display a geocode as barcode. With this app c:geo can read that geocode directly from the screen of your computer.</string>
-
+ <string name="helper_pocketquery_title">Pocket Query Creator</string>
+ <string name="helper_pocketquery_description">Allows easy creation and download of Pocket Queries centred on your current position or a point selected from a map. Requires a premium Geocaching.com account.</string>
+
<!-- add-ons -->
<string name="addon_missing_title">Missing Add-On</string>
<string name="addon_download_prompt">Get it now from Google Play.</string>
@@ -998,6 +1022,8 @@
<string name="attribute_swamp_no">No swamp or marsh</string>
<string name="attribute_hills_yes">Hilly area</string>
<string name="attribute_hills_no">No hilly area</string>
+ <string name="attribute_easy_climbing_yes">Lightweight climbing</string>
+ <string name="attribute_easy_climbing_no">No lightweight climbing</string>
<string name="attribute_poi_yes">Point of interest</string>
<string name="attribute_poi_no">No point of interest</string>
<string name="attribute_moving_target_yes">Moving target</string>
@@ -1042,19 +1068,21 @@
<string name="attribute_ask_owner_no">Don\'t ask owner for start conditions</string>
<string name="attribute_unknown_yes">Unknown attribute present</string>
<string name="attribute_unknown_no">No unknown attribute present</string>
-
+ <string name="attribute_geotour_yes">Part of GeoTour</string>
+ <string name="attribute_geotour_no">Not part of GeoTour</string>
+
<!-- next things -->
<string name="legal_note">To use the services of Geocaching.com, terms and conditions of the <a href="http://www.geocaching.com/about/termsofuse.aspx">Groundspeak disclaimer</a> have to be agreed.</string>
<string name="quote">To make geocaching easier, to make users lazier.</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 page</a></string>
- <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string>
- <string name="nutshellmanual">Manual: <a href="http://manual.cgeo.org/">c:geo in a Nutshell</a></string>
+ <!-- Note: Links here are just for appearance. See AboutActivity to make changes -->
+ <string name="support">Support: <a href="">support@cgeo.org</a></string>
+ <string name="website">Website: <a href="">cgeo.org</a></string>
+ <string name="facebook">Facebook: <a href="">c:geo page</a></string>
+ <string name="twitter">Twitter: <a href="">@android_GC</a></string>
+ <string name="nutshellmanual">Manual: <a href="">c:geo in a Nutshell</a></string>
+ <string name="market">Android: <a href="">c:geo on Google Play</a></string>
<string name="about_twitter">Should <b>c:geo</b> publish a new status on Twitter every time you log a cache?</string>
- <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 (used via string based resource loading) -->
<string name="status_new_release" tools:ignore="UnusedResources">New release available.\nClick to install.</string>
@@ -1063,6 +1091,17 @@
<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>
+ <!-- text-to-speech for compass view -->
+ <string name="tts_service">Talking compass</string>
+ <string name="tts_start">Start talking</string>
+ <string name="tts_stop">Stop talking</string>
+ <string name="tts_kilometers">%s kilometers</string>
+ <string name="tts_meters">%s meters</string>
+ <string name="tts_miles">%s miles</string>
+ <string name="tts_feet">%s feet</string>
+ <string name="tts_oclock">%s o\'clock</string>
+
+ <!-- various -->
<string name="clipboard_copy_ok">Copied to clipboard</string>
<plurals name="days_ago">
<item quantity="one">yesterday</item>
diff --git a/main/res/values/strings_not_translatable.xml b/main/res/values/strings_not_translatable.xml
index 16dc3d3..93fd87e 100644
--- a/main/res/values/strings_not_translatable.xml
+++ b/main/res/values/strings_not_translatable.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="waypoint_coordinate_formats" translatable="false">
<item>@string/waypoint_coordinate_formats_plain</item>
@@ -28,6 +28,15 @@
<string name="init_select_gpx_exportdir" translatable="false">…</string>
<string name="init_select_gpx_importdir" translatable="false">…</string>
+ <!-- upload image scaling -->
+ <integer-array name="log_image_scale_values">
+ <item>-1</item>
+ <item>512</item>
+ <item>640</item>
+ <item>800</item>
+ <item>1024</item>
+ </integer-array>
+
<!-- contributors -->
<string name="contributors" translatable="false">\n
· <a href="http://carnero.cc/">carnero</a> as the father of c:geo\n
@@ -102,7 +111,7 @@
\n
<b>2013.05.18</b>\n
<b>Bugfixing:</b>\n
- · Correction for compatability issue with tablet devices\n
+ · Correction for compatibility issue with tablet devices\n
\n
\n
<b>2013.05.16</b>\n
diff --git a/main/res/values/styles.xml b/main/res/values/styles.xml
index caa884a..8bf0e98 100644
--- a/main/res/values/styles.xml
+++ b/main/res/values/styles.xml
@@ -9,7 +9,7 @@
<item name="android:singleLine">true</item>
<item name="android:scrollHorizontally">true</item>
<item name="android:ellipsize">marquee</item>
- <item name="android:textSize">22dip</item>
+ <item name="android:textSize">22sp</item>
<item name="android:textColor">?text_color</item>
<item name="android:background">?button</item>
</style>
@@ -18,7 +18,7 @@
<item name="android:padding">6dip</item>
<item name="android:singleLine">true</item>
<item name="android:autoText">true</item>
- <item name="android:textSize">22dip</item>
+ <item name="android:textSize">22sp</item>
<item name="android:textColor">?text_color</item>
<item name="android:textColorHint">?text_color_hint</item>
<item name="android:background">?input</item>
@@ -81,7 +81,6 @@
</style>
<style name="action_bar_progress" parent="@android:style/Widget.ProgressBar.Small">
- <item name="android:id">@id/actionbar_progress</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginLeft">15dip</item>
@@ -90,7 +89,6 @@
</style>
<style name="action_bar_title">
- <item name="android:id">@id/actionbar_title</item>
<item name="android:layout_width">0dip</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
@@ -99,7 +97,7 @@
<item name="android:scrollHorizontally">true</item>
<item name="android:ellipsize">marquee</item>
<item name="android:lines">1</item>
- <item name="android:textSize">20dip</item>
+ <item name="android:textSize">20sp</item>
<item name="android:textColor">@color/just_white</item>
<item name="android:text">c:geo</item>
</style>
@@ -123,7 +121,7 @@
<item name="android:layout_marginTop">3dip</item>
<item name="android:layout_marginBottom">3dip</item>
<item name="android:padding">3dip</item>
- <item name="android:textSize">14dip</item>
+ <item name="android:textSize">14sp</item>
</style>
<!-- edittext -->
@@ -168,7 +166,7 @@
<item name="android:singleLine">true</item>
<item name="android:lines">1</item>
<item name="android:ellipsize">marquee</item>
- <item name="android:textSize">13dip</item>
+ <item name="android:textSize">13sp</item>
<item name="android:textColor">@color/text_icon</item>
<item name="android:background">@drawable/icon_bcg</item>
</style>
@@ -190,7 +188,7 @@
<item name="android:singleLine">true</item>
<item name="android:lines">1</item>
<item name="android:ellipsize">marquee</item>
- <item name="android:textSize">11dip</item>
+ <item name="android:textSize">11sp</item>
<item name="android:textColor">@color/just_white</item>
<item name="android:background">@drawable/count_bcg</item>
<item name="android:text"></item>
@@ -207,7 +205,7 @@
<item name="android:singleLine">true</item>
<item name="android:scrollHorizontally">true</item>
<item name="android:ellipsize">marquee</item>
- <item name="android:textSize">14dip</item>
+ <item name="android:textSize">14sp</item>
<item name="android:textColor">@color/text_icon</item>
<item name="android:background">@drawable/icon_bcg</item>
</style>
@@ -223,7 +221,7 @@
<item name="android:singleLine">true</item>
<item name="android:scrollHorizontally">true</item>
<item name="android:ellipsize">marquee</item>
- <item name="android:textSize">12dip</item>
+ <item name="android:textSize">12sp</item>
<item name="android:textColor">@color/text_dark</item>
</style>
@@ -265,7 +263,7 @@
<item name="android:singleLine">true</item>
<item name="android:scrollHorizontally">true</item>
<item name="android:ellipsize">marquee</item>
- <item name="android:textSize">22dip</item>
+ <item name="android:textSize">22sp</item>
<item name="android:textColor">?text_color_headline</item>
<item name="android:background">?background_color</item>
</style>
diff --git a/main/res/values/themes.xml b/main/res/values/themes.xml
index fdc2eeb..655d9e1 100644
--- a/main/res/values/themes.xml
+++ b/main/res/values/themes.xml
@@ -36,10 +36,10 @@
<item name="button">@drawable/action_button_dark</item>
<item name="input">@drawable/input_bcg_dark</item>
<item name="inventory">@drawable/inventory_background_dark</item>
- <item name="favourite">@drawable/favourite_background_dark</item>
- <item name="favourite_r">@drawable/favourite_background_red_dark</item>
- <item name="favourite_o">@drawable/favourite_background_orange_dark</item>
- <item name="favourite_g">@drawable/favourite_background_green_dark</item>
+ <item name="favorite">@drawable/favorite_background_dark</item>
+ <item name="favorite_r">@drawable/favorite_background_red_dark</item>
+ <item name="favorite_o">@drawable/favorite_background_orange_dark</item>
+ <item name="favorite_g">@drawable/favorite_background_green_dark</item>
<item name="close">@drawable/map_close_dark</item>
<item name="log_img_icon">@drawable/log_img_dark</item>
<item name="actionbar_compass">@drawable/actionbar_compass_dark</item>
@@ -67,10 +67,10 @@
<item name="button">@drawable/action_button_light</item>
<item name="input">@drawable/input_bcg_light</item>
<item name="inventory">@drawable/inventory_background_light</item>
- <item name="favourite">@drawable/favourite_background_light</item>
- <item name="favourite_r">@drawable/favourite_background_red_light</item>
- <item name="favourite_o">@drawable/favourite_background_orange_light</item>
- <item name="favourite_g">@drawable/favourite_background_green_light</item>
+ <item name="favorite">@drawable/favorite_background_light</item>
+ <item name="favorite_r">@drawable/favorite_background_red_light</item>
+ <item name="favorite_o">@drawable/favorite_background_orange_light</item>
+ <item name="favorite_g">@drawable/favorite_background_green_light</item>
<item name="close">@drawable/map_close_light</item>
<item name="log_img_icon">@drawable/log_img_light</item>
<item name="actionbar_compass">@drawable/actionbar_compass_light</item>
@@ -109,10 +109,10 @@
<item name="button">@drawable/action_button_dark</item>
<item name="input">@drawable/input_bcg_dark</item>
<item name="inventory">@drawable/inventory_background_dark</item>
- <item name="favourite">@drawable/favourite_background_dark</item>
- <item name="favourite_r">@drawable/favourite_background_red_dark</item>
- <item name="favourite_o">@drawable/favourite_background_orange_dark</item>
- <item name="favourite_g">@drawable/favourite_background_green_dark</item>
+ <item name="favorite">@drawable/favorite_background_dark</item>
+ <item name="favorite_r">@drawable/favorite_background_red_dark</item>
+ <item name="favorite_o">@drawable/favorite_background_orange_dark</item>
+ <item name="favorite_g">@drawable/favorite_background_green_dark</item>
<item name="close">@drawable/map_close_dark</item>
<item name="log_img_icon">@drawable/log_img_dark</item>
<item name="actionbar_compass">@drawable/actionbar_compass_dark</item>
@@ -141,10 +141,10 @@
<item name="button">@drawable/action_button_light</item>
<item name="input">@drawable/input_bcg_light</item>
<item name="inventory">@drawable/inventory_background_light</item>
- <item name="favourite">@drawable/favourite_background_light</item>
- <item name="favourite_r">@drawable/favourite_background_red_light</item>
- <item name="favourite_o">@drawable/favourite_background_orange_light</item>
- <item name="favourite_g">@drawable/favourite_background_green_light</item>
+ <item name="favorite">@drawable/favorite_background_light</item>
+ <item name="favorite_r">@drawable/favorite_background_red_light</item>
+ <item name="favorite_o">@drawable/favorite_background_orange_light</item>
+ <item name="favorite_g">@drawable/favorite_background_green_light</item>
<item name="close">@drawable/map_close_light</item>
<item name="log_img_icon">@drawable/log_img_light</item>
<item name="actionbar_compass">@drawable/actionbar_compass_light</item>
diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java
index c154ffb..3164602 100644
--- a/main/src/cgeo/geocaching/AboutActivity.java
+++ b/main/src/cgeo/geocaching/AboutActivity.java
@@ -1,28 +1,29 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+
import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
import cgeo.geocaching.utils.Version;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.TextView;
public class AboutActivity extends AbstractActivity {
+ @InjectView(R.id.about_version_string) protected TextView version;
+ @InjectView(R.id.contributors) protected TextView contributors;
+ @InjectView(R.id.changelog) protected TextView changeLog;
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.about_activity);
- setTitle(res.getString(R.string.about));
+ super.onCreate(savedInstanceState, R.layout.about_activity);
- ((TextView) findViewById(R.id.about_version_string)).setText(Version.getVersionName(this));
- ((TextView) findViewById(R.id.contributors)).setMovementMethod(LinkMovementMethod.getInstance());
- ((TextView) findViewById(R.id.changelog)).setMovementMethod(LinkMovementMethod.getInstance());
+ version.setText(Version.getVersionName(this));
+ contributors.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
+ changeLog.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
}
/**
@@ -70,6 +71,16 @@ public class AboutActivity extends AbstractActivity {
* unused here but needed since this method is referenced from XML layout
*/
public void nutshellmanual(View view) {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.cgeo.org/")));
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://manual.cgeo.org/")));
+ }
+
+ /**
+ * @param view
+ * unused here but needed since this method is referenced from XML layout
+ */
+ public void market(View view) {
+ Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName()));
+ marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ startActivity(marketIntent);
}
}
diff --git a/main/src/cgeo/geocaching/AbstractLoggingActivity.java b/main/src/cgeo/geocaching/AbstractLoggingActivity.java
index 37c3643..78da757 100644
--- a/main/src/cgeo/geocaching/AbstractLoggingActivity.java
+++ b/main/src/cgeo/geocaching/AbstractLoggingActivity.java
@@ -17,27 +17,17 @@ import android.view.SubMenu;
import android.widget.EditText;
public abstract class AbstractLoggingActivity extends AbstractActivity {
- private static final int MENU_SIGNATURE = 1;
- private static final int MENU_SMILEY = 2;
-
- protected AbstractLoggingActivity(String helpTopic) {
- super(helpTopic);
- }
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
- // signature menu
- menu.add(0, MENU_SIGNATURE, 0, res.getString(R.string.init_signature)).setIcon(R.drawable.ic_menu_edit);
+ getMenuInflater().inflate(R.menu.abstract_logging_activity, menu);
- // templates menu
- final SubMenu menuLog = menu.addSubMenu(0, 0, 0, res.getString(R.string.log_add)).setIcon(R.drawable.ic_menu_add);
+ final SubMenu menuLog = menu.findItem(R.id.menu_templates).getSubMenu();
for (LogTemplate template : LogTemplateProvider.getTemplates()) {
menuLog.add(0, template.getItemId(), 0, template.getResourceId());
}
- menuLog.add(0, MENU_SIGNATURE, 0, res.getString(R.string.init_signature));
- // smilies
- final SubMenu menuSmilies = menu.addSubMenu(0, MENU_SMILEY, 0, res.getString(R.string.log_smilies)).setIcon(R.drawable.ic_menu_emoticons);
+ final SubMenu menuSmilies = menu.findItem(R.id.menu_smilies).getSubMenu();
for (Smiley smiley : GCSmiliesProvider.getSmilies()) {
menuSmilies.add(0, smiley.getItemId(), 0, smiley.text);
}
@@ -48,7 +38,7 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
final boolean signatureAvailable = StringUtils.isNotBlank(Settings.getSignature());
- menu.findItem(MENU_SIGNATURE).setVisible(signatureAvailable);
+ menu.findItem(R.id.menu_signature).setVisible(signatureAvailable);
boolean smileyVisible = false;
final Geocache cache = getLogContext().getCache();
@@ -60,7 +50,7 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
smileyVisible = true;
}
- menu.findItem(MENU_SMILEY).setVisible(smileyVisible);
+ menu.findItem(R.id.menu_smilies).setVisible(smileyVisible);
return true;
}
@@ -69,7 +59,7 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
public boolean onOptionsItemSelected(MenuItem item) {
final int id = item.getItemId();
- if (id == MENU_SIGNATURE) {
+ if (id == R.id.menu_signature) {
insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), getLogContext()), true);
return true;
}
diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java
index f903d00..73dc86d 100644
--- a/main/src/cgeo/geocaching/AbstractPopupActivity.java
+++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java
@@ -2,7 +2,6 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.ActivityMixin;
-import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.gcvote.GCVote;
@@ -34,11 +33,6 @@ import android.widget.TextView;
public abstract class AbstractPopupActivity extends AbstractActivity {
- private static final int MENU_CACHES_AROUND = 5;
- private static final int MENU_NAVIGATION = 3;
- private static final int MENU_DEFAULT_NAVIGATION = 2;
- private static final int MENU_SHOW_IN_BROWSER = 7;
-
protected Geocache cache = null;
protected String geocode = null;
protected CacheDetailsCreator details;
@@ -67,14 +61,24 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
cacheDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords())));
cacheDistance.bringToFront();
}
+ onUpdateGeoData(geo);
} catch (Exception e) {
Log.w("Failed to UpdateLocation location.");
}
}
};
- protected AbstractPopupActivity(String helpTopic, int layout) {
- super(helpTopic);
+ /**
+ * Callback to run when new location information is available.
+ * This may be overridden by deriving classes. The default implementation does nothing.
+ *
+ * @param geo
+ * the new data
+ */
+ public void onUpdateGeoData(final IGeoData geo) {
+ }
+
+ protected AbstractPopupActivity(int layout) {
this.layout = layout;
}
@@ -102,12 +106,6 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
}).start();
}
- @Override
- public void goManual(View view) {
- super.goManual(view);
- finish();
- }
-
protected void init() {
cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
@@ -134,7 +132,6 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
this.setTheme(ActivityMixin.getDialogTheme());
// set layout
setContentView(layout);
- setTitle(res.getString(R.string.detail));
// get parameters
final Bundle extras = getIntent().getExtras();
@@ -162,12 +159,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_DEFAULT_NAVIGATION, 0, NavigationAppFactory.getDefaultNavigationApplication().getName()).setIcon(R.drawable.ic_menu_compass); // default navigation tool
- menu.add(0, MENU_NAVIGATION, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
- LoggingUI.addMenuItems(menu, cache);
- menu.add(0, MENU_CACHES_AROUND, 0, res.getString(R.string.cache_menu_around)).setIcon(R.drawable.ic_menu_rotate); // caches around
- menu.add(0, MENU_SHOW_IN_BROWSER, 0, res.getString(R.string.cache_menu_browser)).setIcon(R.drawable.ic_menu_info_details); // browser
-
+ getMenuInflater().inflate(R.menu.abstract_popup_activity, menu);
return true;
}
@@ -176,16 +168,16 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
final int menuItem = item.getItemId();
switch (menuItem) {
- case MENU_DEFAULT_NAVIGATION:
+ case R.id.menu_default_navigation:
navigateTo();
return true;
- case MENU_NAVIGATION:
+ case R.id.menu_navigate:
showNavigationMenu();
return true;
- case MENU_CACHES_AROUND:
+ case R.id.menu_caches_around:
cachesAround();
return true;
- case MENU_SHOW_IN_BROWSER:
+ case R.id.menu_show_in_browser:
showInBrowser();
return true;
default:
@@ -209,11 +201,11 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
try {
final boolean visible = getCoordinates() != null;
- menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(visible);
- menu.findItem(MENU_NAVIGATION).setVisible(visible);
- menu.findItem(MENU_CACHES_AROUND).setVisible(visible);
+ menu.findItem(R.id.menu_default_navigation).setVisible(visible);
+ menu.findItem(R.id.menu_navigate).setVisible(visible);
+ menu.findItem(R.id.menu_caches_around).setVisible(visible);
- LoggingUI.onPrepareOptionsMenu(menu);
+ LoggingUI.onPrepareOptionsMenu(menu, cache);
} catch (Exception e) {
// nothing
}
@@ -269,8 +261,8 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
aquireGCVote();
}
- // favourite count
- details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×");
+ // favorite count
+ details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×");
// more details
final Button buttonMore = (Button) findViewById(R.id.more_details);
diff --git a/main/src/cgeo/geocaching/AddressListActivity.java b/main/src/cgeo/geocaching/AddressListActivity.java
index b1de065..150bbc5 100644
--- a/main/src/cgeo/geocaching/AddressListActivity.java
+++ b/main/src/cgeo/geocaching/AddressListActivity.java
@@ -20,11 +20,7 @@ public class AddressListActivity extends AbstractListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.addresses);
- setTitle(res.getString(R.string.search_address_result));
+ super.onCreate(savedInstanceState, R.layout.addresses);
// get parameters
final String keyword = getIntent().getStringExtra(Intents.EXTRA_KEYWORD);
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index 1662bb6..9b57f0d 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -1,5 +1,8 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.calendar.ICalendar;
import cgeo.geocaching.activity.AbstractViewPagerActivity;
import cgeo.geocaching.activity.Progress;
@@ -21,13 +24,14 @@ import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
import cgeo.geocaching.ui.CacheDetailsCreator;
+import cgeo.geocaching.ui.CoordinatesFormatSwitcher;
import cgeo.geocaching.ui.DecryptTextClickListener;
+import cgeo.geocaching.ui.EditNoteDialog;
+import cgeo.geocaching.ui.EditNoteDialog.EditNoteDialogListener;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.ImagesList;
-import cgeo.geocaching.ui.ImagesList.ImageType;
import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.ui.WeakReferenceHandler;
-import cgeo.geocaching.ui.dialog.EditorDialog;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.ClipboardUtils;
@@ -65,12 +69,12 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
import android.text.Spanned;
import android.text.format.DateUtils;
-import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
@@ -112,7 +116,8 @@ import java.util.regex.Pattern;
*
* e.g. details, description, logs, waypoints, inventory...
*/
-public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page> {
+public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page>
+ implements EditNoteDialogListener {
private static final int MENU_FIELD_COPY = 1;
private static final int MENU_FIELD_TRANSLATE = 2;
@@ -132,13 +137,21 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
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}" + "\"");
+ private static final Pattern[] DARK_COLOR_PATTERNS = {
+ Pattern.compile("((?<!bg)color)=\"#" + "(0[0-9]){3}" + "\"", Pattern.CASE_INSENSITIVE),
+ Pattern.compile("((?<!bg)color)=\"" + "black" + "\"", Pattern.CASE_INSENSITIVE),
+ Pattern.compile("((?<!bg)color)=\"#" + "000080" + "\"", Pattern.CASE_INSENSITIVE) };
+ private static final Pattern[] LIGHT_COLOR_PATTERNS = {
+ Pattern.compile("((?<!bg)color)=\"#" + "([F][6-9A-F]){3}" + "\"", Pattern.CASE_INSENSITIVE),
+ Pattern.compile("((?<!bg)color)=\"" + "white" + "\"", Pattern.CASE_INSENSITIVE) };
public static final String STATE_PAGE_INDEX = "cgeo.geocaching.pageIndex";
private Geocache cache;
private final Progress progress = new Progress();
private SearchResult search;
+ private EditNoteDialogListener editNoteDialogListener;
+
private final GeoDirHandler locationUpdater = new GeoDirHandler() {
@Override
public void updateGeoData(final IGeoData geo) {
@@ -187,18 +200,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
};
protected ImagesList imagesList;
- public CacheDetailActivity() {
- // identifier for manual
- super("c:geolocation-cache-details");
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ super.onCreate(savedInstanceState, R.layout.cacheview);
- // initialize the main view and set a default title
- setTheme();
- setContentView(R.layout.cacheview);
+ // set title in code, as the activity needs a hard coded title due to the intent filters
setTitle(res.getString(R.string.cache));
String geocode = null;
@@ -259,6 +265,23 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
finish();
return;
}
+ } else if (uriHost.contains("opencaching.de")) {
+ if (uriPath != null && uriPath.startsWith("/oc")) {
+ geocode = uriPath.substring(1).toUpperCase(Locale.US);
+ } else {
+ geocode = uri.getQueryParameter("wp");
+ if (StringUtils.isNotBlank(geocode)) {
+ geocode = geocode.toUpperCase(Locale.US);
+ } else {
+ showToast(res.getString(R.string.err_detail_open));
+ finish();
+ return;
+ }
+ }
+ } else {
+ showToast(res.getString(R.string.err_detail_open));
+ finish();
+ return;
}
}
@@ -541,7 +564,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
NavigationAppFactory.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);
+ LoggingUI.addMenuItems(this, menu, cache);
menu.add(0, MENU_CACHES_AROUND, 0, res.getString(R.string.cache_menu_around)).setIcon(R.drawable.ic_menu_rotate); // caches around
menu.add(0, MENU_BROWSER, 0, res.getString(R.string.cache_menu_browser)).setIcon(R.drawable.ic_menu_globe); // browser
menu.add(0, MENU_SHARE, 0, res.getString(R.string.cache_menu_share)).setIcon(R.drawable.ic_menu_share); // share cache
@@ -557,6 +580,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround());
menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser());
}
+ LoggingUI.onPrepareOptionsMenu(menu, cache);
return super.onPrepareOptionsMenu(menu);
}
@@ -797,7 +821,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
/**
* Wrapper for the referenced method in the xml-layout.
*/
- public void startDefaultNavigation(@SuppressWarnings("unused") View view) {
+ public void goDefaultNavigation(@SuppressWarnings("unused") View view) {
startDefaultNavigation();
}
@@ -901,7 +925,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return;
}
imagesList = new ImagesList(this, cache.getGeocode());
- imagesList.loadImages(imageView, cache.getImages(), ImageType.AllImages, false);
+ imagesList.loadImages(imageView, cache.getImages(), false);
}
public static void startActivity(final Context context, final String geocode) {
@@ -1165,7 +1189,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// favorite count
if (cache.getFavoritePoints() > 0) {
- details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×");
+ details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×");
}
// own rating
@@ -1204,23 +1228,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// cache coordinates
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;
-
- final TextView valueView = (TextView) view.findViewById(R.id.value);
- valueView.setText(cache.getCoords().format(availableFormats[position]));
- }
- });
+ valueView.setOnClickListener(new CoordinatesFormatSwitcher(cache.getCoords()));
registerForContextMenu(valueView);
}
@@ -1260,7 +1268,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
TextView licenseView = ((TextView) view.findViewById(R.id.license));
licenseView.setText(Html.fromHtml(license), BufferType.SPANNABLE);
licenseView.setClickable(true);
- licenseView.setMovementMethod(LinkMovementMethod.getInstance());
+ licenseView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
} else {
view.findViewById(R.id.license_box).setVisibility(View.GONE);
}
@@ -1356,6 +1364,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return;
}
+ if (!Network.isNetworkConnected(getApplicationContext())) {
+ showToast(getString(R.string.err_server));
+ return;
+ }
+
final RefreshCacheHandler refreshCacheHandler = new RefreshCacheHandler();
progress.show(CacheDetailActivity.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
@@ -1482,7 +1495,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
@Override
public void run() {
- handler.sendEmptyMessage(GCConnector.addToWatchlist(cache) ? 1 : -1);
+ handler.sendEmptyMessage(ConnectorFactory.getConnector(cache).addToWatchlist(cache) ? 1 : -1);
}
}
@@ -1496,11 +1509,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
@Override
public void run() {
- handler.sendEmptyMessage(GCConnector.removeFromWatchlist(cache) ? 1 : -1);
+ handler.sendEmptyMessage(ConnectorFactory.getConnector(cache).removeFromWatchlist(cache) ? 1 : -1);
}
}
- /** Thread to add this cache to the favourite list of the user */
+ /** Thread to add this cache to the favorite list of the user */
private class FavoriteAddThread extends Thread {
private final Handler handler;
@@ -1514,7 +1527,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- /** Thread to remove this cache to the favourite list of the user */
+ /** Thread to remove this cache to the favorite list of the user */
private class FavoriteRemoveThread extends Thread {
private final Handler handler;
@@ -1541,25 +1554,25 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
/**
- * Listener for "add to favourites" button
+ * Listener for "add to favorites" 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,
+ doExecute(R.string.cache_dialog_favorite_add_title,
+ R.string.cache_dialog_favorite_add_message,
new FavoriteAddThread(new FavoriteUpdateHandler()));
}
}
/**
- * Listener for "remove from favourites" button
+ * Listener for "remove from favorites" 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,
+ doExecute(R.string.cache_dialog_favorite_remove_title,
+ R.string.cache_dialog_favorite_remove_message,
new FavoriteRemoveThread(new FavoriteUpdateHandler()));
}
}
@@ -1752,7 +1765,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
- private class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
+ protected class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
+
+ @InjectView(R.id.personalnote) protected TextView personalNoteView;
@Override
public ScrollView getDispatchedView() {
@@ -1762,11 +1777,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
view = (ScrollView) getLayoutInflater().inflate(R.layout.cacheview_description, null);
+ Views.inject(this, view);
// cache short description
if (StringUtils.isNotBlank(cache.getShortDescription())) {
- new LoadDescriptionTask().execute(cache.getShortDescription(), view.findViewById(R.id.shortdesc), null);
- registerForContextMenu(view.findViewById(R.id.shortdesc));
+ new LoadDescriptionTask(cache.getShortDescription(), view.findViewById(R.id.shortdesc), null, null).execute();
}
// long description
@@ -1786,31 +1801,20 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
// cache personal note
- final TextView personalNoteView = (TextView) view.findViewById(R.id.personalnote);
- setPersonalNote(personalNoteView);
- personalNoteView.setMovementMethod(LinkMovementMethod.getInstance());
+ setPersonalNote();
+ personalNoteView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
registerForContextMenu(personalNoteView);
final Button personalNoteEdit = (Button) view.findViewById(R.id.edit_personalnote);
- if (cache.isOffline()) {
- personalNoteEdit.setVisibility(View.VISIBLE);
- personalNoteEdit.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- EditorDialog editor = new EditorDialog(CacheDetailActivity.this, personalNoteView.getText());
- editor.setOnEditorUpdate(new EditorDialog.EditorUpdate() {
- @Override
- public void update(CharSequence editorText) {
- cache.setPersonalNote(editorText.toString());
- setPersonalNote(personalNoteView);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
- }
- });
- editor.show();
+ personalNoteEdit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (cache.isOffline()) {
+ editPersonalNote();
+ } else {
+ warnPersonalNoteNeedsStoring();
}
- });
- } else {
- personalNoteEdit.setVisibility(View.INVISIBLE);
- }
+ }
+ });
// cache hint and spoiler images
final View hintBoxView = view.findViewById(R.id.hint_box);
@@ -1863,13 +1867,28 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return view;
}
- private void setPersonalNote(final TextView personalNoteView) {
+ private void editPersonalNote() {
+ if (cache.isOffline()) {
+ editNoteDialogListener = new EditNoteDialogListener() {
+ @Override
+ public void onFinishEditNoteDialog(final String note) {
+ cache.setPersonalNote(note);
+ setPersonalNote();
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ }
+ };
+ final FragmentManager fm = getSupportFragmentManager();
+ final EditNoteDialog dialog = EditNoteDialog.newInstance(cache.getPersonalNote());
+ dialog.show(fm, "fragment_edit_note");
+ }
+ }
+
+ private void setPersonalNote() {
final String personalNote = cache.getPersonalNote();
personalNoteView.setText(personalNote, TextView.BufferType.SPANNABLE);
if (StringUtils.isNotBlank(personalNote)) {
personalNoteView.setVisibility(View.VISIBLE);
- }
- else {
+ } else {
personalNoteView.setVisibility(View.GONE);
}
}
@@ -1880,10 +1899,41 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
showDesc.setOnClickListener(null);
view.findViewById(R.id.loading).setVisibility(View.VISIBLE);
- new LoadDescriptionTask().execute(cache.getDescription(), view.findViewById(R.id.longdesc), view.findViewById(R.id.loading));
- registerForContextMenu(view.findViewById(R.id.longdesc));
+ new LoadDescriptionTask(cache.getDescription(), view.findViewById(R.id.longdesc), view.findViewById(R.id.loading), view.findViewById(R.id.shortdesc)).execute();
}
+ private void warnPersonalNoteNeedsStoring() {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(CacheDetailActivity.this);
+ builder.setTitle(R.string.cache_personal_note_unstored);
+ builder.setMessage(R.string.cache_personal_note_store);
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // do nothing
+ }
+ });
+
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ cache.store(null);
+ editPersonalNote();
+ }
+
+ });
+ final AlertDialog dialog = builder.create();
+ dialog.setOwnerActivity(CacheDetailActivity.this);
+ dialog.show();
+ }
+
+ }
+
+ @Override
+ public void onFinishEditNoteDialog(final String note) {
+ editNoteDialogListener.onFinishEditNoteDialog(note);
}
private static class HtmlImageCounter implements Html.ImageGetter {
@@ -1912,28 +1962,33 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* </ol>
*/
private class LoadDescriptionTask extends AsyncTask<Object, Void, Void> {
- private View loadingIndicatorView;
- private TextView descriptionView;
- private String descriptionString;
+ private final View loadingIndicatorView;
+ private final TextView descriptionView;
+ private final String descriptionString;
private Spanned description;
+ private final View shortDescView;
+ public LoadDescriptionTask(final String description, final View descriptionView, final View loadingIndicatorView, final View shortDescView) {
+ this.descriptionString = description;
+ this.descriptionView = (TextView) descriptionView;
+ this.loadingIndicatorView = loadingIndicatorView;
+ this.shortDescView = shortDescView;
+ }
@Override
protected Void doInBackground(Object... params) {
try {
- descriptionString = ((String) params[0]);
- descriptionView = (TextView) params[1];
- loadingIndicatorView = (View) params[2];
-
// Fast preview: parse only HTML without loading any images
HtmlImageCounter imageCounter = new HtmlImageCounter();
final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
description = Html.fromHtml(descriptionString, imageCounter, unknownTagsHandler);
publishProgress();
+
+ boolean needsRefresh = false;
if (imageCounter.getImageCount() > 0) {
// Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview
description = Html.fromHtml(descriptionString, new HtmlImage(cache.getGeocode(), true, cache.getListId(), false), unknownTagsHandler);
- publishProgress();
+ needsRefresh = true;
}
// If description has an HTML construct which may be problematic to render, add a note at the end of the long description.
@@ -1945,6 +2000,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>"));
((Editable) description).append("\n\n").append(tableNote);
((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ needsRefresh = true;
+ }
+
+ if (needsRefresh) {
publishProgress();
}
} catch (Exception e) {
@@ -1953,48 +2012,75 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return null;
}
- /*
- * (non-Javadoc)
- *
- * @see android.os.AsyncTask#onProgressUpdate(Progress[])
- */
@Override
protected void onProgressUpdate(Void... values) {
- if (description != null) {
- if (StringUtils.isNotBlank(descriptionString)) {
- descriptionView.setText(description, TextView.BufferType.SPANNABLE);
- descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- fixBlackTextColor(descriptionView, descriptionString);
- }
-
- descriptionView.setVisibility(View.VISIBLE);
- } else {
+ if (description == null) {
showToast(res.getString(R.string.err_load_descr_failed));
+ return;
}
+ if (StringUtils.isNotBlank(descriptionString)) {
+ descriptionView.setText(description, TextView.BufferType.SPANNABLE);
+ descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
+ fixTextColor(descriptionView, descriptionString);
+ descriptionView.setVisibility(View.VISIBLE);
+ registerForContextMenu(descriptionView);
+ hideDuplicatedShortDescription();
+ }
+ }
+
+ /**
+ * Hide the short description, if it is contained somewhere at the start of the long description.
+ */
+ private void hideDuplicatedShortDescription() {
+ if (shortDescView != null) {
+ final String shortDescription = cache.getShortDescription();
+ if (StringUtils.isNotBlank(shortDescription)) {
+ int index = descriptionString.indexOf(shortDescription);
+ if (index >= 0 && index < 200) {
+ shortDescView.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
if (null != loadingIndicatorView) {
loadingIndicatorView.setVisibility(View.GONE);
}
}
/**
- * handle caches with black font color
- *
+ * Handle caches with black font color in dark skin and white font color in light skin
+ * by changing background color of the view
+ *
* @param view
+ * containing the text
* @param text
+ * to be checked
*/
- private void fixBlackTextColor(final TextView view, final String text) {
+ private void fixTextColor(final TextView view, final String text) {
+ int backcolor;
if (Settings.isLightSkin()) {
- return;
- }
- int backcolor = color.black;
- if (-1 != StringUtils.indexOfAny(text, new String[] { "color=\"black", "color=\"#000080\"" })) {
- backcolor = color.darker_gray;
- }
- else {
- MatcherWrapper matcher = new MatcherWrapper(DARK_COLOR_PATTERN, text);
- if (matcher.find()) {
- backcolor = color.darker_gray;
+ backcolor = color.white;
+
+ for (Pattern pattern : LIGHT_COLOR_PATTERNS) {
+ final MatcherWrapper matcher = new MatcherWrapper(pattern, text);
+ if (matcher.find()) {
+ view.setBackgroundResource(color.darker_gray);
+ return;
+ }
+ }
+ } else {
+ backcolor = color.black;
+
+ for (Pattern pattern : DARK_COLOR_PATTERNS) {
+ final MatcherWrapper matcher = new MatcherWrapper(pattern, text);
+ if (matcher.find()) {
+ view.setBackgroundResource(color.darker_gray);
+ return;
+ }
}
}
view.setBackgroundResource(backcolor);
@@ -2094,15 +2180,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// Fast preview: parse only HTML without loading any images
HtmlImageCounter imageCounter = new HtmlImageCounter();
final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
- holder.text.setText(Html.fromHtml(logText, imageCounter, unknownTagsHandler));
+ holder.text.setText(Html.fromHtml(logText, imageCounter, unknownTagsHandler), TextView.BufferType.SPANNABLE);
if (imageCounter.getImageCount() > 0) {
// Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview
LogImageLoader loader = new LogImageLoader(holder);
- loader.execute(new String[] { logText });
+ loader.execute(logText);
}
}
else {
- holder.text.setText(logText);
+ holder.text.setText(logText, TextView.BufferType.SPANNABLE);
}
// images
@@ -2132,7 +2218,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (null == convertView) {
// if convertView != null then this listeners are already set
holder.author.setOnClickListener(userActionsClickListener);
- holder.text.setMovementMethod(LinkMovementMethod.getInstance());
+ holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
holder.text.setOnClickListener(decryptTextClickListener);
registerForContextMenu(holder.text);
}
@@ -2190,10 +2276,23 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
statusMarker = (ImageView) base.findViewById(R.id.log_mark);
}
+ /**
+ * Read the position of the cursor pointed to by this holder. <br/>
+ * This must be called by the UI thread.
+ *
+ * @return the cursor position
+ */
public int getPosition() {
return position;
}
+ /**
+ * Set the position of the cursor pointed to by this holder. <br/>
+ * This must be called by the UI thread.
+ *
+ * @param position
+ * the cursor position
+ */
public void setPosition(final int position) {
this.position = position;
}
@@ -2224,6 +2323,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// coordinates
if (null != wpt.getCoords()) {
final TextView coordinatesView = (TextView) waypointView.findViewById(R.id.coordinates);
+ coordinatesView.setOnClickListener(new CoordinatesFormatSwitcher(wpt.getCoords()));
coordinatesView.setText(wpt.getCoords().toString());
coordinatesView.setVisibility(View.VISIBLE);
}
diff --git a/main/src/cgeo/geocaching/CachePopup.java b/main/src/cgeo/geocaching/CachePopup.java
index e6d0148..4df428e 100644
--- a/main/src/cgeo/geocaching/CachePopup.java
+++ b/main/src/cgeo/geocaching/CachePopup.java
@@ -3,6 +3,7 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.network.Network;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
@@ -64,7 +65,7 @@ public class CachePopup extends AbstractPopupActivity {
}
public CachePopup() {
- super("c:geo-cache-info", R.layout.popup);
+ super(R.layout.popup);
}
@Override
@@ -160,6 +161,11 @@ public class CachePopup extends AbstractPopupActivity {
return;
}
+ if (!Network.isNetworkConnected(getApplicationContext())) {
+ showToast(getString(R.string.err_server));
+ return;
+ }
+
final RefreshCacheHandler refreshCacheHandler = new RefreshCacheHandler();
progress.show(CachePopup.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
new RefreshCacheThread(refreshCacheHandler).start();
diff --git a/main/src/cgeo/geocaching/cgeonavigate.java b/main/src/cgeo/geocaching/CompassActivity.java
index 17c2e20..73db653 100644
--- a/main/src/cgeo/geocaching/cgeonavigate.java
+++ b/main/src/cgeo/geocaching/CompassActivity.java
@@ -1,9 +1,13 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.maps.CGeoMap;
+import cgeo.geocaching.speech.SpeechService;
import cgeo.geocaching.ui.CompassView;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -12,8 +16,10 @@ import org.apache.commons.lang3.StringUtils;
import android.content.Context;
import android.content.Intent;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
import android.os.Bundle;
-import android.os.PowerManager;
+import android.speech.tts.TextToSpeech.Engine;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
@@ -24,46 +30,47 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-public class cgeonavigate extends AbstractActivity {
+public class CompassActivity extends AbstractActivity {
+
+ @InjectView(R.id.nav_type) protected TextView navType;
+ @InjectView(R.id.nav_accuracy) protected TextView navAccuracy;
+ @InjectView(R.id.nav_satellites) protected TextView navSatellites;
+ @InjectView(R.id.nav_location) protected TextView navLocation;
+ @InjectView(R.id.distance) protected TextView distanceView;
+ @InjectView(R.id.heading) protected TextView headingView;
+ @InjectView(R.id.rose) protected CompassView compassView;
+ @InjectView(R.id.destination) protected TextView destinationTextView;
+ @InjectView(R.id.cacheinfo) protected TextView cacheInfoView;
private static final String EXTRAS_COORDS = "coords";
private static final String EXTRAS_NAME = "name";
private static final String EXTRAS_GEOCODE = "geocode";
private static final String EXTRAS_CACHE_INFO = "cacheinfo";
private static final List<IWaypoint> coordinates = new ArrayList<IWaypoint>();
- private static final int MENU_MAP = 0;
- private static final int MENU_SWITCH_COMPASS_GPS = 1;
- private PowerManager pm = null;
+ private static final int COORDINATES_OFFSET = 10;
+ private static final int REQUEST_TTS_DATA_CHECK = 1;
private Geopoint dstCoords = null;
private float cacheHeading = 0;
private String title = null;
private String info = null;
- private TextView navType = null;
- private TextView navAccuracy = null;
- private TextView navSatellites = null;
- private TextView navLocation = null;
- private TextView distanceView = null;
- private TextView headingView = null;
- private CompassView compassView = null;
-
- public cgeonavigate() {
- super("c:geo-compass", true);
- }
+ private boolean hasMagneticFieldSensor;
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ super.onCreate(savedInstanceState, R.layout.navigate);
- setTheme();
- setContentView(R.layout.navigate);
- setTitle(res.getString(R.string.compass_title));
+ final SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
+ hasMagneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null;
+ if (!hasMagneticFieldSensor) {
+ Settings.setUseCompass(false);
+ }
// get parameters
Bundle extras = getIntent().getExtras();
if (extras != null) {
title = extras.getString(EXTRAS_GEOCODE);
final String name = extras.getString(EXTRAS_NAME);
- dstCoords = (Geopoint) extras.getParcelable(EXTRAS_COORDS);
+ dstCoords = extras.getParcelable(EXTRAS_COORDS);
info = extras.getString(EXTRAS_CACHE_INFO);
if (StringUtils.isNotBlank(name)) {
@@ -86,8 +93,7 @@ public class cgeonavigate extends AbstractActivity {
setDestCoords();
setCacheInfo();
- // get textviews once
- compassView = (CompassView) findViewById(R.id.rose);
+ Views.inject(this);
}
@Override
@@ -96,11 +102,6 @@ public class cgeonavigate extends AbstractActivity {
// sensor & geolocation manager
geoDirHandler.startGeoAndDir();
-
- // keep backlight on
- if (pm == null) {
- pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- }
}
@Override
@@ -112,23 +113,23 @@ public class cgeonavigate extends AbstractActivity {
@Override
public void onDestroy() {
compassView.destroyDrawingCache();
+ SpeechService.stopService(this);
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
- menu.add(0, MENU_SWITCH_COMPASS_GPS, 0, res.getString(Settings.isUseCompass() ? R.string.use_gps : R.string.use_compass)).setIcon(R.drawable.ic_menu_compass);
- menu.add(0, MENU_MAP, 0, res.getString(R.string.caches_on_map)).setIcon(R.drawable.ic_menu_mapmode);
- menu.add(0, 2, 0, res.getString(R.string.destination_set)).setIcon(R.drawable.ic_menu_edit);
+ getMenuInflater().inflate(R.menu.compass_activity_options, menu);
+ menu.findItem(R.id.menu_switch_compass_gps).setVisible(hasMagneticFieldSensor);
+ final SubMenu subMenu = menu.findItem(R.id.menu_select_destination).getSubMenu();
if (coordinates.size() > 1) {
- final SubMenu subMenu = menu.addSubMenu(0, 3, 0, res.getString(R.string.destination_select)).setIcon(R.drawable.ic_menu_myplaces);
- int cnt = 4;
- for (final IWaypoint coordinate : coordinates) {
- subMenu.add(0, cnt, 0, coordinate.getName() + " (" + coordinate.getCoordType() + ")");
- cnt++;
+ for (int i = 0; i < coordinates.size(); i++) {
+ final IWaypoint coordinate = coordinates.get(i);
+ subMenu.add(0, COORDINATES_OFFSET + i, 0, coordinate.getName() + " (" + coordinate.getCoordType() + ")");
}
- } else {
- menu.add(0, 3, 0, res.getString(R.string.destination_select)).setIcon(R.drawable.ic_menu_myplaces).setEnabled(false);
+ }
+ else {
+ menu.findItem(R.id.menu_select_destination).setVisible(false);
}
return true;
}
@@ -136,46 +137,73 @@ public class cgeonavigate extends AbstractActivity {
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- menu.findItem(MENU_SWITCH_COMPASS_GPS).setTitle(res.getString(Settings.isUseCompass() ? R.string.use_gps : R.string.use_compass));
+ menu.findItem(R.id.menu_switch_compass_gps).setTitle(res.getString(Settings.isUseCompass() ? R.string.use_gps : R.string.use_compass));
+ menu.findItem(R.id.menu_tts_start).setVisible(!SpeechService.isRunning());
+ menu.findItem(R.id.menu_tts_stop).setVisible(SpeechService.isRunning());
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
+ switch (id) {
+ case R.id.menu_map:
+ CGeoMap.startActivityCoords(this, dstCoords, null, null);
+ return true;
+ case R.id.menu_switch_compass_gps:
+ boolean oldSetting = Settings.isUseCompass();
+ Settings.setUseCompass(!oldSetting);
+ invalidateOptionsMenuCompatible();
+ if (oldSetting) {
+ geoDirHandler.stopDir();
+ } else {
+ geoDirHandler.startDir();
+ }
+ return true;
+ case R.id.menu_edit_destination:
+ Intent pointIntent = new Intent(this, NavigateAnyPointActivity.class);
+ startActivity(pointIntent);
+
+ finish();
+ return true;
+ case R.id.menu_tts_start:
+ initTextToSpeech();
+ return true;
+ case R.id.menu_tts_stop:
+ SpeechService.stopService(this);
+ return true;
+ default:
+ int coordinatesIndex = id - COORDINATES_OFFSET;
+ if (coordinatesIndex >= 0 && coordinatesIndex < coordinates.size()) {
+ final IWaypoint coordinate = coordinates.get(coordinatesIndex);
+ title = coordinate.getName();
+ dstCoords = coordinate.getCoords();
+ setTitle();
+ setDestCoords();
+ setCacheInfo();
+ updateDistanceInfo(app.currentGeo());
+
+ Log.d("destination set: " + title + " (" + dstCoords + ")");
+ return true;
+ }
+ }
+ return false;
+ }
- if (id == MENU_MAP) {
- CGeoMap.startActivityCoords(this, dstCoords, null, null);
- } else if (id == MENU_SWITCH_COMPASS_GPS) {
- boolean oldSetting = Settings.isUseCompass();
- Settings.setUseCompass(!oldSetting);
- invalidateOptionsMenuCompatible();
- if (oldSetting) {
- geoDirHandler.stopDir();
- } else {
- geoDirHandler.startDir();
- }
- } else if (id == 2) {
- Intent pointIntent = new Intent(this, NavigateAnyPointActivity.class);
- startActivity(pointIntent);
+ private void initTextToSpeech() {
+ Intent intent = new Intent(Engine.ACTION_CHECK_TTS_DATA);
+ startActivityForResult(intent, REQUEST_TTS_DATA_CHECK);
+ }
- finish();
- return true;
- } else if (id > 3 && coordinates.get(id - 4) != null) {
- final IWaypoint coordinate = coordinates.get(id - 4);
-
- title = coordinate.getName();
- dstCoords = coordinate.getCoords();
- setTitle();
- setDestCoords();
- setCacheInfo();
- updateDistanceInfo(app.currentGeo());
-
- Log.d("destination set: " + title + " (" + dstCoords + ")");
- return true;
+ @Override
+ protected void onActivityResult(int request, int result, Intent data) {
+ if (request == REQUEST_TTS_DATA_CHECK && result == Engine.CHECK_VOICE_DATA_PASS) {
+ SpeechService.startService(this, dstCoords);
+ }
+ else {
+ Log.i("TTS failed to start. Request: " + request + " result: " + result);
+ startActivity(new Intent(Engine.ACTION_INSTALL_TTS_DATA));
}
-
- return false;
}
private void setTitle() {
@@ -191,11 +219,10 @@ public class cgeonavigate extends AbstractActivity {
return;
}
- ((TextView) findViewById(R.id.destination)).setText(dstCoords.toString());
+ destinationTextView.setText(dstCoords.toString());
}
private void setCacheInfo() {
- final TextView cacheInfoView = (TextView) findViewById(R.id.cacheinfo);
if (info == null) {
cacheInfoView.setVisibility(View.GONE);
return;
@@ -209,13 +236,6 @@ public class cgeonavigate extends AbstractActivity {
return;
}
- if (distanceView == null) {
- distanceView = (TextView) findViewById(R.id.distance);
- }
- if (headingView == null) {
- headingView = (TextView) findViewById(R.id.heading);
- }
-
cacheHeading = geo.getCoords().bearingTo(dstCoords);
distanceView.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(dstCoords)));
headingView.setText(Math.round(cacheHeading) + "°");
@@ -225,13 +245,6 @@ public class cgeonavigate extends AbstractActivity {
@Override
public void updateGeoData(final IGeoData geo) {
try {
- if (navType == null || navLocation == null || navAccuracy == null) {
- navType = (TextView) findViewById(R.id.nav_type);
- navAccuracy = (TextView) findViewById(R.id.nav_accuracy);
- navSatellites = (TextView) findViewById(R.id.nav_satellites);
- navLocation = (TextView) findViewById(R.id.nav_location);
- }
-
if (geo.getCoords() != null) {
if (geo.getSatellitesVisible() >= 0) {
navSatellites.setText(res.getString(R.string.loc_sat) + ": " + geo.getSatellitesFixed() + "/" + geo.getSatellitesVisible());
@@ -272,7 +285,7 @@ public class cgeonavigate extends AbstractActivity {
@Override
public void updateDirection(final float direction) {
if (app.currentGeo().getSpeed() <= 5) { // use compass when speed is lower than 18 km/h
- updateNorthHeading(DirectionProvider.getDirectionNow(cgeonavigate.this, direction));
+ updateNorthHeading(DirectionProvider.getDirectionNow(CompassActivity.this, direction));
}
}
};
@@ -286,11 +299,15 @@ public class cgeonavigate extends AbstractActivity {
public static void startActivity(final Context context, final String geocode, final String displayedName, final Geopoint coords, final Collection<IWaypoint> coordinatesWithType,
final String info) {
coordinates.clear();
- if (coordinatesWithType != null) { // avoid possible NPE
- coordinates.addAll(coordinatesWithType);
+ if (coordinatesWithType != null) {
+ for (IWaypoint coordinate : coordinatesWithType) {
+ if (coordinate != null) {
+ coordinates.add(coordinate);
+ }
+ }
}
- final Intent navigateIntent = new Intent(context, cgeonavigate.class);
+ final Intent navigateIntent = new Intent(context, CompassActivity.class);
navigateIntent.putExtra(EXTRAS_COORDS, coords);
navigateIntent.putExtra(EXTRAS_GEOCODE, geocode);
if (null != displayedName) {
@@ -301,7 +318,7 @@ public class cgeonavigate extends AbstractActivity {
}
public static void startActivity(final Context context, final String geocode, final String displayedName, final Geopoint coords, final Collection<IWaypoint> coordinatesWithType) {
- cgeonavigate.startActivity(context, geocode, displayedName, coords, coordinatesWithType, null);
+ CompassActivity.startActivity(context, geocode, displayedName, coords, coordinatesWithType, null);
}
}
diff --git a/main/src/cgeo/geocaching/DirectionProvider.java b/main/src/cgeo/geocaching/DirectionProvider.java
index c1f83ac..37b184a 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 signaled to observers to avoid resending the same value when the
+ // Previous values signaled to observers to avoid re-sending 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.
@@ -27,7 +27,8 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
@Override
protected void onFirstObserver() {
- sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
+ final Sensor defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
+ sensorManager.registerListener(this, defaultSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
@@ -43,7 +44,7 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
* 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
*/
diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java
index 7f011fc..0a1d22d 100644
--- a/main/src/cgeo/geocaching/EditWaypointActivity.java
+++ b/main/src/cgeo/geocaching/EditWaypointActivity.java
@@ -1,7 +1,8 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+
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;
@@ -37,6 +38,7 @@ import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.RadioButton;
+import android.widget.RadioGroup;
import android.widget.Spinner;
import java.util.ArrayList;
@@ -44,6 +46,19 @@ import java.util.EnumSet;
import java.util.List;
public class EditWaypointActivity extends AbstractActivity {
+ @InjectView(R.id.buttonLatitude) protected Button buttonLat;
+ @InjectView(R.id.buttonLongitude) protected Button buttonLon;
+ @InjectView(R.id.add_waypoint) protected Button addWaypoint;
+ @InjectView(R.id.note) protected EditText note;
+ @InjectView(R.id.wpt_visited_checkbox) protected CheckBox visitedCheckBox;
+ @InjectView(R.id.name) protected AutoCompleteTextView waypointName;
+ @InjectView(R.id.type) protected Spinner waypointTypeSelector;
+ @InjectView(R.id.distance) protected EditText distanceView;
+ @InjectView(R.id.modify_cache_coordinates_group) protected RadioGroup coordinatesGroup;
+ @InjectView(R.id.modify_cache_coordinates_local_and_remote) protected RadioButton modifyBoth;
+ @InjectView(R.id.distanceUnit) protected Spinner distanceUnitSelector;
+ @InjectView(R.id.bearing) protected EditText bearing;
+ @InjectView(R.id.modify_cache_coordinates_local) protected RadioButton modifyLocal;
private String geocode = null;
private int id = -1;
@@ -78,15 +93,15 @@ public class EditWaypointActivity extends AbstractActivity {
visited = waypoint.isVisited();
if (waypoint.getCoords() != null) {
- ((Button) findViewById(R.id.buttonLatitude)).setText(waypoint.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE));
- ((Button) findViewById(R.id.buttonLongitude)).setText(waypoint.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE));
+ buttonLat.setText(waypoint.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE));
+ buttonLon.setText(waypoint.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE));
}
- ((EditText) findViewById(R.id.name)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getName())).toString());
+ waypointName.setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getName())).toString());
if (BaseUtils.containsHtml(waypoint.getNote())) {
- ((EditText) findViewById(R.id.note)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getNote())).toString());
+ note.setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getNote())).toString());
}
else {
- ((EditText) findViewById(R.id.note)).setText(StringUtils.trimToEmpty(waypoint.getNote()));
+ note.setText(StringUtils.trimToEmpty(waypoint.getNote()));
}
Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_ONLY);
setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache);
@@ -95,7 +110,7 @@ public class EditWaypointActivity extends AbstractActivity {
if (own) {
initializeWaypointTypeSelector();
}
- ((CheckBox) findViewById(R.id.wpt_visited_checkbox)).setChecked(visited);
+ visitedCheckBox.setChecked(visited);
initializeDistanceUnitSelector();
} catch (Exception e) {
@@ -111,11 +126,7 @@ public class EditWaypointActivity extends AbstractActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.edit_waypoint_activity);
- setTitle("waypoint");
+ super.onCreate(savedInstanceState, R.layout.edit_waypoint_activity);
// get parameters
Bundle extras = getIntent().getExtras();
@@ -138,24 +149,19 @@ public class EditWaypointActivity extends AbstractActivity {
setTitle(res.getString(R.string.waypoint_edit_title));
}
- Button buttonLat = (Button) findViewById(R.id.buttonLatitude);
buttonLat.setOnClickListener(new CoordDialogListener());
- Button buttonLon = (Button) findViewById(R.id.buttonLongitude);
buttonLon.setOnClickListener(new CoordDialogListener());
- Button addWaypoint = (Button) findViewById(R.id.add_waypoint);
addWaypoint.setOnClickListener(new CoordsListener());
List<String> wayPointNames = new ArrayList<String>();
for (WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) {
wayPointNames.add(wpt.getL10n());
}
- AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.name);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, wayPointNames);
- textView.setAdapter(adapter);
+ waypointName.setAdapter(adapter);
if (id > 0) {
- Spinner waypointTypeSelector = (Spinner) findViewById(R.id.type);
waypointTypeSelector.setVisibility(View.GONE);
waitDialog = ProgressDialog.show(this, null, res.getString(R.string.waypoint_loading), true);
@@ -171,7 +177,6 @@ public class EditWaypointActivity extends AbstractActivity {
IConnector con = ConnectorFactory.getConnector(geocode);
setCoordsModificationVisibility(con, cache);
}
- CheckBox visitedCheckBox = ((CheckBox) findViewById(R.id.wpt_visited_checkbox));
visitedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -181,16 +186,16 @@ public class EditWaypointActivity extends AbstractActivity {
initializeDistanceUnitSelector();
- disableSuggestions((EditText) findViewById(R.id.distance));
+ disableSuggestions(distanceView);
}
private void setCoordsModificationVisibility(IConnector con, Geocache 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);
+ coordinatesGroup.setVisibility(View.VISIBLE);
+ modifyBoth.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);
+ coordinatesGroup.setVisibility(View.GONE);
+ modifyBoth.setVisibility(View.GONE);
}
}
@@ -211,25 +216,12 @@ public class EditWaypointActivity extends AbstractActivity {
}
@Override
- public void onDestroy() {
- super.onDestroy();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- }
-
- @Override
public void onPause() {
geoDirHandler.stopGeo();
super.onPause();
}
private void initializeWaypointTypeSelector() {
-
- Spinner waypointTypeSelector = (Spinner) findViewById(R.id.type);
-
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);
@@ -247,9 +239,6 @@ public class EditWaypointActivity extends AbstractActivity {
}
private void initializeDistanceUnitSelector() {
-
- Spinner distanceUnitSelector = (Spinner) findViewById(R.id.distanceUnit);
-
if (StringUtils.isBlank(distanceUnit)) {
if (Settings.isUseMetricUnits()) {
distanceUnitSelector.setSelection(0); // m
@@ -271,10 +260,8 @@ public class EditWaypointActivity extends AbstractActivity {
}
try {
- Button bLat = (Button) findViewById(R.id.buttonLatitude);
- 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));
+ buttonLat.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW));
+ buttonLon.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW));
} catch (final Exception e) {
Log.e("failed to update location", e);
}
@@ -311,8 +298,8 @@ public class EditWaypointActivity extends AbstractActivity {
coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
@Override
public void update(final Geopoint gp) {
- ((Button) findViewById(R.id.buttonLatitude)).setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
- ((Button) findViewById(R.id.buttonLongitude)).setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
+ buttonLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
+ buttonLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
if (waypoint != null) {
waypoint.setCoords(gp);
} else {
@@ -378,11 +365,11 @@ public class EditWaypointActivity extends AbstractActivity {
@Override
public void onClick(View arg0) {
- final String bearingText = ((EditText) findViewById(R.id.bearing)).getText().toString();
+ final String bearingText = bearing.getText().toString();
// combine distance from EditText and distanceUnit saved from Spinner
- final String distanceText = ((EditText) findViewById(R.id.distance)).getText().toString() + distanceUnit;
- final String latText = ((Button) findViewById(R.id.buttonLatitude)).getText().toString();
- final String lonText = ((Button) findViewById(R.id.buttonLongitude)).getText().toString();
+ final String distanceText = distanceView.getText().toString() + distanceUnit;
+ final String latText = buttonLat.getText().toString();
+ final String lonText = buttonLon.getText().toString();
if (StringUtils.isBlank(bearingText) && StringUtils.isBlank(distanceText)
&& StringUtils.isBlank(latText) && StringUtils.isBlank(lonText)) {
@@ -430,9 +417,9 @@ public class EditWaypointActivity extends AbstractActivity {
}
// if no name is given, just give the waypoint its number as name
- final String givenName = ((EditText) findViewById(R.id.name)).getText().toString().trim();
+ final String givenName = waypointName.getText().toString().trim();
final String name = StringUtils.isNotEmpty(givenName) ? givenName : res.getString(R.string.waypoint) + " " + (wpCount + 1);
- final String note = ((EditText) findViewById(R.id.note)).getText().toString().trim();
+ final String noteText = note.getText().toString().trim();
final Geopoint coordsToSave = coords;
final ProgressDialog progress = ProgressDialog.show(EditWaypointActivity.this, getString(R.string.cache), getString(R.string.waypoint_being_saved), true);
final Handler finishHandler = new Handler() {
@@ -483,7 +470,7 @@ public class EditWaypointActivity extends AbstractActivity {
waypoint.setPrefix(prefix);
waypoint.setLookup(lookup);
waypoint.setCoords(coordsToSave);
- waypoint.setNote(note);
+ waypoint.setNote(noteText);
waypoint.setVisited(visited);
waypoint.setId(id);
@@ -501,8 +488,6 @@ public class EditWaypointActivity extends AbstractActivity {
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);
@@ -541,11 +526,6 @@ public class EditWaypointActivity extends AbstractActivity {
return con.supportsOwnCoordinates() && con.uploadModifiedCoordinates(cache, waypointUploaded);
}
- @Override
- public void goManual(final View view) {
- ActivityMixin.goManual(this, id >= 0 ? "c:geo-waypoint-edit" : "c:geo-waypoint-new");
- }
-
public static void startActivityEditWaypoint(final Context context, final int waypointId) {
context.startActivity(new Intent(context, EditWaypointActivity.class)
.putExtra(Intents.EXTRA_WAYPOINT_ID, waypointId));
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index 836cccb..ac1c9b1 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -5,6 +5,7 @@ import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.activity.IAbstractActivity;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
+import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.capability.ISearchByCenter;
import cgeo.geocaching.connector.capability.ISearchByGeocode;
import cgeo.geocaching.connector.gc.GCConnector;
@@ -47,8 +48,8 @@ import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
@@ -175,7 +176,9 @@ public class Geocache implements ICache, IWaypoint {
}
/**
- * Gather missing information from another cache object.
+ * Gather missing information for new Geocache object from the stored Geocache object.
+ * This is called in the new Geocache parsed from website to set information not yet
+ * parsed.
*
* @param other
* the other version, or null if non-existent
@@ -187,6 +190,8 @@ public class Geocache implements ICache, IWaypoint {
}
updated = System.currentTimeMillis();
+ // if parsed cache is not yet detailed and stored is, the information of
+ // the parsed cache will be overwritten
if (!detailed && (other.detailed || zoomlevel < other.zoomlevel)) {
detailed = other.detailed;
detailedUpdate = other.detailedUpdate;
@@ -194,15 +199,19 @@ public class Geocache implements ICache, IWaypoint {
cacheType = other.cacheType;
zoomlevel = other.zoomlevel;
// boolean values must be enumerated here. Other types are assigned outside this if-statement
+ // TODO: check whether a search or a live map systematically returns those, in which case
+ // we want to keep the most recent one instead of getting information from the previously
+ // stored data. This is the case for "archived" for example which has been taken out of this
+ // list.
premiumMembersOnly = other.premiumMembersOnly;
reliableLatLon = other.reliableLatLon;
- archived = other.archived;
found = other.found;
disabled = other.disabled;
favorite = other.favorite;
onWatchlist = other.onWatchlist;
logOffline = other.logOffline;
finalDefined = other.finalDefined;
+ archived = other.archived;
}
/*
@@ -447,7 +456,7 @@ public class Geocache implements ICache, IWaypoint {
}
public void logVisit(final IAbstractActivity fromActivity) {
- if (StringUtils.isBlank(cacheId)) {
+ if (!getConnector().canLog(this)) {
fromActivity.showToast(((Activity) fromActivity).getResources().getString(R.string.err_cannot_log_visit));
return;
}
@@ -483,34 +492,37 @@ public class Geocache implements ICache, IWaypoint {
}
public List<LogType> getPossibleLogTypes() {
- final List<LogType> logTypes = new LinkedList<LogType>();
+ final List<LogType> logTypes = new ArrayList<LogType>();
if (isEventCache()) {
logTypes.add(LogType.WILL_ATTEND);
- logTypes.add(LogType.NOTE);
logTypes.add(LogType.ATTENDED);
- logTypes.add(LogType.NEEDS_ARCHIVE);
if (isOwner()) {
logTypes.add(LogType.ANNOUNCEMENT);
}
} else if (CacheType.WEBCAM == cacheType) {
logTypes.add(LogType.WEBCAM_PHOTO_TAKEN);
- logTypes.add(LogType.DIDNT_FIND_IT);
- logTypes.add(LogType.NOTE);
- logTypes.add(LogType.NEEDS_ARCHIVE);
- logTypes.add(LogType.NEEDS_MAINTENANCE);
} else {
logTypes.add(LogType.FOUND_IT);
+ }
+ if (!isEventCache()) {
logTypes.add(LogType.DIDNT_FIND_IT);
- logTypes.add(LogType.NOTE);
- logTypes.add(LogType.NEEDS_ARCHIVE);
+ }
+ logTypes.add(LogType.NOTE);
+ if (!isEventCache()) {
logTypes.add(LogType.NEEDS_MAINTENANCE);
}
if (isOwner()) {
logTypes.add(LogType.OWNER_MAINTENANCE);
- logTypes.add(LogType.TEMP_DISABLE_LISTING);
- logTypes.add(LogType.ENABLE_LISTING);
+ if (isDisabled()) {
+ logTypes.add(LogType.ENABLE_LISTING);
+ }
+ else {
+ logTypes.add(LogType.TEMP_DISABLE_LISTING);
+ }
logTypes.add(LogType.ARCHIVE);
- logTypes.remove(LogType.UPDATE_COORDINATES);
+ }
+ if (!isArchived() && !isOwner()) {
+ logTypes.add(LogType.NEEDS_ARCHIVE);
}
return logTypes;
}
@@ -551,6 +563,10 @@ public class Geocache implements ICache, IWaypoint {
return getConnector().supportsLogging();
}
+ public boolean supportsLogImages() {
+ return getConnector().supportsLogImages();
+ }
+
public boolean supportsOwnCoordinates() {
return getConnector().supportsOwnCoordinates();
}
@@ -559,6 +575,10 @@ public class Geocache implements ICache, IWaypoint {
return getConnector().getCacheRealm();
}
+ public ILoggingManager getLoggingManager(Activity activity) {
+ return getConnector().getLoggingManager(activity, this);
+ }
+
@Override
public float getDifficulty() {
return difficulty;
@@ -710,10 +730,7 @@ public class Geocache implements ICache, IWaypoint {
public String getPersonalNote() {
// non premium members have no personal notes, premium members have an empty string by default.
// map both to null, so other code doesn't need to differentiate
- if (StringUtils.isBlank(personalNote)) {
- return null;
- }
- return personalNote;
+ return StringUtils.defaultIfBlank(personalNote, null);
}
public boolean supportsUserActions() {
@@ -765,8 +782,8 @@ public class Geocache implements ICache, IWaypoint {
return favorite;
}
- public void setFavorite(boolean favourite) {
- this.favorite = favourite;
+ public void setFavorite(boolean favorite) {
+ this.favorite = favorite;
}
@Override
@@ -829,8 +846,7 @@ public class Geocache implements ICache, IWaypoint {
}
public boolean isVirtual() {
- return CacheType.VIRTUAL == cacheType || CacheType.WEBCAM == cacheType
- || CacheType.EARTH == cacheType;
+ return cacheType.isVirtual();
}
public boolean showSize() {
@@ -1360,6 +1376,9 @@ public class Geocache implements ICache, IWaypoint {
return null;
}
+ /**
+ * Detect coordinates in the personal note and convert them to user defined waypoints. Works by rule of thumb.
+ */
public void parseWaypointsFromNote() {
try {
if (StringUtils.isBlank(getPersonalNote())) {
@@ -1378,7 +1397,8 @@ public class Geocache implements ICache, IWaypoint {
((point.getLatitudeE6() % 1000) != 0 || (point.getLongitudeE6() % 1000) != 0) &&
!hasIdenticalWaypoint(point)) {
final String name = cgeoapplication.getInstance().getString(R.string.cache_personal_note) + " " + count;
- final Waypoint waypoint = new Waypoint(name, WaypointType.WAYPOINT, false);
+ final String potentialWaypointType = note.substring(Math.max(0, matcher.start() - 15));
+ final Waypoint waypoint = new Waypoint(name, parseWaypointType(potentialWaypointType), false);
waypoint.setCoords(point);
addOrChangeWaypoint(waypoint, false);
count++;
@@ -1395,6 +1415,25 @@ public class Geocache implements ICache, IWaypoint {
}
}
+ /**
+ * Detect waypoint types in the personal note text. It works by rule of thumb only.
+ */
+ private static WaypointType parseWaypointType(final String input) {
+ final String lowerInput = StringUtils.substring(input, 0, 20).toLowerCase(Locale.getDefault());
+ for (WaypointType wpType : WaypointType.values()) {
+ if (lowerInput.contains(wpType.getL10n().toLowerCase(Locale.getDefault()))) {
+ return wpType;
+ }
+ if (lowerInput.contains(wpType.id)) {
+ return wpType;
+ }
+ if (lowerInput.contains(wpType.name().toLowerCase(Locale.US))) {
+ return wpType;
+ }
+ }
+ return WaypointType.WAYPOINT;
+ }
+
private boolean hasIdenticalWaypoint(final Geopoint point) {
for (final Waypoint waypoint: waypoints) {
if (waypoint.getCoords().equals(point)) {
diff --git a/main/src/cgeo/geocaching/GpxFileListActivity.java b/main/src/cgeo/geocaching/GpxFileListActivity.java
index f12a30c..de0be21 100644
--- a/main/src/cgeo/geocaching/GpxFileListActivity.java
+++ b/main/src/cgeo/geocaching/GpxFileListActivity.java
@@ -31,14 +31,9 @@ public class GpxFileListActivity extends AbstractFileListActivity<GPXListAdapter
return Collections.singletonList(new File(Settings.getGpxImportDir()));
}
- @Override
- protected void setTitle() {
- setTitle(res.getString(R.string.gpx_import_title));
- }
-
public static void startSubActivity(Activity fromActivity, int listId) {
final Intent intent = new Intent(fromActivity, GpxFileListActivity.class);
- intent.putExtra(Intents.EXTRA_LIST_ID, listId);
+ intent.putExtra(Intents.EXTRA_LIST_ID, StoredList.getConcreteList(listId));
fromActivity.startActivityForResult(intent, 0);
}
diff --git a/main/src/cgeo/geocaching/ImageSelectActivity.java b/main/src/cgeo/geocaching/ImageSelectActivity.java
index 347cd86..f442a51 100644
--- a/main/src/cgeo/geocaching/ImageSelectActivity.java
+++ b/main/src/cgeo/geocaching/ImageSelectActivity.java
@@ -1,7 +1,11 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.compatibility.Compatibility;
+import cgeo.geocaching.utils.ImageHelper;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
@@ -10,14 +14,18 @@ import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.Spinner;
import java.io.File;
import java.text.SimpleDateFormat;
@@ -25,37 +33,41 @@ import java.util.Date;
import java.util.Locale;
public class ImageSelectActivity extends AbstractActivity {
+
+ @InjectView(R.id.caption) protected EditText captionView;
+ @InjectView(R.id.description) protected EditText descriptionView;
+ @InjectView(R.id.logImageScale) protected Spinner scaleView;
+ @InjectView(R.id.camera) protected Button cameraButton;
+ @InjectView(R.id.stored) protected Button storedButton;
+ @InjectView(R.id.save) protected Button saveButton;
+ @InjectView(R.id.cancel) protected Button clearButton;
+ @InjectView(R.id.image_preview) protected ImageView imagePreview;
+
static final String EXTRAS_CAPTION = "caption";
static final String EXTRAS_DESCRIPTION = "description";
static final String EXTRAS_URI_AS_STRING = "uri";
+ static final String EXTRAS_SCALE = "scale";
private static final String SAVED_STATE_IMAGE_CAPTION = "cgeo.geocaching.saved_state_image_caption";
private static final String SAVED_STATE_IMAGE_DESCRIPTION = "cgeo.geocaching.saved_state_image_description";
private static final String SAVED_STATE_IMAGE_URI = "cgeo.geocaching.saved_state_image_uri";
+ private static final String SAVED_STATE_IMAGE_SCALE = "cgeo.geocaching.saved_state_image_scale";
private static final int SELECT_NEW_IMAGE = 1;
private static final int SELECT_STORED_IMAGE = 2;
- private EditText captionView;
- private EditText descriptionView;
-
// Data to be saved while reconfiguring
private String imageCaption;
private String imageDescription;
+ private int scaleChoiceIndex;
private Uri imageUri;
- public ImageSelectActivity() {
- super("c:geo-selectimage");
- }
-
@Override
public void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.visit_image);
- setTitle(res.getString(R.string.log_image));
+ super.onCreate(savedInstanceState, R.layout.visit_image);
+ Views.inject(this);
+ scaleChoiceIndex = Settings.getLogImageScale();
imageCaption = "";
imageDescription = "";
imageUri = Uri.EMPTY;
@@ -66,6 +78,7 @@ public class ImageSelectActivity extends AbstractActivity {
imageCaption = extras.getString(EXTRAS_CAPTION);
imageDescription = extras.getString(EXTRAS_DESCRIPTION);
imageUri = Uri.parse(extras.getString(EXTRAS_URI_AS_STRING));
+ scaleChoiceIndex = extras.getInt(EXTRAS_SCALE, scaleChoiceIndex);
}
// Restore previous state
@@ -73,9 +86,9 @@ public class ImageSelectActivity extends AbstractActivity {
imageCaption = savedInstanceState.getString(SAVED_STATE_IMAGE_CAPTION);
imageDescription = savedInstanceState.getString(SAVED_STATE_IMAGE_DESCRIPTION);
imageUri = Uri.parse(savedInstanceState.getString(SAVED_STATE_IMAGE_URI));
+ scaleChoiceIndex = savedInstanceState.getInt(SAVED_STATE_IMAGE_SCALE);
}
- final Button cameraButton = (Button) findViewById(R.id.camera);
cameraButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -84,7 +97,6 @@ public class ImageSelectActivity extends AbstractActivity {
}
});
- final Button storedButton = (Button) findViewById(R.id.stored);
storedButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -93,17 +105,27 @@ public class ImageSelectActivity extends AbstractActivity {
}
});
- captionView = (EditText) findViewById(R.id.caption);
if (StringUtils.isNotBlank(imageCaption)) {
captionView.setText(imageCaption);
}
- descriptionView = (EditText) findViewById(R.id.description);
if (StringUtils.isNotBlank(imageDescription)) {
descriptionView.setText(imageDescription);
}
- final Button saveButton = (Button) findViewById(R.id.save);
+ scaleView.setSelection(scaleChoiceIndex);
+ scaleView.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
+ scaleChoiceIndex = scaleView.getSelectedItemPosition();
+ Settings.setLogImageScale(scaleChoiceIndex);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> arg0) {
+ }
+ });
+
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -112,7 +134,6 @@ public class ImageSelectActivity extends AbstractActivity {
}
});
- final Button clearButton = (Button) findViewById(R.id.cancel);
clearButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -131,15 +152,19 @@ public class ImageSelectActivity extends AbstractActivity {
outState.putString(SAVED_STATE_IMAGE_CAPTION, imageCaption);
outState.putString(SAVED_STATE_IMAGE_DESCRIPTION, imageDescription);
outState.putString(SAVED_STATE_IMAGE_URI, imageUri != null ? imageUri.getPath() : StringUtils.EMPTY);
+ outState.putInt(SAVED_STATE_IMAGE_SCALE, scaleChoiceIndex);
}
public void saveImageInfo(boolean saveInfo) {
if (saveInfo) {
+ String filename = writeScaledImage(imageUri.getPath());
+ imageUri = Uri.parse(filename);
Intent intent = new Intent();
syncEditTexts();
intent.putExtra(EXTRAS_CAPTION, imageCaption);
intent.putExtra(EXTRAS_DESCRIPTION, imageDescription);
intent.putExtra(EXTRAS_URI_AS_STRING, imageUri.toString());
+ intent.putExtra(EXTRAS_SCALE, scaleChoiceIndex);
setResult(RESULT_OK, intent);
} else {
@@ -152,6 +177,7 @@ public class ImageSelectActivity extends AbstractActivity {
private void syncEditTexts() {
imageCaption = captionView.getText().toString();
imageDescription = descriptionView.getText().toString();
+ scaleChoiceIndex = scaleView.getSelectedItemPosition();
}
private void selectImageFromCamera() {
@@ -231,8 +257,40 @@ public class ImageSelectActivity extends AbstractActivity {
loadImagePreview();
}
+ /**
+ * Scales and writes the scaled image.
+ *
+ * @param filePath
+ * @return
+ */
+ private String writeScaledImage(final String filePath) {
+ scaleChoiceIndex = scaleView.getSelectedItemPosition();
+ final int maxXY = getResources().getIntArray(R.array.log_image_scale_values)[scaleChoiceIndex];
+ if (maxXY == 0) {
+ return filePath;
+ }
+ BitmapFactory.Options sizeOnlyOptions = new BitmapFactory.Options();
+ sizeOnlyOptions.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(filePath, sizeOnlyOptions);
+ final int myMaxXY = Math.max(sizeOnlyOptions.outHeight, sizeOnlyOptions.outWidth);
+ final int sampleSize = myMaxXY / maxXY;
+ Bitmap image;
+ if (sampleSize > 1) {
+ BitmapFactory.Options sampleOptions = new BitmapFactory.Options();
+ sampleOptions.inSampleSize = sampleSize;
+ image = BitmapFactory.decodeFile(filePath, sampleOptions);
+ } else {
+ image = BitmapFactory.decodeFile(filePath);
+ }
+ final BitmapDrawable scaledImage = ImageHelper.scaleBitmapTo(image, maxXY, maxXY);
+ image = null;
+ final String uploadFilename = getOutputImageFile().getPath();
+ ImageHelper.storeBitmap(scaledImage.getBitmap(), Bitmap.CompressFormat.JPEG, 75, uploadFilename);
+ return uploadFilename;
+ }
+
private void showFailure() {
- showToast(getResources().getString(R.string.err_aquire_image_failed));
+ showToast(getResources().getString(R.string.err_acquire_image_failed));
}
private void loadImagePreview() {
@@ -244,7 +302,6 @@ public class ImageSelectActivity extends AbstractActivity {
return;
}
- final ImageView imagePreview = (ImageView) findViewById(R.id.image_preview);
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = 8;
final Bitmap bitmap = BitmapFactory.decodeFile(imageUri.getPath(), bitmapOptions);
diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java
index 24f699e..07ff734 100644
--- a/main/src/cgeo/geocaching/ImagesActivity.java
+++ b/main/src/cgeo/geocaching/ImagesActivity.java
@@ -19,10 +19,6 @@ import java.util.List;
public class ImagesActivity extends AbstractActivity {
- private static final String EXTRAS_IMAGES = "images";
- private static final String EXTRAS_TYPE = "type";
- private static final String EXTRAS_GEOCODE = "geocode";
-
private boolean offline;
private ArrayList<Image> imageNames;
private ImagesList imagesList;
@@ -37,8 +33,8 @@ public class ImagesActivity extends AbstractActivity {
String geocode = null;
if (extras != null) {
- geocode = extras.getString(EXTRAS_GEOCODE);
- imgType = (ImageType) extras.getSerializable(EXTRAS_TYPE);
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
+ imgType = (ImageType) extras.getSerializable(Intents.EXTRA_TYPE);
}
if (extras == null || geocode == null) {
@@ -54,7 +50,7 @@ public class ImagesActivity extends AbstractActivity {
imagesList = new ImagesList(this, geocode);
- imageNames = extras.getParcelableArrayList(EXTRAS_IMAGES);
+ imageNames = extras.getParcelableArrayList(Intents.EXTRA_IMAGES);
if (CollectionUtils.isEmpty(imageNames)) {
showToast(res.getString(R.string.warn_load_images));
finish();
@@ -67,7 +63,7 @@ public class ImagesActivity extends AbstractActivity {
@Override
public void onStart() {
super.onStart();
- imagesList.loadImages(findViewById(R.id.spoiler_list), imageNames, imgType, offline);
+ imagesList.loadImages(findViewById(R.id.spoiler_list), imageNames, offline);
}
@Override
@@ -85,12 +81,12 @@ public class ImagesActivity extends AbstractActivity {
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)
- .putExtra(EXTRAS_TYPE, imageType);
+ .putExtra(Intents.EXTRA_GEOCODE, geocode)
+ .putExtra(Intents.EXTRA_TYPE, imageType);
// avoid forcing the array list as parameter type
final ArrayList<Image> arrayList = new ArrayList<Image>(logImages);
- logImgIntent.putParcelableArrayListExtra(EXTRAS_IMAGES, arrayList);
+ logImgIntent.putParcelableArrayListExtra(Intents.EXTRA_IMAGES, arrayList);
fromActivity.startActivity(logImgIntent);
}
diff --git a/main/src/cgeo/geocaching/Intents.java b/main/src/cgeo/geocaching/Intents.java
index 7f0a004..a700451 100644
--- a/main/src/cgeo/geocaching/Intents.java
+++ b/main/src/cgeo/geocaching/Intents.java
@@ -9,10 +9,11 @@ public class Intents {
private static final String PREFIX = "cgeo.geocaching.intent.extra.";
public static final String EXTRA_ADDRESS = PREFIX + "address";
- public static final String EXTRAS_COORDS = PREFIX + "coords";
+ public static final String EXTRA_COORDS = PREFIX + "coords";
public static final String EXTRA_COUNT = PREFIX + "count";
public static final String EXTRA_GEOCODE = PREFIX + "geocode";
public static final String EXTRA_GUID = PREFIX + "guid";
+ public static final String EXTRA_IMAGES = PREFIX + "images";
public static final String EXTRA_ID = PREFIX + "id";
public static final String EXTRA_KEYWORD = PREFIX + "keyword";
public static final String EXTRA_KEYWORD_SEARCH = PREFIX + "keyword_search";
@@ -23,6 +24,7 @@ public class Intents {
public static final String EXTRA_SEARCH = PREFIX + "search";
public static final String EXTRA_START_DIR = PREFIX + "start_dir";
public static final String EXTRA_TRACKING_CODE = PREFIX + "tracking_code";
+ public static final String EXTRA_TYPE = PREFIX + "type";
public static final String EXTRA_USERNAME = PREFIX + "username";
public static final String EXTRA_WAYPOINT_ID = PREFIX + "waypoint_id";
public static final String EXTRA_CACHELIST = PREFIX + "cache_list";
diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java
index b8983ba..7d8575b 100644
--- a/main/src/cgeo/geocaching/LogTrackableActivity.java
+++ b/main/src/cgeo/geocaching/LogTrackableActivity.java
@@ -1,5 +1,8 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.connector.gc.GCParser;
import cgeo.geocaching.connector.gc.Login;
import cgeo.geocaching.enumerations.LogType;
@@ -36,6 +39,14 @@ import java.util.Calendar;
import java.util.List;
public class LogTrackableActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent {
+
+ @InjectView(R.id.post) protected Button buttonPost;
+ @InjectView(R.id.type) protected Button typeButton;
+ @InjectView(R.id.date) protected Button dateButton;
+ @InjectView(R.id.tracking) protected EditText trackingEditText;
+ @InjectView(R.id.tweet) protected CheckBox tweetCheck;
+ @InjectView(R.id.tweet_box) protected LinearLayout tweetBox;
+
private List<LogType> possibleLogTypes = new ArrayList<LogType>();
private ProgressDialog waitDialog = null;
private String guid = null;
@@ -45,8 +56,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
private Calendar date = Calendar.getInstance();
private LogType typeSelected = LogType.getById(Settings.getTrackableAction());
private int attempts = 0;
- private CheckBox tweetCheck = null;
- private LinearLayout tweetBox = null;
private Trackable trackable;
private Handler showProgressHandler = new Handler() {
@@ -57,6 +66,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
};
private Handler loadDataHandler = new Handler() {
+
@Override
public void handleMessage(final Message msg) {
if (!possibleLogTypes.contains(typeSelected)) {
@@ -78,7 +88,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
gettingViewstate = false; // we're done, user can post log
- final Button buttonPost = (Button) findViewById(R.id.post);
buttonPost.setEnabled(true);
buttonPost.setOnClickListener(new PostListener());
@@ -104,17 +113,10 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
}
};
- public LogTrackableActivity() {
- super("c:geo-log-trackable");
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.touch);
- setTitle(res.getString(R.string.trackable_touch));
+ super.onCreate(savedInstanceState, R.layout.touch);
+ Views.inject(this);
// get parameters
final Bundle extras = getIntent().getExtras();
@@ -123,7 +125,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
guid = extras.getString(Intents.EXTRA_GUID);
if (StringUtils.isNotBlank(extras.getString(Intents.EXTRA_TRACKING_CODE))) {
- ((EditText) findViewById(R.id.tracking)).setText(extras.getString(Intents.EXTRA_TRACKING_CODE));
+ trackingEditText.setText(extras.getString(Intents.EXTRA_TRACKING_CODE));
}
}
@@ -146,11 +148,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
}
@Override
- public void onResume() {
- super.onResume();
- }
-
- @Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -184,7 +181,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
}
public void init() {
- final Button typeButton = (Button) findViewById(R.id.type);
registerForContextMenu(typeButton);
typeButton.setText(typeSelected.getL10n());
typeButton.setOnClickListener(new View.OnClickListener() {
@@ -194,23 +190,15 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
}
});
- final Button dateButton = (Button) findViewById(R.id.date);
dateButton.setOnClickListener(new DateListener());
setDate(date);
- if (tweetBox == null) {
- tweetBox = (LinearLayout) findViewById(R.id.tweet_box);
- }
- if (tweetCheck == null) {
- tweetCheck = (CheckBox) findViewById(R.id.tweet);
- }
tweetCheck.setChecked(true);
if (CollectionUtils.isEmpty(possibleLogTypes)) {
possibleLogTypes = Trackable.getPossibleLogTypes();
}
- final Button buttonPost = (Button) findViewById(R.id.post);
if (Login.isEmpty(viewstates)) {
buttonPost.setEnabled(false);
buttonPost.setOnTouchListener(null);
@@ -221,20 +209,17 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
buttonPost.setEnabled(true);
buttonPost.setOnClickListener(new PostListener());
}
- disableSuggestions((EditText) findViewById(R.id.tracking));
+ disableSuggestions(trackingEditText);
}
@Override
public void setDate(Calendar dateIn) {
date = dateIn;
- final Button dateButton = (Button) findViewById(R.id.date);
dateButton.setText(Formatter.formatShortDateVerbally(date.getTime().getTime()));
}
public void setType(LogType type) {
- final Button typeButton = (Button) findViewById(R.id.type);
-
typeSelected = type;
typeButton.setText(typeSelected.getL10n());
@@ -257,6 +242,8 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
private class PostListener implements View.OnClickListener {
+ protected EditText logEditText = (EditText) findViewById(R.id.log);
+
@Override
public void onClick(View arg0) {
if (!gettingViewstate) {
@@ -265,8 +252,8 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
Settings.setTrackableAction(typeSelected.id);
- final String tracking = ((EditText) findViewById(R.id.tracking)).getText().toString();
- final String log = ((EditText) findViewById(R.id.log)).getText().toString();
+ final String tracking = trackingEditText.getText().toString();
+ final String log = logEditText.getText().toString();
new PostLogThread(postLogHandler, tracking, log).start();
} else {
showToast(res.getString(R.string.err_log_load_data_still));
diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/MainActivity.java
index 5680ff3..7579a1d 100644
--- a/main/src/cgeo/geocaching/cgeo.java
+++ b/main/src/cgeo/geocaching/MainActivity.java
@@ -1,7 +1,9 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.activity.AbstractActivity;
-import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.gc.Login;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.StatusCode;
@@ -14,6 +16,9 @@ import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.RunnableWithArgument;
import cgeo.geocaching.utils.Version;
+import com.google.zxing.integration.android.IntentIntegrator;
+import com.google.zxing.integration.android.IntentResult;
+
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -31,11 +36,10 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
-import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.RelativeLayout;
+import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
@@ -45,14 +49,25 @@ import java.util.Comparator;
import java.util.List;
import java.util.Locale;
-public class cgeo extends AbstractActivity {
+public class MainActivity extends AbstractActivity {
+ @InjectView(R.id.user_info) protected TextView userInfoView;
+ @InjectView(R.id.nav_satellites) protected TextView navSatellites;
+ @InjectView(R.id.filter_button_title)protected TextView filterTitle;
+ @InjectView(R.id.map) protected ImageView findOnMap;
+ @InjectView(R.id.search_offline) protected ImageView findByOffline;
+ @InjectView(R.id.advanced_button) protected ImageView advanced;
+ @InjectView(R.id.any_button) protected ImageView any;
+ @InjectView(R.id.filter_button) protected ImageView filter;
+ @InjectView(R.id.nearest) protected ImageView nearestView;
+ @InjectView(R.id.nav_type) protected TextView navType ;
+ @InjectView(R.id.nav_accuracy) protected TextView navAccuracy ;
+ @InjectView(R.id.nav_location) protected TextView navLocation ;
+ @InjectView(R.id.offline_count) protected TextView countBubble ;
private static final String SCAN_INTENT = "com.google.zxing.client.android.SCAN";
- private static final int SCAN_REQUEST_CODE = 1;
public static final int SEARCH_REQUEST_CODE = 2;
private int version = 0;
- private TextView filterTitle = null;
private boolean cleanupRunning = false;
private int countBubbleCnt = 0;
private Geopoint addCoords = null;
@@ -67,17 +82,20 @@ public class cgeo extends AbstractActivity {
@Override
public void handleMessage(Message msg) {
- TextView userInfoView = (TextView) findViewById(R.id.user_info);
-
StringBuilder userInfo = new StringBuilder("geocaching.com").append(Formatter.SEPARATOR);
- if (Login.isActualLoginStatus()) {
- userInfo.append(Login.getActualUserName());
- if (Login.getActualCachesFound() >= 0) {
- userInfo.append(" (").append(String.valueOf(Login.getActualCachesFound())).append(')');
+ if (Settings.isGCConnectorActive()) {
+ if (Login.isActualLoginStatus()) {
+ userInfo.append(Login.getActualUserName());
+ if (Login.getActualCachesFound() >= 0) {
+ userInfo.append(" (").append(String.valueOf(Login.getActualCachesFound())).append(')');
+ }
+ userInfo.append(Formatter.SEPARATOR);
}
- userInfo.append(Formatter.SEPARATOR);
+ userInfo.append(Login.getActualStatus());
+ }
+ else {
+ userInfo.append("<disabled>"); // TODO this is just a quick fix. We need some better status implementation showing multiple connectors.
}
- userInfo.append(Login.getActualStatus());
userInfoView.setText(userInfo.toString());
}
@@ -109,7 +127,6 @@ public class cgeo extends AbstractActivity {
addCoords = app.currentGeo().getCoords();
- TextView navLocation = (TextView) findViewById(R.id.nav_location);
navLocation.setText(addText.toString());
}
} catch (Exception e) {
@@ -137,7 +154,6 @@ public class cgeo extends AbstractActivity {
satellitesFixed = data.getSatellitesFixed();
satellitesVisible = data.getSatellitesVisible();
- final TextView navSatellites = (TextView) findViewById(R.id.nav_satellites);
if (gpsEnabled) {
if (satellitesFixed > 0) {
navSatellites.setText(res.getString(R.string.loc_sat) + ": " + satellitesFixed + '/' + satellitesVisible);
@@ -169,13 +185,12 @@ public class cgeo extends AbstractActivity {
}
};
- public cgeo() {
- super("c:geo-main-screen");
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
+ // don't call the super implementation with the layout argument, as that would set the wrong theme
super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ Views.inject(this);
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
// If we had been open already, start from the last used activity.
@@ -183,33 +198,11 @@ public class cgeo extends AbstractActivity {
return;
}
- setContentView(R.layout.main);
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); // type to search
version = Version.getVersionCode(this);
Log.i("Starting " + getPackageName() + ' ' + version + " a.k.a " + Version.getVersionName(this));
- try {
- if (!Settings.isHelpShown()) {
- final RelativeLayout helper = (RelativeLayout) findViewById(R.id.helper);
- if (helper != null) {
- helper.setVisibility(View.VISIBLE);
- helper.setClickable(true);
- helper.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View view) {
- ActivityMixin.goManual(cgeo.this, "c:geo-intro");
- view.setVisibility(View.GONE);
- }
- });
- Settings.setHelpShown();
- }
- }
- } catch (Exception e) {
- // nothing
- }
-
init();
}
@@ -253,8 +246,7 @@ public class cgeo extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.main_options, menu);
+ getMenuInflater().inflate(R.menu.main_activity_options, menu);
return true;
}
@@ -302,25 +294,19 @@ public class cgeo extends AbstractActivity {
}
private void startScannerApplication() {
- Intent intent = new Intent(SCAN_INTENT);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); // when resuming our app, cancel this activity
- intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
- startActivityForResult(intent, SCAN_REQUEST_CODE);
+ IntentIntegrator integrator = new IntentIntegrator(this);
+ integrator.initiateScan(IntentIntegrator.QR_CODE_TYPES);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- if (requestCode == SCAN_REQUEST_CODE) {
- if (resultCode == RESULT_OK) {
- String scan = intent.getStringExtra("SCAN_RESULT");
- if (StringUtils.isBlank(scan)) {
- return;
- }
-
- SearchActivity.startActivityScan(scan, this);
- } else if (resultCode == RESULT_CANCELED) {
- // do nothing
+ IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
+ if (scanResult != null) {
+ String scan = scanResult.getContents();
+ if (StringUtils.isBlank(scan)) {
+ return;
}
+ SearchActivity.startActivityScan(scan, this);
} else if (requestCode == SEARCH_REQUEST_CODE) {
// SearchActivity activity returned without making a search
if (resultCode == RESULT_CANCELED) {
@@ -338,9 +324,6 @@ public class cgeo extends AbstractActivity {
}
private void setFilterTitle() {
- if (filterTitle == null) {
- filterTitle = (TextView) findViewById(R.id.filter_button_title);
- }
filterTitle.setText(Settings.getCacheType().getL10n());
}
@@ -358,7 +341,6 @@ public class cgeo extends AbstractActivity {
(new FirstLoginThread()).start();
}
- final View findOnMap = findViewById(R.id.map);
findOnMap.setClickable(true);
findOnMap.setOnClickListener(new OnClickListener() {
@Override
@@ -367,7 +349,6 @@ public class cgeo extends AbstractActivity {
}
});
- final View findByOffline = findViewById(R.id.search_offline);
findByOffline.setClickable(true);
findByOffline.setOnClickListener(new OnClickListener() {
@Override
@@ -379,12 +360,12 @@ public class cgeo extends AbstractActivity {
@Override
public boolean onLongClick(View v) {
- new StoredList.UserInterface(cgeo.this).promptForListSelection(R.string.list_title, new RunnableWithArgument<Integer>() {
+ new StoredList.UserInterface(MainActivity.this).promptForListSelection(R.string.list_title, new RunnableWithArgument<Integer>() {
@Override
public void run(Integer selectedListId) {
Settings.saveLastList(selectedListId);
- cgeocaches.startActivityOffline(cgeo.this);
+ cgeocaches.startActivityOffline(MainActivity.this);
}
});
return true;
@@ -392,7 +373,6 @@ public class cgeo extends AbstractActivity {
});
findByOffline.setLongClickable(true);
- final View advanced = findViewById(R.id.advanced_button);
advanced.setClickable(true);
advanced.setOnClickListener(new OnClickListener() {
@Override
@@ -401,7 +381,6 @@ public class cgeo extends AbstractActivity {
}
});
- final View any = findViewById(R.id.any_button);
any.setClickable(true);
any.setOnClickListener(new OnClickListener() {
@Override
@@ -410,7 +389,6 @@ public class cgeo extends AbstractActivity {
}
});
- final View filter = findViewById(R.id.filter_button);
filter.setClickable(true);
filter.setOnClickListener(new View.OnClickListener() {
@Override
@@ -501,7 +479,7 @@ public class cgeo extends AbstractActivity {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
cgData.resetNewlyCreatedDatabase();
- app.restoreDatabase(cgeo.this);
+ app.restoreDatabase(MainActivity.this);
}
})
.setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
@@ -519,10 +497,6 @@ public class cgeo extends AbstractActivity {
@Override
public void updateGeoData(final IGeoData geo) {
- final View nearestView = findViewById(R.id.nearest);
- final TextView navType = (TextView) findViewById(R.id.nav_type);
- final TextView navAccuracy = (TextView) findViewById(R.id.nav_accuracy);
- final TextView navLocation = (TextView) findViewById(R.id.nav_location);
try {
if (geo.getCoords() != null) {
if (!nearestView.isClickable()) {
@@ -583,7 +557,7 @@ public class cgeo extends AbstractActivity {
* unused here but needed since this method is referenced from XML layout
*/
public void cgeoFindOnMap(View v) {
- findViewById(R.id.map).setPressed(true);
+ findOnMap.setPressed(true);
CGeoMap.startActivityLiveMap(this);
}
@@ -596,7 +570,7 @@ public class cgeo extends AbstractActivity {
return;
}
- findViewById(R.id.nearest).setPressed(true);
+ nearestView.setPressed(true);
cgeocaches.startActivityNearest(this, app.currentGeo().getCoords());
}
@@ -605,7 +579,7 @@ public class cgeo extends AbstractActivity {
* unused here but needed since this method is referenced from XML layout
*/
public void cgeoFindByOffline(View v) {
- findViewById(R.id.search_offline).setPressed(true);
+ findByOffline.setPressed(true);
cgeocaches.startActivityOffline(this);
}
@@ -614,7 +588,7 @@ public class cgeo extends AbstractActivity {
* unused here but needed since this method is referenced from XML layout
*/
public void cgeoSearch(View v) {
- findViewById(R.id.advanced_button).setPressed(true);
+ advanced.setPressed(true);
startActivity(new Intent(this, SearchActivity.class));
}
@@ -623,7 +597,7 @@ public class cgeo extends AbstractActivity {
* unused here but needed since this method is referenced from XML layout
*/
public void cgeoPoint(View v) {
- findViewById(R.id.any_button).setPressed(true);
+ any.setPressed(true);
startActivity(new Intent(this, NavigateAnyPointActivity.class));
}
@@ -632,8 +606,8 @@ public class cgeo extends AbstractActivity {
* unused here but needed since this method is referenced from XML layout
*/
public void cgeoFilter(View v) {
- findViewById(R.id.filter_button).setPressed(true);
- findViewById(R.id.filter_button).performClick();
+ filter.setPressed(true);
+ filter.performClick();
}
/**
@@ -646,15 +620,10 @@ public class cgeo extends AbstractActivity {
private class CountBubbleUpdateThread extends Thread {
private Handler countBubbleHandler = new Handler() {
- private TextView countBubble = null;
@Override
public void handleMessage(Message msg) {
try {
- if (countBubble == null) {
- countBubble = (TextView) findViewById(R.id.offline_count);
- }
-
if (countBubbleCnt == 0) {
countBubble.setVisibility(View.GONE);
} else {
@@ -730,6 +699,10 @@ public class cgeo extends AbstractActivity {
return;
}
+ if (!Settings.isGCConnectorActive()) {
+ return;
+ }
+
// login
final StatusCode status = Login.login();
@@ -745,7 +718,7 @@ public class cgeo extends AbstractActivity {
// invoke settings activity to insert login details
if (status == StatusCode.NO_LOGIN_INFO_STORED) {
- SettingsActivity.startActivity(cgeo.this);
+ SettingsActivity.startActivity(MainActivity.this);
}
}
}
@@ -765,7 +738,7 @@ public class cgeo extends AbstractActivity {
addressObtaining = true;
try {
- final Geocoder geocoder = new Geocoder(cgeo.this, Locale.getDefault());
+ final Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
final Geopoint coords = app.currentGeo().getCoords();
addresses = geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1);
} catch (Exception e) {
diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
index efea819..61ba0e5 100644
--- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
+++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java
@@ -1,5 +1,8 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.geopoint.DistanceParser;
@@ -37,10 +40,38 @@ import android.widget.TextView;
import java.util.List;
public class NavigateAnyPointActivity extends AbstractActivity {
- private static final int MENU_DEFAULT_NAVIGATION = 2;
- private static final int MENU_NAVIGATE = 0;
- private static final int MENU_CACHES_AROUND = 5;
- private static final int MENU_CLEAR_HISTORY = 6;
+
+ @InjectView(R.id.buttonLatitude) protected Button latButton;
+ @InjectView(R.id.buttonLongitude) protected Button lonButton;
+ @InjectView(R.id.current) protected Button buttonCurrent;
+ @InjectView(R.id.historyList) protected ListView historyListView;
+ @InjectView(R.id.distanceUnit) protected Spinner distanceUnitSelector;
+ @InjectView(R.id.bearing) protected EditText bearingEditText;
+ @InjectView(R.id.distance) protected EditText distanceEditText;
+
+ private boolean changed = false;
+ private List<Destination> historyOfSearchedLocations;
+ private DestinationHistoryAdapter destinationHistoryAdapter;
+ private TextView historyFooter;
+
+ private static final int CONTEXT_MENU_NAVIGATE = 1;
+ private static final int CONTEXT_MENU_DELETE_WAYPOINT = 2;
+ private static final int CONTEXT_MENU_EDIT_WAYPOINT = 3;
+
+ private int contextMenuItemPosition;
+
+ private String distanceUnit = "";
+
+ protected static class ViewHolder {
+ @InjectView(R.id.simple_way_point_longitude) protected TextView longitude;
+ @InjectView(R.id.simple_way_point_latitude) protected TextView latitude;
+ @InjectView(R.id.date) protected TextView date;
+
+ public ViewHolder(View rowView) {
+ Views.inject(this, rowView);
+ rowView.setTag(this);
+ }
+ }
private static class DestinationHistoryAdapter extends ArrayAdapter<Destination> {
private LayoutInflater inflater = null;
@@ -52,29 +83,29 @@ public class NavigateAnyPointActivity extends AbstractActivity {
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
+ View rowView = convertView;
- Destination loc = getItem(position);
+ ViewHolder viewHolder;
+ if (rowView == null) {
+ rowView = getInflater().inflate(R.layout.simple_way_point, null);
+ viewHolder = new ViewHolder(rowView);
+ }
+ else {
+ viewHolder = (ViewHolder) rowView.getTag();
+ }
- View v = convertView;
+ fillViewHolder(viewHolder, getItem(position));
- if (v == null) {
- v = getInflater().inflate(R.layout.simple_way_point,
- null);
- }
- TextView longitude = (TextView) v
- .findViewById(R.id.simple_way_point_longitude);
- TextView latitude = (TextView) v
- .findViewById(R.id.simple_way_point_latitude);
- TextView date = (TextView) v.findViewById(R.id.date);
+ return rowView;
+ }
+ private void fillViewHolder(ViewHolder viewHolder, Destination loc) {
String lonString = loc.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE);
String latString = loc.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE);
- longitude.setText(lonString);
- latitude.setText(latString);
- date.setText(Formatter.formatShortDateTime(getContext(), loc.getDate()));
-
- return v;
+ viewHolder.longitude.setText(lonString);
+ viewHolder.latitude.setText(latString);
+ viewHolder.date.setText(Formatter.formatShortDateTime(getContext(), loc.getDate()));
}
private LayoutInflater getInflater() {
@@ -86,46 +117,22 @@ public class NavigateAnyPointActivity extends AbstractActivity {
}
}
- private Button latButton = null;
- private Button lonButton = null;
- private boolean changed = false;
- private List<Destination> historyOfSearchedLocations;
- private DestinationHistoryAdapter destionationHistoryAdapter;
- private ListView historyListView;
- private TextView historyFooter;
-
- private static final int CONTEXT_MENU_NAVIGATE = 1;
- private static final int CONTEXT_MENU_DELETE_WAYPOINT = 2;
- private static final int CONTEXT_MENU_EDIT_WAYPOINT = 3;
-
- private int contextMenuItemPosition;
-
- String distanceUnit = "";
-
- public NavigateAnyPointActivity() {
- super("c:geo-navigate-any");
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.point);
- setTitle(res.getString(R.string.search_destination));
+ super.onCreate(savedInstanceState, R.layout.point);
+ Views.inject(this);
createHistoryView();
-
init();
}
private void createHistoryView() {
- historyListView = (ListView) findViewById(R.id.historyList);
-
- final View pointControls = getLayoutInflater().inflate(
- R.layout.point_controls, null);
+ final View pointControls = getLayoutInflater().inflate(R.layout.point_controls, null);
historyListView.addHeaderView(pointControls, null, false);
+ // inject a second time to also find the dynamically expanded views above
+ Views.inject(this);
+
if (getHistoryOfSearchedLocations().isEmpty()) {
historyListView.addFooterView(getEmptyHistoryFooter(), null, false);
}
@@ -146,7 +153,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
historyListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
+ ContextMenuInfo menuInfo) {
menu.add(Menu.NONE, CONTEXT_MENU_NAVIGATE, Menu.NONE, res.getString(R.string.cache_menu_navigate));
menu.add(Menu.NONE, CONTEXT_MENU_EDIT_WAYPOINT, Menu.NONE, R.string.waypoint_edit);
menu.add(Menu.NONE, CONTEXT_MENU_DELETE_WAYPOINT, Menu.NONE, R.string.waypoint_delete);
@@ -190,19 +197,17 @@ public class NavigateAnyPointActivity extends AbstractActivity {
private TextView getEmptyHistoryFooter() {
if (historyFooter == null) {
- historyFooter = (TextView) getLayoutInflater().inflate(
- R.layout.caches_footer, null);
+ historyFooter = (TextView) getLayoutInflater().inflate(R.layout.caches_footer, null);
historyFooter.setText(R.string.search_history_empty);
}
return historyFooter;
}
private DestinationHistoryAdapter getDestionationHistoryAdapter() {
- if (destionationHistoryAdapter == null) {
- destionationHistoryAdapter = new DestinationHistoryAdapter(this,
- getHistoryOfSearchedLocations());
+ if (destinationHistoryAdapter == null) {
+ destinationHistoryAdapter = new DestinationHistoryAdapter(this, getHistoryOfSearchedLocations());
}
- return destionationHistoryAdapter;
+ return destinationHistoryAdapter;
}
private List<Destination> getHistoryOfSearchedLocations() {
@@ -229,25 +234,12 @@ public class NavigateAnyPointActivity extends AbstractActivity {
}
@Override
- public void onDestroy() {
- super.onDestroy();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- }
-
- @Override
public void onPause() {
geoDirHandler.stopGeo();
super.onPause();
}
private void init() {
- latButton = (Button) findViewById(R.id.buttonLatitude);
- lonButton = (Button) findViewById(R.id.buttonLongitude);
-
latButton.setOnClickListener(new CoordDialogListener());
lonButton.setOnClickListener(new CoordDialogListener());
@@ -257,19 +249,15 @@ public class NavigateAnyPointActivity extends AbstractActivity {
lonButton.setText(coords.format(GeopointFormatter.Format.LON_DECMINUTE));
}
- Button buttonCurrent = (Button) findViewById(R.id.current);
buttonCurrent.setOnClickListener(new CurrentListener());
getDestionationHistoryAdapter().notifyDataSetChanged();
- disableSuggestions((EditText) findViewById(R.id.distance));
+ disableSuggestions(distanceEditText);
initializeDistanceUnitSelector();
}
private void initializeDistanceUnitSelector() {
-
- Spinner distanceUnitSelector = (Spinner) findViewById(R.id.distanceUnit);
-
if (StringUtils.isBlank(distanceUnit)) {
if (Settings.isUseMetricUnits()) {
distanceUnitSelector.setSelection(0); // m
@@ -326,14 +314,8 @@ public class NavigateAnyPointActivity extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_DEFAULT_NAVIGATION, 0, NavigationAppFactory.getDefaultNavigationApplication().getName()).setIcon(R.drawable.ic_menu_compass); // default navigation tool
-
- menu.add(0, MENU_NAVIGATE, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
-
- menu.add(0, MENU_CACHES_AROUND, 0, res.getString(R.string.cache_menu_around)).setIcon(R.drawable.ic_menu_rotate); // caches around
-
- menu.add(0, MENU_CLEAR_HISTORY, 0, res.getString(R.string.search_clear_history)).setIcon(R.drawable.ic_menu_delete); // clear history
-
+ getMenuInflater().inflate(R.menu.navigate_any_point_activity_options, menu);
+ menu.findItem(R.id.menu_default_navigation).setTitle(NavigationAppFactory.getDefaultNavigationApplication().getName());
return true;
}
@@ -343,11 +325,11 @@ public class NavigateAnyPointActivity extends AbstractActivity {
try {
boolean visible = getDestination() != null;
- menu.findItem(MENU_NAVIGATE).setVisible(visible);
- menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(visible);
- menu.findItem(MENU_CACHES_AROUND).setVisible(visible);
+ menu.findItem(R.id.menu_navigate).setVisible(visible);
+ menu.findItem(R.id.menu_default_navigation).setVisible(visible);
+ menu.findItem(R.id.menu_caches_around).setVisible(visible);
- menu.findItem(MENU_CLEAR_HISTORY).setEnabled(!getHistoryOfSearchedLocations().isEmpty());
+ menu.findItem(R.id.menu_clear_history).setEnabled(!getHistoryOfSearchedLocations().isEmpty());
} catch (Exception e) {
// nothing
}
@@ -366,19 +348,19 @@ public class NavigateAnyPointActivity extends AbstractActivity {
}
switch (menuItem) {
- case MENU_DEFAULT_NAVIGATION:
+ case R.id.menu_default_navigation:
navigateTo();
return true;
- case MENU_CACHES_AROUND:
+ case R.id.menu_caches_around:
cachesAround();
return true;
- case MENU_CLEAR_HISTORY:
+ case R.id.menu_clear_history:
clearHistory();
return true;
- case MENU_NAVIGATE:
+ case R.id.menu_navigate:
NavigationAppFactory.showNavigationMenu(this, null, null, coords);
return true;
default:
@@ -402,7 +384,7 @@ public class NavigateAnyPointActivity extends AbstractActivity {
runOnUiThread(new Runnable() {
@Override
public void run() {
- destionationHistoryAdapter.notifyDataSetChanged();
+ destinationHistoryAdapter.notifyDataSetChanged();
}
});
}
@@ -495,10 +477,9 @@ public class NavigateAnyPointActivity extends AbstractActivity {
}
private Geopoint getDestination() {
-
- String bearingText = ((EditText) findViewById(R.id.bearing)).getText().toString();
+ String bearingText = bearingEditText.getText().toString();
// combine distance from EditText and distanceUnit saved from Spinner
- String distanceText = ((EditText) findViewById(R.id.distance)).getText().toString() + distanceUnit;
+ String distanceText = distanceEditText.getText().toString() + distanceUnit;
String latText = latButton.getText().toString();
String lonText = lonButton.getText().toString();
diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java
index 6fdff5a..946724f 100644
--- a/main/src/cgeo/geocaching/SearchActivity.java
+++ b/main/src/cgeo/geocaching/SearchActivity.java
@@ -1,5 +1,8 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
@@ -33,13 +36,25 @@ import java.util.Locale;
public class SearchActivity extends AbstractActivity {
- private static final int MENU_SEARCH_OWN_CACHES = 1;
- private EditText latEdit = null;
- private EditText lonEdit = null;
-
- public SearchActivity() {
- super("c:geo-search");
- }
+ @InjectView(R.id.buttonLatitude) protected Button buttonLatitude;
+ @InjectView(R.id.buttonLongitude) protected Button buttonLongitude;
+ @InjectView(R.id.search_coordinates) protected Button findByCoords;
+ @InjectView(R.id.search_address) protected Button findByAddress;
+ @InjectView(R.id.geocode) protected AutoCompleteTextView geocodeEdit;
+ @InjectView(R.id.display_geocode) protected Button displayByGeocode;
+ @InjectView(R.id.search_keyword) protected Button findByKeyword;
+ @InjectView(R.id.search_username) protected Button findByUserName;
+ @InjectView(R.id.search_owner) protected Button findByOwner;
+ @InjectView(R.id.trackable) protected AutoCompleteTextView trackable;
+ @InjectView(R.id.display_trackable) protected Button displayTrackable;
+ @InjectView(R.id.latitude) protected EditText latEdit;
+ @InjectView(R.id.longitude) protected EditText lonEdit;
+ @InjectView(R.id.keyword) protected EditText keywordEditText;
+ @InjectView(R.id.address) protected EditText addressEditText;
+ @InjectView(R.id.username) protected EditText userNameEditText;
+ @InjectView(R.id.owner) protected EditText ownerNameEditText;
+ @InjectView(R.id.geocode) protected EditText geocodeEditText;
+ @InjectView(R.id.trackable) protected EditText trackableEditText;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -64,8 +79,11 @@ public class SearchActivity extends AbstractActivity {
setTheme();
setContentView(R.layout.search);
+
+ // set title in code, as the activity needs a hard coded title due to the intent filters
setTitle(res.getString(R.string.search));
+ Views.inject(this);
init();
}
@@ -135,10 +153,8 @@ public class SearchActivity extends AbstractActivity {
private void init() {
Settings.getLogin();
- findViewById(R.id.buttonLatitude).setOnClickListener(new FindByCoordsAction());
- findViewById(R.id.buttonLongitude).setOnClickListener(new FindByCoordsAction());
-
- final Button findByCoords = (Button) findViewById(R.id.search_coordinates);
+ buttonLatitude.setOnClickListener(new FindByCoordsAction());
+ buttonLongitude.setOnClickListener(new FindByCoordsAction());
findByCoords.setOnClickListener(new FindByCoordsListener());
EditUtils.setActionListener((EditText) findViewById(R.id.address), new Runnable() {
@@ -148,11 +164,8 @@ public class SearchActivity extends AbstractActivity {
findByAddressFn();
}
});
-
- final Button findByAddress = (Button) findViewById(R.id.search_address);
findByAddress.setOnClickListener(new FindByAddressListener());
- final AutoCompleteTextView geocodeEdit = (AutoCompleteTextView) findViewById(R.id.geocode);
EditUtils.setActionListener(geocodeEdit, new Runnable() {
@Override
@@ -161,8 +174,6 @@ public class SearchActivity extends AbstractActivity {
}
});
addHistoryEntries(geocodeEdit, cgData.getRecentGeocodesForSearch());
-
- final Button displayByGeocode = (Button) findViewById(R.id.display_geocode);
displayByGeocode.setOnClickListener(new FindByGeocodeListener());
EditUtils.setActionListener((EditText) findViewById(R.id.keyword), new Runnable() {
@@ -172,8 +183,6 @@ public class SearchActivity extends AbstractActivity {
findByKeywordFn();
}
});
-
- final Button findByKeyword = (Button) findViewById(R.id.search_keyword);
findByKeyword.setOnClickListener(new FindByKeywordListener());
EditUtils.setActionListener((EditText) findViewById(R.id.username), new Runnable() {
@@ -183,8 +192,6 @@ public class SearchActivity extends AbstractActivity {
findByUsernameFn();
}
});
-
- final Button findByUserName = (Button) findViewById(R.id.search_username);
findByUserName.setOnClickListener(new FindByUsernameListener());
EditUtils.setActionListener((EditText) findViewById(R.id.owner), new Runnable() {
@@ -194,8 +201,6 @@ public class SearchActivity extends AbstractActivity {
findByOwnerFn();
}
});
-
- final Button findByOwner = (Button) findViewById(R.id.search_owner);
findByOwner.setOnClickListener(new OnClickListener() {
@Override
@@ -204,7 +209,6 @@ public class SearchActivity extends AbstractActivity {
}
});
- AutoCompleteTextView trackable = (AutoCompleteTextView) findViewById(R.id.trackable);
EditUtils.setActionListener(trackable, new Runnable() {
@Override
@@ -213,10 +217,7 @@ public class SearchActivity extends AbstractActivity {
}
});
addHistoryEntries(trackable, cgData.getTrackableCodes());
-
disableSuggestions(trackable);
-
- final Button displayTrackable = (Button) findViewById(R.id.display_trackable);
displayTrackable.setOnClickListener(new FindTrackableListener());
}
@@ -231,13 +232,6 @@ public class SearchActivity extends AbstractActivity {
@Override
public void updateGeoData(final IGeoData geo) {
try {
- if (latEdit == null) {
- latEdit = (EditText) findViewById(R.id.latitude);
- }
- if (lonEdit == null) {
- lonEdit = (EditText) findViewById(R.id.longitude);
- }
-
if (geo.getCoords() != null) {
if (latEdit != null) {
latEdit.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW));
@@ -261,8 +255,8 @@ public class SearchActivity extends AbstractActivity {
coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
@Override
public void update(Geopoint gp) {
- ((Button) findViewById(R.id.buttonLatitude)).setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
- ((Button) findViewById(R.id.buttonLongitude)).setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
+ buttonLatitude.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
+ buttonLongitude.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
}
});
coordsDialog.show();
@@ -278,16 +272,14 @@ public class SearchActivity extends AbstractActivity {
}
private void findByCoordsFn() {
- final Button latView = (Button) findViewById(R.id.buttonLatitude);
- final Button lonView = (Button) findViewById(R.id.buttonLongitude);
- final String latText = latView.getText().toString();
- final String lonText = lonView.getText().toString();
+ final String latText = buttonLatitude.getText().toString();
+ final String lonText = buttonLongitude.getText().toString();
if (StringUtils.isEmpty(latText) || StringUtils.isEmpty(lonText)) {
final IGeoData geo = app.currentGeo();
if (geo.getCoords() != null) {
- latView.setText(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE));
- lonView.setText(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE));
+ buttonLatitude.setText(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE));
+ buttonLongitude.setText(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE));
}
} else {
try {
@@ -308,7 +300,7 @@ public class SearchActivity extends AbstractActivity {
private void findByKeywordFn() {
// find caches by coordinates
- String keyText = ((EditText) findViewById(R.id.keyword)).getText().toString();
+ String keyText = keywordEditText.getText().toString();
if (StringUtils.isBlank(keyText)) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_keyword));
@@ -326,7 +318,7 @@ public class SearchActivity extends AbstractActivity {
}
private void findByAddressFn() {
- final String addText = ((EditText) findViewById(R.id.address)).getText().toString();
+ final String addText = addressEditText.getText().toString();
if (StringUtils.isBlank(addText)) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_address));
@@ -347,7 +339,7 @@ public class SearchActivity extends AbstractActivity {
}
public void findByUsernameFn() {
- final String usernameText = ((EditText) findViewById(R.id.username)).getText().toString();
+ final String usernameText = userNameEditText.getText().toString();
if (StringUtils.isBlank(usernameText)) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_user));
@@ -358,7 +350,7 @@ public class SearchActivity extends AbstractActivity {
}
private void findByOwnerFn() {
- findByOwnerFn(((EditText) findViewById(R.id.owner)).getText().toString());
+ findByOwnerFn(ownerNameEditText.getText().toString());
}
private void findByOwnerFn(String userName) {
@@ -381,7 +373,7 @@ public class SearchActivity extends AbstractActivity {
}
private void findByGeocodeFn() {
- final String geocodeText = ((EditText) findViewById(R.id.geocode)).getText().toString();
+ final String geocodeText = geocodeEditText.getText().toString();
if (StringUtils.isBlank(geocodeText) || geocodeText.equalsIgnoreCase("GC")) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_gccode));
@@ -400,7 +392,7 @@ public class SearchActivity extends AbstractActivity {
}
private void findTrackableFn() {
- final String trackableText = ((EditText) findViewById(R.id.trackable)).getText().toString();
+ final String trackableText = trackableEditText.getText().toString();
if (StringUtils.isBlank(trackableText) || trackableText.equalsIgnoreCase("TB")) {
helpDialog(res.getString(R.string.warn_search_help_title), res.getString(R.string.warn_search_help_tb));
@@ -414,13 +406,13 @@ public class SearchActivity extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_SEARCH_OWN_CACHES, 0, res.getString(R.string.search_own_caches)).setIcon(R.drawable.ic_menu_myplaces);
+ getMenuInflater().inflate(R.menu.search_activity_options, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == MENU_SEARCH_OWN_CACHES) {
+ if (item.getItemId() == R.id.menu_search_own_caches) {
findByOwnerFn(Settings.getUsername());
return true;
}
@@ -432,6 +424,6 @@ public class SearchActivity extends AbstractActivity {
searchIntent.setAction(Intent.ACTION_SEARCH).
putExtra(SearchManager.QUERY, scan).
putExtra(Intents.EXTRA_KEYWORD_SEARCH, false);
- fromActivity.startActivityForResult(searchIntent, cgeo.SEARCH_REQUEST_CODE);
+ fromActivity.startActivityForResult(searchIntent, MainActivity.SEARCH_REQUEST_CODE);
}
}
diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java
index b0540f2..4cef95e 100644
--- a/main/src/cgeo/geocaching/SearchResult.java
+++ b/main/src/cgeo/geocaching/SearchResult.java
@@ -114,7 +114,7 @@ public class SearchResult implements Parcelable {
public SearchResult(final Collection<Geocache> caches) {
this();
for (final Geocache cache : caches) {
- addCache(cache);
+ addAndPutInCache(cache);
}
}
@@ -199,7 +199,7 @@ public class SearchResult implements Parcelable {
(excludeMine && (cache.isOwner() || cache.isFound())) ||
(!cacheType.contains(cache));
if (!excludeCache) {
- result.addCache(cache);
+ result.addAndPutInCache(cache);
cachesForVote.add(cache);
}
}
@@ -229,7 +229,7 @@ public class SearchResult implements Parcelable {
}
/** Add the cache geocode to the search and store the cache in the CacheCache */
- public boolean addCache(final Geocache cache) {
+ public boolean addAndPutInCache(final Geocache cache) {
addGeocode(cache.getGeocode());
return cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
}
diff --git a/main/src/cgeo/geocaching/SelectMapfileActivity.java b/main/src/cgeo/geocaching/SelectMapfileActivity.java
index 9557f3e..aa6d46a 100644
--- a/main/src/cgeo/geocaching/SelectMapfileActivity.java
+++ b/main/src/cgeo/geocaching/SelectMapfileActivity.java
@@ -55,11 +55,6 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio
}
@Override
- protected void setTitle() {
- setTitle(res.getString(R.string.map_file_select_title));
- }
-
- @Override
public String getCurrentFile() {
return mapFile;
}
diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java
index 0c157e1..58bae64 100644
--- a/main/src/cgeo/geocaching/Settings.java
+++ b/main/src/cgeo/geocaching/Settings.java
@@ -40,8 +40,8 @@ import java.util.Locale;
*/
public final class Settings {
- private static final String KEY_TEMP_TOKEN_SECRET = "temp-token-secret";
- private static final String KEY_TEMP_TOKEN_PUBLIC = "temp-token-public";
+ private static final String KEY_TEMP_TWITTER_TOKEN_SECRET = "temp-token-secret";
+ private static final String KEY_TEMP_TWITTER_TOKEN_PUBLIC = "temp-token-public";
private static final String KEY_HELP_SHOWN = "helper";
private static final String KEY_ANYLONGITUDE = "anylongitude";
private static final String KEY_ANYLATITUDE = "anylatitude";
@@ -110,8 +110,14 @@ 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_GC_ACTIVE = "connectorGCActive";
private static final String KEY_CONNECTOR_OC_ACTIVE = "connectorOCActive";
- private static final String KEY_CONNECTOR_OC_USER = "connectorOCUser";
+ private static final String KEY_LOG_IMAGE_SCALE = "logImageScale";
+ private static final String KEY_OCDE_TOKEN_SECRET = "ocde_tokensecret";
+ private static final String KEY_OCDE_TOKEN_PUBLIC = "ocde_tokenpublic";
+ private static final String KEY_TEMP_OCDE_TOKEN_SECRET = "ocde-temp-token-secret";
+ private static final String KEY_TEMP_OCDE_TOKEN_PUBLIC = "ocde-temp-token-public";
+
private final static int unitsMetric = 1;
@@ -149,6 +155,7 @@ public final class Settings {
// maps
private static MapProvider mapProvider = null;
+ private static String cacheTwitterMessage = "I found [NAME] ([URL])";
private Settings() {
// this class is not to be instantiated;
@@ -161,8 +168,8 @@ public final class Settings {
final SharedPreferences old = cgeoapplication.getInstance().getSharedPreferences(oldPreferencesName, Context.MODE_PRIVATE);
final Editor e = sharedPrefs.edit();
- e.putString(KEY_TEMP_TOKEN_SECRET, old.getString(KEY_TEMP_TOKEN_SECRET, null));
- e.putString(KEY_TEMP_TOKEN_PUBLIC, old.getString(KEY_TEMP_TOKEN_PUBLIC, null));
+ e.putString(KEY_TEMP_TWITTER_TOKEN_SECRET, old.getString(KEY_TEMP_TWITTER_TOKEN_SECRET, null));
+ e.putString(KEY_TEMP_TWITTER_TOKEN_PUBLIC, old.getString(KEY_TEMP_TWITTER_TOKEN_PUBLIC, null));
e.putBoolean(KEY_HELP_SHOWN, old.getInt(KEY_HELP_SHOWN, 0) != 0);
e.putFloat(KEY_ANYLONGITUDE, old.getFloat(KEY_ANYLONGITUDE, 0));
e.putFloat(KEY_ANYLATITUDE, old.getFloat(KEY_ANYLATITUDE, 0));
@@ -185,7 +192,7 @@ public final class Settings {
e.putString(KEY_TWITTER_TOKEN_SECRET, old.getString(KEY_TWITTER_TOKEN_SECRET, null));
e.putString(KEY_TWITTER_TOKEN_PUBLIC, old.getString(KEY_TWITTER_TOKEN_PUBLIC, null));
e.putInt(KEY_VERSION, old.getInt(KEY_VERSION, 0));
- e.putBoolean(KEY_LOAD_DESCRIPTION, 0 != old.getInt(KEY_LOAD_DESCRIPTION, 0));
+ e.putBoolean(KEY_LOAD_DESCRIPTION, 0 != old.getInt(KEY_LOAD_DESCRIPTION, 1));
e.putBoolean(KEY_RATING_WANTED, old.getBoolean(KEY_RATING_WANTED, true));
e.putBoolean(KEY_ELEVATION_WANTED, old.getBoolean(KEY_ELEVATION_WANTED, true));
e.putBoolean(KEY_FRIENDLOGS_WANTED, old.getBoolean(KEY_FRIENDLOGS_WANTED, true));
@@ -282,6 +289,20 @@ public final class Settings {
});
}
+ public static boolean isGCConnectorActive() {
+ return sharedPrefs.getBoolean(KEY_CONNECTOR_GC_ACTIVE, true);
+ }
+
+ public static boolean setGCConnectorActive(final boolean isActive) {
+ return editSharedSettings(new PrefRunnable() {
+
+ @Override
+ public void edit(Editor edit) {
+ edit.putBoolean(KEY_CONNECTOR_GC_ACTIVE, isActive);
+ }
+ });
+ }
+
public static boolean isPremiumMember() {
// Basic Member, Premium Member, ???
String memberStatus = Settings.getMemberStatus();
@@ -323,26 +344,44 @@ public final class Settings {
});
}
- public static String getOCConnectorUserName() {
- String ocConnectorUser = sharedPrefs.getString(KEY_CONNECTOR_OC_USER, null);
- if (StringUtils.isBlank(ocConnectorUser)) {
- return StringUtils.EMPTY;
- }
- return ocConnectorUser;
+ public static String getOCDETokenPublic() {
+ return sharedPrefs.getString(KEY_OCDE_TOKEN_PUBLIC, "");
}
- public static boolean setOCConnectorUserName(final String userName) {
- return editSharedSettings(new PrefRunnable() {
+ public static String getOCDETokenSecret() {
+ return sharedPrefs.getString(KEY_OCDE_TOKEN_SECRET, "");
+ }
+
+ public static void setOCDETokens(final String tokenPublic, final String tokenSecret, boolean enableOcDe) {
+ 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);
+ edit.putString(KEY_OCDE_TOKEN_PUBLIC, tokenPublic);
+ edit.putString(KEY_OCDE_TOKEN_SECRET, tokenSecret);
+ if (tokenPublic != null) {
+ edit.remove(KEY_TEMP_OCDE_TOKEN_PUBLIC);
+ edit.remove(KEY_TEMP_OCDE_TOKEN_SECRET);
}
}
});
+ setOCConnectorActive(enableOcDe);
+ }
+
+ public static void setOCDETempTokens(final String tokenPublic, final String tokenSecret) {
+ editSharedSettings(new PrefRunnable() {
+ @Override
+ public void edit(Editor edit) {
+ edit.putString(KEY_TEMP_OCDE_TOKEN_PUBLIC, tokenPublic);
+ edit.putString(KEY_TEMP_OCDE_TOKEN_SECRET, tokenSecret);
+ }
+ });
+ }
+
+ public static ImmutablePair<String, String> getTempOCDEToken() {
+ String tokenPublic = sharedPrefs.getString(KEY_TEMP_OCDE_TOKEN_PUBLIC, null);
+ String tokenSecret = sharedPrefs.getString(KEY_TEMP_OCDE_TOKEN_SECRET, null);
+ return new ImmutablePair<String, String>(tokenPublic, tokenSecret);
}
public static boolean isGCvoteLogin() {
@@ -725,7 +764,7 @@ public final class Settings {
}
public static boolean isAutoLoadDescription() {
- return sharedPrefs.getBoolean(KEY_LOAD_DESCRIPTION, false);
+ return sharedPrefs.getBoolean(KEY_LOAD_DESCRIPTION, true);
}
public static void setAutoLoadDesc(final boolean autoLoad) {
@@ -1120,8 +1159,8 @@ public final class Settings {
edit.putString(KEY_TWITTER_TOKEN_PUBLIC, tokenPublic);
edit.putString(KEY_TWITTER_TOKEN_SECRET, tokenSecret);
if (tokenPublic != null) {
- edit.remove(KEY_TEMP_TOKEN_PUBLIC);
- edit.remove(KEY_TEMP_TOKEN_SECRET);
+ edit.remove(KEY_TEMP_TWITTER_TOKEN_PUBLIC);
+ edit.remove(KEY_TEMP_TWITTER_TOKEN_SECRET);
}
}
});
@@ -1132,15 +1171,15 @@ public final class Settings {
editSharedSettings(new PrefRunnable() {
@Override
public void edit(Editor edit) {
- edit.putString(KEY_TEMP_TOKEN_PUBLIC, tokenPublic);
- edit.putString(KEY_TEMP_TOKEN_SECRET, tokenSecret);
+ edit.putString(KEY_TEMP_TWITTER_TOKEN_PUBLIC, tokenPublic);
+ edit.putString(KEY_TEMP_TWITTER_TOKEN_SECRET, tokenSecret);
}
});
}
public static ImmutablePair<String, String> getTempToken() {
- String tokenPublic = sharedPrefs.getString(KEY_TEMP_TOKEN_PUBLIC, null);
- String tokenSecret = sharedPrefs.getString(KEY_TEMP_TOKEN_SECRET, null);
+ String tokenPublic = sharedPrefs.getString(KEY_TEMP_TWITTER_TOKEN_PUBLIC, null);
+ String tokenSecret = sharedPrefs.getString(KEY_TEMP_TWITTER_TOKEN_SECRET, null);
return new ImmutablePair<String, String>(tokenPublic, tokenSecret);
}
@@ -1424,4 +1463,32 @@ public final class Settings {
}
});
}
+
+ public static String getCacheTwitterMessage() {
+ // TODO make customizable from UI
+ return cacheTwitterMessage;
+ }
+
+ public static String getTrackableTwitterMessage() {
+ // TODO make customizable from UI
+ return "I touched [NAME] ([URL])!";
+ }
+
+ public static void setCacheTwitterMessage(final String message) {
+ cacheTwitterMessage = message;
+ }
+
+ public static int getLogImageScale() {
+ return sharedPrefs.getInt(KEY_LOG_IMAGE_SCALE, -1);
+ }
+
+ public static void setLogImageScale(final int scale) {
+ editSharedSettings(new PrefRunnable() {
+
+ @Override
+ public void edit(Editor edit) {
+ edit.putInt(KEY_LOG_IMAGE_SCALE, scale);
+ }
+ });
+ }
}
diff --git a/main/src/cgeo/geocaching/SettingsActivity.java b/main/src/cgeo/geocaching/SettingsActivity.java
index 0678617..aa163ad 100644
--- a/main/src/cgeo/geocaching/SettingsActivity.java
+++ b/main/src/cgeo/geocaching/SettingsActivity.java
@@ -5,6 +5,7 @@ import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.gc.Login;
+import cgeo.geocaching.connector.oc.OCAuthorizationActivity;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.files.SimpleDirChooser;
import cgeo.geocaching.maps.MapProviderFactory;
@@ -123,19 +124,9 @@ public class SettingsActivity extends AbstractActivity {
}
};
- public SettingsActivity() {
- super("c:geo-configuration");
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // init
-
- setTheme();
- setContentView(R.layout.init);
- setTitle(res.getString(R.string.settings));
+ super.onCreate(savedInstanceState, R.layout.init);
init();
}
@@ -169,14 +160,13 @@ public class SettingsActivity extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, 0, 0, res.getString(R.string.init_clear)).setIcon(R.drawable.ic_menu_delete);
-
+ getMenuInflater().inflate(R.menu.settings_activity_options, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == 0) {
+ if (item.getItemId() == R.id.menu_clear) {
((EditText) findViewById(R.id.username)).setText("");
((EditText) findViewById(R.id.password)).setText("");
((EditText) findViewById(R.id.passvote)).setText("");
@@ -223,6 +213,15 @@ public class SettingsActivity extends AbstractActivity {
public void init() {
// geocaching.com settings
+ final CheckBox gcCheck = (CheckBox) findViewById(R.id.gc_option);
+ gcCheck.setChecked(Settings.isGCConnectorActive());
+ gcCheck.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ Settings.setGCConnectorActive(gcCheck.isChecked());
+ }
+ });
final ImmutablePair<String, String> login = Settings.getLogin();
if (login != null) {
((EditText) findViewById(R.id.username)).setText(login.left);
@@ -252,10 +251,9 @@ public class SettingsActivity extends AbstractActivity {
Settings.setOCConnectorActive(ocCheck.isChecked());
}
});
- EditText ocUserEdit = (EditText) findViewById(R.id.oc_username);
- if (ocUserEdit.getText().length() == 0) {
- ocUserEdit.setText(Settings.getOCConnectorUserName());
- }
+
+ Button checkOCUser = (Button) findViewById(R.id.register_oc_de);
+ checkOCUser.setOnClickListener(new OCDEAuthorizeCgeoListener());
// gcvote settings
final ImmutablePair<String, String> gcvoteLogin = Settings.getGCvoteLogin();
@@ -839,7 +837,6 @@ 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);
@@ -853,7 +850,6 @@ 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());
@@ -861,7 +857,7 @@ public class SettingsActivity extends AbstractActivity {
Settings.setGpxImportDir(importNew);
Settings.setGpxExportDir(exportNew);
- return status1 && status2 && status3 && status4 && status5 && status6 && status7;
+ return status1 && status2 && status3 && status4 && status5 && status6;
}
/**
@@ -930,6 +926,15 @@ public class SettingsActivity extends AbstractActivity {
}
}
+ private class OCDEAuthorizeCgeoListener implements View.OnClickListener {
+
+ @Override
+ public void onClick(View v) {
+ Intent authIntent = new Intent(SettingsActivity.this, OCAuthorizationActivity.class);
+ startActivity(authIntent);
+ }
+ }
+
private class WebAuthListener implements View.OnClickListener {
@Override
diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java
index 005ee9e..a6a81d5 100644
--- a/main/src/cgeo/geocaching/StaticMapsActivity.java
+++ b/main/src/cgeo/geocaching/StaticMapsActivity.java
@@ -27,7 +27,6 @@ public class StaticMapsActivity extends AbstractActivity {
private static final String EXTRAS_WAYPOINT = "waypoint";
private static final String EXTRAS_DOWNLOAD = "download";
private static final String EXTRAS_GEOCODE = "geocode";
- private static final int MENU_REFRESH = 1;
private final List<Bitmap> maps = new ArrayList<Bitmap>();
private boolean download = false;
private Integer waypoint_id = null;
@@ -88,11 +87,7 @@ public class StaticMapsActivity extends AbstractActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.map_static);
- setTitle(res.getString(R.string.map_static_title));
+ super.onCreate(savedInstanceState, R.layout.map_static);
// get parameters
final Bundle extras = getIntent().getExtras();
@@ -163,13 +158,13 @@ public class StaticMapsActivity extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_REFRESH, 0, res.getString(R.string.cache_offline_refresh));
+ getMenuInflater().inflate(R.menu.static_maps_activity_options, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == MENU_REFRESH) {
+ if (item.getItemId() == R.id.menu_refresh) {
downloadStaticMaps();
restartActivity();
return true;
diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java
index cd88071..9a4c00b 100644
--- a/main/src/cgeo/geocaching/StaticMapsProvider.java
+++ b/main/src/cgeo/geocaching/StaticMapsProvider.java
@@ -10,7 +10,6 @@ import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.content.Context;
@@ -81,10 +80,6 @@ public class StaticMapsProvider {
}
public static void downloadMaps(Geocache cache) {
- if (cache == null) {
- Log.e("downloadMaps - missing input parameter cache");
- return;
- }
if ((!Settings.isStoreOfflineMaps() && !Settings.isStoreOfflineWpMaps()) || StringUtils.isBlank(cache.getGeocode())) {
return;
}
@@ -96,8 +91,8 @@ public class StaticMapsProvider {
}
// clean old and download static maps for waypoints if one is missing
- if (Settings.isStoreOfflineWpMaps() && CollectionUtils.isNotEmpty(cache.getWaypoints())) {
- for (Waypoint waypoint : cache.getWaypoints()) {
+ if (Settings.isStoreOfflineWpMaps()) {
+ for (final Waypoint waypoint : cache.getWaypoints()) {
if (!hasAllStaticMapsForWaypoint(cache.getGeocode(), waypoint)) {
refreshAllWpStaticMaps(cache, edge);
}
@@ -167,10 +162,6 @@ public class StaticMapsProvider {
}
public static void storeCachePreviewMap(final Geocache cache) {
- if (cache == null) {
- Log.e("storeCachePreviewMap - missing input parameter cache");
- return;
- }
final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA);
final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
@@ -183,12 +174,7 @@ public class StaticMapsProvider {
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;
+ return Math.max(displaySize.x, displaySize.y) - 25;
}
private static void downloadMaps(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int edge,
@@ -245,7 +231,7 @@ public class StaticMapsProvider {
/**
* Check if at least one map file exists for the given cache.
- *
+ *
* @param cache
* @return <code>true</code> if at least one map file exists; <code>false</code> otherwise
*/
@@ -268,7 +254,7 @@ public class StaticMapsProvider {
/**
* Checks if at least one map file exists for the given geocode and waypoint ID.
- *
+ *
* @param geocode
* @param waypoint
* @return <code>true</code> if at least one map file exists; <code>false</code> otherwise
@@ -287,7 +273,7 @@ public class StaticMapsProvider {
/**
* Checks if all map files exist for the given geocode and waypoint ID.
- *
+ *
* @param geocode
* @param waypoint
* @return <code>true</code> if all map files exist; <code>false</code> otherwise
@@ -326,5 +312,4 @@ public class StaticMapsProvider {
}
return null;
}
-
}
diff --git a/main/src/cgeo/geocaching/StoredList.java b/main/src/cgeo/geocaching/StoredList.java
index 5a6f132..c505e3c 100644
--- a/main/src/cgeo/geocaching/StoredList.java
+++ b/main/src/cgeo/geocaching/StoredList.java
@@ -12,7 +12,10 @@ import android.content.res.Resources;
import android.view.View;
import android.widget.EditText;
+import java.text.Collator;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
public class StoredList {
@@ -69,7 +72,7 @@ public class StoredList {
}
public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyMoveTargets, final int exceptListId) {
- final List<StoredList> lists = cgData.getLists();
+ final List<StoredList> lists = getSortedLists();
if (lists == null) {
return;
@@ -115,6 +118,19 @@ public class StoredList {
builder.create().show();
}
+ private static List<StoredList> getSortedLists() {
+ final Collator collator = Collator.getInstance();
+ final List<StoredList> lists = cgData.getLists();
+ Collections.sort(lists, new Comparator<StoredList>() {
+
+ @Override
+ public int compare(StoredList lhs, StoredList rhs) {
+ return collator.compare(lhs.getTitle(), rhs.getTitle());
+ }
+ });
+ return lists;
+ }
+
public void promptForListCreation(final RunnableWithArgument<Integer> runAfterwards) {
handleListNameInput("", R.string.list_dialog_create_title, R.string.list_dialog_create, new RunnableWithArgument<String>() {
@@ -176,4 +192,23 @@ public class StoredList {
});
}
}
+
+ /**
+ * Get the list title. This method is not public by intention to make clients use the {@link UserInterface} class.
+ *
+ * @return
+ */
+ protected String getTitle() {
+ return title;
+ }
+
+ /**
+ * Return the given list, if it is a concrete list. Return the default list otherwise.
+ */
+ public static int getConcreteList(int listId) {
+ if (listId == ALL_LIST_ID || listId == TEMPORARY_LIST_ID) {
+ return STANDARD_LIST_ID;
+ }
+ return listId;
+ }
}
diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java
index fea4521..80ffc09 100644
--- a/main/src/cgeo/geocaching/TrackableActivity.java
+++ b/main/src/cgeo/geocaching/TrackableActivity.java
@@ -1,5 +1,8 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.AbstractViewPagerActivity;
import cgeo.geocaching.connector.gc.GCParser;
@@ -8,6 +11,7 @@ import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
+import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.utils.BaseUtils;
@@ -26,7 +30,6 @@ 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;
@@ -56,8 +59,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
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;
@@ -108,16 +109,11 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
};
- public TrackableActivity() {
- super("c:geo-trackable-details");
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ super.onCreate(savedInstanceState, R.layout.trackable_activity);
- setTheme();
- setContentView(R.layout.trackable_activity);
+ // set title in code, as the activity needs a hard coded title due to the intent filters
setTitle(res.getString(R.string.trackable));
// get parameters
@@ -241,18 +237,17 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
@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
+ getMenuInflater().inflate(R.menu.trackable_activity, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case MENU_LOG_TOUCH:
+ case R.id.menu_log_touch:
LogTrackableActivity.startActivity(this, trackable);
return true;
- case MENU_BROWSER_TRACKABLE:
+ case R.id.menu_browser_trackable:
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl())));
return true;
default:
@@ -263,8 +258,8 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
@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()));
+ menu.findItem(R.id.menu_log_touch).setEnabled(StringUtils.isNotBlank(geocode) && trackable.isLoggable());
+ menu.findItem(R.id.menu_browser_trackable).setEnabled(StringUtils.isNotBlank(trackable.getUrl()));
}
return super.onPrepareOptionsMenu(menu);
}
@@ -392,24 +387,18 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
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;
+ protected class LogViewHolder {
+ @InjectView(R.id.added) protected TextView added ;
+ @InjectView(R.id.type) protected TextView type;
+ @InjectView(R.id.author) protected TextView author;
+ @InjectView(R.id.location) protected TextView location;
+ @InjectView(R.id.log) protected TextView text;
+ @InjectView(R.id.log_images) protected TextView images;
+ @InjectView(R.id.log_mark) protected ImageView marker;
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);
+ Views.inject(this, rowView);
+ rowView.setTag(this);
}
}
@@ -428,7 +417,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
LogViewHolder holder = (LogViewHolder) rowView.getTag();
if (null == holder) {
holder = new LogViewHolder(rowView);
- rowView.setTag(holder);
}
final LogEntry log = getItem(position);
@@ -440,7 +428,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
return view;
}
- protected void fillViewHolder(LogViewHolder holder, LogEntry log) {
+ protected void fillViewHolder(LogViewHolder holder, final LogEntry log) {
if (log.date > 0) {
holder.added.setText(Formatter.formatShortDate(log.date));
}
@@ -462,8 +450,8 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
});
}
- TextView logView = holder.log;
- logView.setMovementMethod(LinkMovementMethod.getInstance());
+ TextView logView = holder.text;
+ logView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
String logText = log.log;
if (BaseUtils.containsHtml(logText)) {
@@ -485,25 +473,18 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
statusMarker.setVisibility(View.GONE);
}
- // add LogImages
- LinearLayout logLayout = holder.logImages;
-
+ // images
if (log.hasLogImages()) {
-
- final ArrayList<Image> logImages = new ArrayList<Image>(log.getLogImages());
-
- final View.OnClickListener listener = new View.OnClickListener() {
+ holder.images.setText(log.getImageTitles());
+ holder.images.setVisibility(View.VISIBLE);
+ holder.images.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- ImagesActivity.startActivityLogImages(TrackableActivity.this, trackable.getGeocode(), logImages);
+ ImagesActivity.startActivityLogImages(TrackableActivity.this, trackable.getGeocode(), new ArrayList<Image>(log.getLogImages()));
}
- };
-
- 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);
+ });
+ } else {
+ holder.images.setVisibility(View.GONE);
}
holder.author.setOnClickListener(new UserActionsListener());
@@ -513,10 +494,20 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
public class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
+ @InjectView(R.id.goal_box) protected View goalBox;
+ @InjectView(R.id.goal) protected TextView goalTextView;
+ @InjectView(R.id.details_box) protected View detailsBox;
+ @InjectView(R.id.details) protected TextView detailsTextView;
+ @InjectView(R.id.image_box) protected View imageBox;
+ @InjectView(R.id.details_list) protected LinearLayout detailsList;
+ @InjectView(R.id.image) protected LinearLayout imageView;
+
@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));
+ Views.inject(this, view);
+
+ final CacheDetailsCreator details = new CacheDetailsCreator(TrackableActivity.this, detailsList);
// action bar icon
if (StringUtils.isNotBlank(trackable.getIconUrl())) {
@@ -610,27 +601,23 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
// 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());
+ goalBox.setVisibility(View.VISIBLE);
+ goalTextView.setVisibility(View.VISIBLE);
+ goalTextView.setText(Html.fromHtml(trackable.getGoal(), new HtmlImage(geocode, true, 0, false), null), TextView.BufferType.SPANNABLE);
+ goalTextView.setMovementMethod(AnchorAwareLinkMovementMethod.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());
+ detailsBox.setVisibility(View.VISIBLE);
+ detailsTextView.setVisibility(View.VISIBLE);
+ detailsTextView.setText(Html.fromHtml(trackable.getDetails(), new HtmlImage(geocode, true, 0, false), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE);
+ detailsTextView.setMovementMethod(AnchorAwareLinkMovementMethod.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);
-
+ imageBox.setVisibility(View.VISIBLE);
final ImageView trackableImage = (ImageView) inflater.inflate(R.layout.trackable_image, null);
trackableImage.setImageResource(R.drawable.image_not_loaded);
@@ -671,7 +658,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi
}
}.start();
- imgView.addView(trackableImage);
+ imageView.addView(trackableImage);
}
return view;
}
diff --git a/main/src/cgeo/geocaching/UsefulAppsActivity.java b/main/src/cgeo/geocaching/UsefulAppsActivity.java
index af643b3..d6e0ec8 100644
--- a/main/src/cgeo/geocaching/UsefulAppsActivity.java
+++ b/main/src/cgeo/geocaching/UsefulAppsActivity.java
@@ -1,79 +1,107 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.activity.AbstractActivity;
+import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
-import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
import android.widget.ImageView;
-import android.widget.LinearLayout;
+import android.widget.ListView;
import android.widget.TextView;
-import java.util.Locale;
-
public class UsefulAppsActivity extends AbstractActivity {
- private LinearLayout parentLayout;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ @InjectView(R.id.apps_list) protected ListView list;
- // init
- setTheme();
- setContentView(R.layout.useful_apps);
- setTitle(res.getString(R.string.helpers));
- parentLayout = (LinearLayout) findViewById(R.id.parent);
+ protected static class ViewHolder {
+ @InjectView(R.id.title) protected TextView title;
+ @InjectView(R.id.image) protected ImageView image;
+ @InjectView(R.id.description) protected TextView description;
- final Locale loc = Locale.getDefault();
- final String language = loc.getLanguage();
+ public ViewHolder(View rowView) {
+ Views.inject(this, rowView);
+ }
+ }
- final String tutorialUrl;
- if ("de".equalsIgnoreCase(language)) {
- tutorialUrl = "gnu.android.app.cgeomanual.de";
+ private static class HelperApp {
+ private final int titleId;
+ private final int descriptionId;
+ private final int iconId;
+ private final String packageName;
+
+ public HelperApp(final int title, final int description, final int icon, final String packageName) {
+ this.titleId = title;
+ this.descriptionId = description;
+ this.iconId = icon;
+ this.packageName = packageName;
}
- else {
- tutorialUrl = "gnu.android.app.cgeomanual.en";
+
+ private void installFromMarket(Activity activity) {
+ try {
+ Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageName));
+ marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ activity.startActivity(marketIntent);
+
+ } catch (Exception e) {
+ // market not available in standard emulator
+ }
}
- addApp(R.string.helper_manual_title, R.string.helper_manual_description, R.drawable.helper_manual, tutorialUrl);
- addApp(R.string.helper_calendar_title, R.string.helper_calendar_description, R.drawable.cgeo, "cgeo.calendar");
- addApp(R.string.helper_locus_title, R.string.helper_locus_description, R.drawable.helper_locus, "menion.android.locus");
- addApp(R.string.helper_gpsstatus_title, R.string.helper_gpsstatus_description, R.drawable.helper_gpsstatus, "com.eclipsim.gpsstatus2");
- addApp(R.string.helper_bluetoothgps_title, R.string.helper_bluetoothgps_description, R.drawable.helper_bluetoothgps, "googoo.android.btgps");
- addApp(R.string.helper_barcode_title, R.string.helper_barcode_description, R.drawable.helper_barcode, "com.google.zxing.client.android");
}
+ private static final HelperApp[] HELPER_APPS = {
+ new HelperApp(R.string.helper_calendar_title, R.string.helper_calendar_description, R.drawable.cgeo, "cgeo.calendar"),
+ new HelperApp(R.string.helper_pocketquery_title, R.string.helper_pocketquery_description, R.drawable.helper_pocketquery, "org.pquery"),
+ new HelperApp(R.string.helper_locus_title, R.string.helper_locus_description, R.drawable.helper_locus, "menion.android.locus"),
+ new HelperApp(R.string.helper_gpsstatus_title, R.string.helper_gpsstatus_description, R.drawable.helper_gpsstatus, "com.eclipsim.gpsstatus2"),
+ new HelperApp(R.string.helper_bluetoothgps_title, R.string.helper_bluetoothgps_description, R.drawable.helper_bluetoothgps, "googoo.android.btgps"),
+ new HelperApp(R.string.helper_barcode_title, R.string.helper_barcode_description, R.drawable.helper_barcode, "com.google.zxing.client.android"),
+ };
+
@Override
- public void onResume() {
- super.onResume();
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState, R.layout.useful_apps_activity);
- }
+ Views.inject(this);
- private void installFromMarket(String marketId) {
- try {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:" + marketId)));
- } catch (Exception e) {
- // market not available in standard emulator
- }
+ list.setAdapter(new ArrayAdapter<HelperApp>(this, R.layout.useful_apps_item, HELPER_APPS) {
+ @Override
+ public View getView(int position, View convertView, android.view.ViewGroup parent) {
+ View rowView = convertView;
+ if (null == rowView) {
+ rowView = getLayoutInflater().inflate(R.layout.useful_apps_item, null);
+ }
+ ViewHolder holder = (ViewHolder) rowView.getTag();
+ if (null == holder) {
+ holder = new ViewHolder(rowView);
+ rowView.setTag(holder);
+ }
+
+ final HelperApp app = getItem(position);
+ fillViewHolder(holder, app);
+ return rowView;
+ }
- finish();
- }
+ private void fillViewHolder(ViewHolder holder, HelperApp app) {
+ holder.title.setText(res.getString(app.titleId));
+ holder.image.setImageDrawable(res.getDrawable(app.iconId));
+ holder.description.setText(res.getString(app.descriptionId));
+ }
+ });
- private void addApp(final int titleId, final int descriptionId, final int imageId, final String marketUrl) {
- final LinearLayout layout = (LinearLayout) getLayoutInflater().inflate(R.layout.useful_apps_item, null);
- ((TextView) layout.findViewById(R.id.title)).setText(res.getString(titleId));
- ((ImageView) layout.findViewById(R.id.image)).setImageDrawable(res.getDrawable(imageId));
- ((TextView) layout.findViewById(R.id.description)).setText(res.getString(descriptionId));
- layout.findViewById(R.id.app_layout).setOnClickListener(new OnClickListener() {
+ list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
- public void onClick(View v) {
- installFromMarket(marketUrl);
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ HelperApp helperApp = HELPER_APPS[position];
+ helperApp.installFromMarket(UsefulAppsActivity.this);
}
});
- parentLayout.addView(layout);
}
-
}
diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java
index dce0fbf..e99da8d 100644
--- a/main/src/cgeo/geocaching/VisitCacheActivity.java
+++ b/main/src/cgeo/geocaching/VisitCacheActivity.java
@@ -1,38 +1,34 @@
package cgeo.geocaching;
-import cgeo.geocaching.connector.gc.GCParser;
-import cgeo.geocaching.connector.gc.Login;
+import cgeo.geocaching.connector.ILoggingManager;
+import cgeo.geocaching.connector.ImageResult;
+import cgeo.geocaching.connector.LogResult;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.LogTypeTrackable;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.gcvote.GCVote;
-import cgeo.geocaching.loaders.UrlLoader;
-import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.twitter.Twitter;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.dialog.DateDialog;
+import cgeo.geocaching.utils.AsyncTaskWithProgress;
+import cgeo.geocaching.utils.DateUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.ImmutablePair;
+import android.app.Activity;
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.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.Loader;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -51,7 +47,7 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
-public class VisitCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent, LoaderManager.LoaderCallbacks<String> {
+public class VisitCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent {
static final String EXTRAS_GEOCODE = "geocode";
static final String EXTRAS_ID = "id";
@@ -67,12 +63,10 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
private LayoutInflater inflater = null;
private Geocache cache = null;
- private ProgressDialog waitDialog = null;
private String cacheid = null;
private String geocode = null;
private String text = null;
private List<LogType> possibleLogTypes = new ArrayList<LogType>();
- private String[] viewstates = null;
private List<TrackableLog> trackables = null;
private Button postButton = null;
private CheckBox tweetCheck = null;
@@ -80,6 +74,8 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
private boolean tbChanged = false;
private SparseArray<TrackableLog> actionButtons;
+ private ILoggingManager loggingManager;
+
// Data to be saved while reconfiguring
private double rating;
private LogType typeSelected;
@@ -88,31 +84,16 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
private String imageDescription;
private Uri imageUri;
- @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));
- }
- @Override
- public void onLoaderReset(final Loader<String> loader) {
- // Nothing to do
- }
+ public void onLoadFinished() {
- @Override
- public void onLoadFinished(final Loader<String> loader, final String page) {
- if (page == null) {
+ if (loggingManager.hasLoaderError()) {
showErrorLoadingData();
return;
}
- viewstates = Login.getViewstates(page);
- trackables = GCParser.parseTrackableLog(page);
- possibleLogTypes = GCParser.parseTypes(page);
- possibleLogTypes.remove(LogType.UPDATE_COORDINATES);
+ trackables = loggingManager.getTrackables();
+ possibleLogTypes = loggingManager.getPossibleLogTypes();
if (possibleLogTypes.isEmpty()) {
showErrorLoadingData();
@@ -231,7 +212,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
if (!postButton.isEnabled()) {
return res.getString(R.string.log_post_not_possible);
}
- if (typeSelected != LogType.FOUND_IT || !Settings.isGCvoteLogin()) {
+ if (typeSelected != LogType.FOUND_IT || !Settings.isGCvoteLogin() || !cache.supportsGCVote()) {
return res.getString(R.string.log_post);
}
if (rating == 0) {
@@ -240,45 +221,9 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
return res.getString(R.string.log_post_rate) + " " + ratingTextValue(rating) + "*";
}
- private final Handler postLogHandler = new Handler() {
-
- @Override
- public void handleMessage(final Message msg) {
- if (waitDialog != null) {
- waitDialog.dismiss();
- }
-
- final StatusCode error = (StatusCode) msg.obj;
- if (error == StatusCode.NO_ERROR) {
- showToast(res.getString(R.string.info_log_posted));
- // No need to save the log when quitting if it has been posted.
- text = currentLogText();
- finish();
- } else if (error == StatusCode.LOG_SAVED) {
- showToast(res.getString(R.string.info_log_saved));
-
- if (waitDialog != null) {
- waitDialog.dismiss();
- }
-
- finish();
- } else {
- showToast(error.getErrorString(res));
- }
- }
- };
-
- public VisitCacheActivity() {
- super("c:geo-log");
- }
-
@Override
public void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.visit);
- setTitle(res.getString(R.string.log_new_log));
+ super.onCreate(savedInstanceState, R.layout.visit);
// Get parameters from intent and basic cache information from database
final Bundle extras = getIntent().getExtras();
@@ -333,7 +278,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
}
updatePostButtonText();
- setImageButtonText();
+ updateImageButton();
enablePostButton(false);
final Button typeButton = (Button) findViewById(R.id.type);
@@ -385,15 +330,25 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
});
- getSupportLoaderManager().initLoader(0, null, this);
+ loggingManager = cache.getLoggingManager(this);
+
+ loggingManager.init();
}
private void setDefaultValues() {
date = Calendar.getInstance();
rating = 0.0;
if (cache.isEventCache()) {
- if (cache.hasOwnLog(LogType.WILL_ATTEND)) {
- typeSelected = LogType.ATTENDED;
+ final Date eventDate = cache.getHiddenDate();
+ boolean expired = DateUtils.daysSince(eventDate.getTime()) > 0;
+
+ if (cache.hasOwnLog(LogType.WILL_ATTEND) || expired) {
+ if (cache.hasOwnLog(LogType.ATTENDED)) {
+ typeSelected = LogType.NOTE;
+ }
+ else {
+ typeSelected = LogType.ATTENDED;
+ }
}
else {
typeSelected = LogType.WILL_ATTEND;
@@ -407,8 +362,8 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
}
text = null;
- imageCaption = "";
- imageDescription = "";
+ imageCaption = StringUtils.EMPTY;
+ imageDescription = StringUtils.EMPTY;
imageUri = Uri.EMPTY;
}
@@ -423,7 +378,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
final EditText logView = (EditText) findViewById(R.id.log);
logView.setText(StringUtils.EMPTY);
- setImageButtonText();
+ updateImageButton();
showToast(res.getString(R.string.info_log_cleared));
}
@@ -463,7 +418,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- final boolean voteAvailable = Settings.isGCvoteLogin() && typeSelected == LogType.FOUND_IT && StringUtils.isNotBlank(cache.getGuid());
+ final boolean voteAvailable = Settings.isGCvoteLogin() && typeSelected == LogType.FOUND_IT && StringUtils.isNotBlank(cache.getGuid()) && cache.supportsGCVote();
menu.findItem(SUBMENU_VOTE).setVisible(voteAvailable);
return true;
@@ -549,81 +504,77 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
private class PostListener implements View.OnClickListener {
@Override
public void onClick(View arg0) {
- waitDialog = ProgressDialog.show(VisitCacheActivity.this, null,
- res.getString(StringUtils.isBlank(imageUri.getPath()) ? R.string.log_saving : R.string.log_saving_and_uploading), true);
- waitDialog.setCancelable(true);
-
- final Thread thread = new PostLogThread(postLogHandler, currentLogText());
- thread.start();
+ final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ?
+ R.string.log_saving :
+ R.string.log_saving_and_uploading);
+ new Poster(VisitCacheActivity.this, message).execute(currentLogText());
}
}
- private class PostLogThread extends Thread {
-
- private final Handler handler;
- private final String log;
+ private class Poster extends AsyncTaskWithProgress<String, StatusCode> {
- public PostLogThread(Handler handlerIn, String logIn) {
- super("Post log");
- handler = handlerIn;
- log = logIn;
+ public Poster(final Activity activity, final String progressMessage) {
+ super(activity, null, progressMessage, true);
}
@Override
- public void run() {
- final StatusCode status = postLogFn(log);
- handler.sendMessage(handler.obtainMessage(0, status));
- }
- }
-
- public StatusCode postLogFn(String log) {
-
- StatusCode result = StatusCode.LOG_POST_ERROR;
-
- try {
-
- final ImmutablePair<StatusCode, String> logResult = GCParser.postLog(geocode, cacheid, viewstates, typeSelected,
- date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE),
- log, trackables);
-
- result = logResult.left;
-
- if (logResult.left == StatusCode.NO_ERROR) {
- final LogEntry logNow = new LogEntry(date, typeSelected, log);
-
- cache.getLogs().add(0, logNow);
-
- if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED) {
- cache.setFound(true);
+ protected StatusCode doInBackgroundInternal(final String[] logTexts) {
+ final String log = logTexts[0];
+ try {
+ final LogResult logResult = loggingManager.postLog(cache, typeSelected, date, log, trackables);
+
+ if (logResult.getPostLogResult() == StatusCode.NO_ERROR) {
+ final LogEntry logNow = new LogEntry(date, typeSelected, log);
+
+ cache.getLogs().add(0, logNow);
+
+ if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED) {
+ cache.setFound(true);
+ }
+
+ cgData.saveChangedCache(cache);
+ cgData.clearLogOffline(geocode);
+
+ if (typeSelected == LogType.FOUND_IT) {
+ if (tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) {
+ Twitter.postTweetCache(geocode);
+ }
+ GCVote.setRating(cache, rating);
+ }
+
+ if (StringUtils.isNotBlank(imageUri.getPath())) {
+ ImageResult imageResult = loggingManager.postLogImage(logResult.getLogId(), imageCaption, imageDescription, imageUri);
+ final String uploadedImageUrl = imageResult.getImageUri();
+ if (StringUtils.isNotEmpty(uploadedImageUrl)) {
+ logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription));
+ cgData.saveChangedCache(cache);
+ }
+ return imageResult.getPostResult();
+ }
}
- cgData.saveChangedCache(cache);
- }
-
- if (logResult.left == StatusCode.NO_ERROR) {
- cgData.clearLogOffline(geocode);
- }
-
- if (logResult.left == StatusCode.NO_ERROR && typeSelected == LogType.FOUND_IT && Settings.isUseTwitter()
- && Settings.isTwitterLoginValid()
- && tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) {
- Twitter.postTweetCache(geocode);
+ return logResult.getPostLogResult();
+ } catch (Exception e) {
+ Log.e("cgeovisit.postLogFn", e);
}
- if (logResult.left == StatusCode.NO_ERROR && typeSelected == LogType.FOUND_IT && Settings.isGCvoteLogin()) {
- GCVote.setRating(cache, rating);
- }
+ return StatusCode.LOG_POST_ERROR;
+ }
- if (logResult.left == StatusCode.NO_ERROR && StringUtils.isNotBlank(imageUri.getPath())) {
- result = GCParser.uploadLogImage(logResult.right, imageCaption, imageDescription, imageUri);
+ @Override
+ protected void onPostExecuteInternal(final StatusCode status) {
+ if (status == StatusCode.NO_ERROR) {
+ showToast(res.getString(R.string.info_log_posted));
+ // No need to save the log when quitting if it has been posted.
+ text = currentLogText();
+ finish();
+ } else if (status == StatusCode.LOG_SAVED) {
+ showToast(res.getString(R.string.info_log_saved));
+ finish();
+ } else {
+ showToast(status.getErrorString(res));
}
-
- return result;
- } catch (Exception e) {
- Log.e("cgeovisit.postLogFn", e);
}
-
- return StatusCode.LOG_POST_ERROR;
}
private void saveLog(final boolean force) {
@@ -677,16 +628,19 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
private void selectLogType() {
+ // use a local copy of the possible types, as that one might be modified in the background by the loader
+ final ArrayList<LogType> possible = new ArrayList<LogType>(possibleLogTypes);
+
Builder alert = new AlertDialog.Builder(this);
- String[] choices = new String[possibleLogTypes.size()];
+ String[] choices = new String[possible.size()];
for (int i = 0; i < choices.length; i++) {
- choices[i] = possibleLogTypes.get(i).getL10n();
+ choices[i] = possible.get(i).getL10n();
}
- alert.setSingleChoiceItems(choices, possibleLogTypes.indexOf(typeSelected), new OnClickListener() {
+ alert.setSingleChoiceItems(choices, possible.indexOf(typeSelected), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int position) {
- setType(possibleLogTypes.get(position));
+ setType(possible.get(position));
dialog.dismiss();
}
});
@@ -734,14 +688,19 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
// Image capture failed, advise user
showToast(getResources().getString(R.string.err_select_logimage_failed));
}
- setImageButtonText();
+ updateImageButton();
}
}
- private void setImageButtonText() {
+ private void updateImageButton() {
final Button imageButton = (Button) findViewById(R.id.image_btn);
- imageButton.setText(StringUtils.isNotBlank(imageUri.getPath()) ?
+ if (cache.supportsLogImages()) {
+ imageButton.setVisibility(View.VISIBLE);
+ imageButton.setText(StringUtils.isNotBlank(imageUri.getPath()) ?
res.getString(R.string.log_image_edit) : res.getString(R.string.log_image_attach));
+ } else {
+ imageButton.setVisibility(View.GONE);
+ }
}
}
diff --git a/main/src/cgeo/geocaching/Waypoint.java b/main/src/cgeo/geocaching/Waypoint.java
index 48c9bc5..e39d26a 100644
--- a/main/src/cgeo/geocaching/Waypoint.java
+++ b/main/src/cgeo/geocaching/Waypoint.java
@@ -275,7 +275,8 @@ public class Waypoint implements IWaypoint, Comparable<Waypoint> {
if (coords != null) {
hash = coords.hashCode();
}
- hash = hash ^ waypointType.markerId;
+ hash ^= waypointType.markerId;
return (int) hash;
}
+
}
diff --git a/main/src/cgeo/geocaching/WaypointPopup.java b/main/src/cgeo/geocaching/WaypointPopup.java
index 766d43d..b77fc0c 100644
--- a/main/src/cgeo/geocaching/WaypointPopup.java
+++ b/main/src/cgeo/geocaching/WaypointPopup.java
@@ -1,7 +1,11 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.utils.Log;
@@ -17,16 +21,23 @@ import android.widget.LinearLayout;
import android.widget.TextView;
public class WaypointPopup extends AbstractPopupActivity {
+ @InjectView(R.id.actionbar_title) protected TextView actionBarTitle;
+ @InjectView(R.id.waypoint_details_list) protected LinearLayout waypointDetailsLayout;
+ @InjectView(R.id.edit) protected Button buttonEdit;
+ @InjectView(R.id.details_list) protected LinearLayout cacheDetailsLayout;
+
private int waypointId = 0;
private Waypoint waypoint = null;
+ private TextView waypointDistance = null;
public WaypointPopup() {
- super("c:geo-waypoint-info", R.layout.waypoint_popup);
+ super(R.layout.waypoint_popup);
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ Views.inject(this);
// get parameters
final Bundle extras = getIntent().getExtras();
if (extras != null) {
@@ -35,6 +46,14 @@ public class WaypointPopup extends AbstractPopupActivity {
}
@Override
+ public void onUpdateGeoData(IGeoData geo) {
+ if (geo.getCoords() != null && waypoint != null && waypoint.getCoords() != null) {
+ waypointDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(waypoint.getCoords())));
+ waypointDistance.bringToFront();
+ }
+ }
+
+ @Override
protected void init() {
super.init();
waypoint = cgData.loadWaypoint(waypointId);
@@ -45,17 +64,16 @@ public class WaypointPopup extends AbstractPopupActivity {
setTitle(waypoint.getGeocode());
}
- // actionbar icon
- ((TextView) findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(waypoint.getWaypointType().markerId), null, null, null);
+ actionBarTitle.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(waypoint.getWaypointType().markerId), null, null, null);
- //Start filling waypoint details
- details = new CacheDetailsCreator(this, (LinearLayout) findViewById(R.id.waypoint_details_list));
+ details = new CacheDetailsCreator(this, waypointDetailsLayout);
//Waypoint geocode
details.add(R.string.cache_geocode, waypoint.getPrefix() + waypoint.getGeocode().substring(2));
+ details.addDistance(waypoint, waypointDistance);
+ waypointDistance = details.getValueView();
+ details.add(R.string.waypoint_note, waypoint.getNote());
- // Edit Button
- final Button buttonEdit = (Button) findViewById(R.id.edit);
buttonEdit.setOnClickListener(new OnClickListener() {
@Override
@@ -65,8 +83,7 @@ public class WaypointPopup extends AbstractPopupActivity {
}
});
- //Start filling cache details
- details = new CacheDetailsCreator(this, (LinearLayout) findViewById(R.id.details_list));
+ details = new CacheDetailsCreator(this, cacheDetailsLayout);
details.add(R.string.cache_name, cache.getName());
addCacheDetails();
diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java
index 557665e..964ef96 100644
--- a/main/src/cgeo/geocaching/activity/AbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.activity;
+import butterknife.Views;
+
import cgeo.geocaching.Settings;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
@@ -14,22 +16,15 @@ import android.widget.EditText;
public abstract class AbstractActivity extends FragmentActivity implements IAbstractActivity {
- final private String helpTopic;
-
protected cgeoapplication app = null;
protected Resources res = null;
private boolean keepScreenOn = false;
protected AbstractActivity() {
- this(null);
- }
-
- protected AbstractActivity(final String helpTopic) {
- this.helpTopic = helpTopic;
+ this(false);
}
- protected AbstractActivity(final String helpTopic, final boolean keepScreenOn) {
- this(helpTopic);
+ protected AbstractActivity(final boolean keepScreenOn) {
this.keepScreenOn = keepScreenOn;
}
@@ -38,20 +33,15 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
ActivityMixin.goHome(this);
}
- @Override
- public void goManual(final View view) {
- ActivityMixin.goManual(this, helpTopic);
- }
-
- final public void setTitle(final String title) {
+ final protected void setTitle(final String title) {
ActivityMixin.setTitle(this, title);
}
- final public void showProgress(final boolean show) {
+ final protected void showProgress(final boolean show) {
ActivityMixin.showProgress(this, show);
}
- final public void setTheme() {
+ final protected void setTheme() {
ActivityMixin.setTheme(this);
}
@@ -70,22 +60,14 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
ActivityMixin.helpDialog(this, title, message);
}
- public final void helpDialog(final String title, final String message, final Drawable icon) {
+ protected final void helpDialog(final String title, final String message, final Drawable icon) {
ActivityMixin.helpDialog(this, title, message, icon);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- // init
- res = this.getResources();
- app = (cgeoapplication) this.getApplication();
-
- // Restore cookie store if needed
- Cookies.restoreCookieStore(Settings.getCookieStore());
-
- ActivityMixin.keepScreenOn(this, keepScreenOn);
+ initializeCommonFields();
}
protected static void disableSuggestions(final EditText edit) {
@@ -128,4 +110,34 @@ public abstract class AbstractActivity extends FragmentActivity implements IAbst
editText.setSelection(newCursor, newCursor);
}
+ protected void onCreate(final Bundle savedInstanceState, final int resourceLayoutID) {
+ super.onCreate(savedInstanceState);
+
+ initializeCommonFields();
+
+ // non declarative part of layout
+ setTheme();
+ setContentView(resourceLayoutID);
+
+ // create view variables
+ Views.inject(this);
+ }
+
+ private void initializeCommonFields() {
+ // initialize commonly used members
+ res = this.getResources();
+ app = (cgeoapplication) this.getApplication();
+
+ // only needed in some activities, but implemented in super class nonetheless
+ Cookies.restoreCookieStore(Settings.getCookieStore());
+ ActivityMixin.keepScreenOn(this, keepScreenOn);
+ }
+
+ @Override
+ public void setContentView(int layoutResID) {
+ super.setContentView(layoutResID);
+
+ // initialize the action bar title with the activity title for single source
+ ActivityMixin.setTitle(this, getTitle());
+ }
}
diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
index f96a769..47c747f 100644
--- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
@@ -12,35 +12,24 @@ import android.view.View;
public abstract class AbstractListActivity extends FragmentListActivity implements
IAbstractActivity {
- private String helpTopic;
private boolean keepScreenOn = false;
protected cgeoapplication app = null;
protected Resources res = null;
protected AbstractListActivity() {
- this(null);
+ this(false);
}
protected AbstractListActivity(final boolean keepScreenOn) {
- this(null);
this.keepScreenOn = keepScreenOn;
}
- protected AbstractListActivity(final String helpTopic) {
- this.helpTopic = helpTopic;
- }
-
@Override
final public void goHome(View view) {
ActivityMixin.goHome(this);
}
- @Override
- public void goManual(View view) {
- ActivityMixin.goManual(this, helpTopic);
- }
-
final public void showProgress(final boolean show) {
ActivityMixin.showProgress(this, show);
}
@@ -71,7 +60,10 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ initializeCommonFields();
+ }
+ private void initializeCommonFields() {
// init
res = this.getResources();
app = (cgeoapplication) this.getApplication();
@@ -79,7 +71,7 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
ActivityMixin.keepScreenOn(this, keepScreenOn);
}
- final public void setTitle(final String title) {
+ final protected void setTitle(final String title) {
ActivityMixin.setTitle(this, title);
}
@@ -87,4 +79,20 @@ public abstract class AbstractListActivity extends FragmentListActivity implemen
public void invalidateOptionsMenuCompatible() {
Compatibility.invalidateOptionsMenu(this);
}
+
+ public void onCreate(Bundle savedInstanceState, int resourceLayoutID) {
+ super.onCreate(savedInstanceState);
+ initializeCommonFields();
+
+ setTheme();
+ setContentView(resourceLayoutID);
+ }
+
+ @Override
+ public void setContentView(int layoutResID) {
+ super.setContentView(layoutResID);
+
+ // initialize action bar title with activity title
+ ActivityMixin.setTitle(this, getTitle());
+ }
}
diff --git a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
index 366a59d..e0c304a 100644
--- a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
@@ -14,6 +14,7 @@ import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
+import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.HashMap;
@@ -29,10 +30,6 @@ import java.util.Map;
*/
public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends AbstractActivity {
- protected AbstractViewPagerActivity(String helpTopic) {
- super(helpTopic);
- }
-
/**
* A {@link List} of all available pages.
*
@@ -95,12 +92,12 @@ public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends
private class ViewPagerAdapter extends PagerAdapter implements TitleProvider {
@Override
- public void destroyItem(View container, int position, Object object) {
+ public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
- public void finishUpdate(View container) {
+ public void finishUpdate(ViewGroup container) {
}
@Override
@@ -109,7 +106,7 @@ public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends
}
@Override
- public Object instantiateItem(View container, int position) {
+ public Object instantiateItem(ViewGroup container, int position) {
final Page page = pageOrder.get(position);
PageViewCreator creator = viewCreators.get(page);
@@ -150,7 +147,7 @@ public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends
}
@Override
- public void startUpdate(View arg0) {
+ public void startUpdate(ViewGroup arg0) {
}
@Override
diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java
index c97cb9a..12ab0be 100644
--- a/main/src/cgeo/geocaching/activity/ActivityMixin.java
+++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java
@@ -1,15 +1,14 @@
package cgeo.geocaching.activity;
+import cgeo.geocaching.MainActivity;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgeo;
import cgeo.geocaching.compatibility.Compatibility;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
import android.app.AlertDialog;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -21,34 +20,17 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
-import gnu.android.app.appmanualclient.AppManualReaderClient;
-
public final class ActivityMixin {
public final static void goHome(final Activity fromActivity) {
- final Intent intent = new Intent(fromActivity, cgeo.class);
+ final Intent intent = new Intent(fromActivity, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
fromActivity.startActivity(intent);
fromActivity.finish();
}
- public static void goManual(final Context context, final String helpTopic) {
- if (StringUtils.isBlank(helpTopic)) {
- return;
- }
- try {
- AppManualReaderClient.openManual(
- "c-geo",
- helpTopic,
- context,
- "http://manual.cgeo.org/");
- } catch (Exception e) {
- // nothing
- }
- }
-
- public static void setTitle(final Activity activity, final String text) {
+ public static void setTitle(final Activity activity, final CharSequence text) {
if (StringUtils.isBlank(text)) {
return;
}
diff --git a/main/src/cgeo/geocaching/activity/IAbstractActivity.java b/main/src/cgeo/geocaching/activity/IAbstractActivity.java
index 04709c6..61c218b 100644
--- a/main/src/cgeo/geocaching/activity/IAbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/IAbstractActivity.java
@@ -6,8 +6,6 @@ public interface IAbstractActivity {
public void goHome(View view);
- public void goManual(View view);
-
public void showToast(String text);
public void showShortToast(String text);
diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java
index c95e8b4..ef56f87 100644
--- a/main/src/cgeo/geocaching/apps/AbstractApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractApp.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.apps;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.cgeo;
+import cgeo.geocaching.MainActivity;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.ProcessUtils;
@@ -29,7 +29,7 @@ public abstract class AbstractApp implements App {
if (ProcessUtils.isInstalled(packageName)) {
return true;
}
- return cgeo.isIntentAvailable(intent);
+ return MainActivity.isIntentAvailable(intent);
}
protected Intent getLaunchIntent() {
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
index 4811916..47010df 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
@@ -3,7 +3,7 @@ package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgeonavigate;
+import cgeo.geocaching.CompassActivity;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.ui.Formatter;
@@ -22,18 +22,18 @@ class CompassApp extends AbstractPointNavigationApp {
@Override
public void navigate(Activity activity, Geopoint coords) {
- cgeonavigate.startActivity(activity, getString(R.string.navigation_direct_navigation), getString(R.string.navigation_target), coords, null);
+ CompassActivity.startActivity(activity, getString(R.string.navigation_direct_navigation), getString(R.string.navigation_target), coords, null);
}
@Override
public void navigate(Activity activity, Waypoint waypoint) {
- cgeonavigate.startActivity(activity, waypoint.getPrefix() + "/" + waypoint.getLookup(), waypoint.getName(), waypoint.getCoords(), null,
+ CompassActivity.startActivity(activity, waypoint.getPrefix() + "/" + waypoint.getLookup(), waypoint.getName(), waypoint.getCoords(), null,
waypoint.getWaypointType().getL10n());
}
@Override
public void navigate(Activity activity, Geocache cache) {
- cgeonavigate.startActivity(activity, cache.getGeocode(), cache.getName(), cache.getCoords(), null,
+ CompassActivity.startActivity(activity, cache.getGeocode(), cache.getName(), cache.getCoords(), null,
Formatter.formatCacheInfoShort(cache));
}
diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java
index 28485a5..2ef5b27 100644
--- a/main/src/cgeo/geocaching/cgData.java
+++ b/main/src/cgeo/geocaching/cgData.java
@@ -33,6 +33,7 @@ import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
@@ -85,7 +86,7 @@ public class cgData {
private static int[] cacheColumnIndex;
private static CacheCache cacheCache = new CacheCache();
private static SQLiteDatabase database = null;
- private static final int dbVersion = 66;
+ private static final int dbVersion = 67;
public static final int customListIdOffset = 10;
private static final String dbName = "data";
private static final String dbTableCaches = "cg_caches";
@@ -107,7 +108,7 @@ public class cgData {
+ "detailedupdate long, "
+ "visiteddate long, "
+ "geocode text unique not null, "
- + "reason integer not null default 0, " // cached, favourite...
+ + "reason integer not null default 0, " // cached, favorite...
+ "cacheid text, "
+ "guid text, "
+ "type text, "
@@ -674,6 +675,16 @@ public class cgData {
}
}
+ // issue2662 OC: Leichtes Klettern / Easy climbing
+ if (oldVersion < 67) {
+ try {
+ db.execSQL("update " + dbTableAttributes + " set attribute = 'easy_climbing_yes' where geocode like 'OC%' and attribute = 'climbing_yes'");
+ db.execSQL("update " + dbTableAttributes + " set attribute = 'easy_climbing_no' where geocode like 'OC%' and attribute = 'climbing_no'");
+ } catch (Exception e) {
+ Log.e("Failed to upgrade to ver. 67", e);
+
+ }
+ }
}
db.setTransactionSuccessful();
@@ -962,25 +973,32 @@ public class cgData {
throw new IllegalArgumentException("cache must not be null");
}
- // merge always with data already stored in the CacheCache or DB
- if (saveFlags.contains(SaveFlag.SAVE_CACHE)) {
- cache.gatherMissingFrom(cacheCache.getCacheFromCache(cache.getGeocode()));
- cacheCache.putCacheInCache(cache);
- }
+ // Merge with the data already stored in the CacheCache or in the database if
+ // the cache had not been loaded before, and update the CacheCache.
+ // Also, a DB update is required if the merge data comes from the CacheCache
+ // (as it may be more recent than the version in the database), or if the
+ // version coming from the database is different than the version we are entering
+ // into the cache (that includes absence from the database).
+ final String geocode = cache.getGeocode();
+ final Geocache cacheFromCache = cacheCache.getCacheFromCache(geocode);
+ final boolean dbUpdateRequired =
+ !cache.gatherMissingFrom(cacheFromCache != null ?
+ cacheFromCache :
+ loadCache(geocode, LoadFlags.LOAD_ALL_DB_ONLY)) ||
+ cacheFromCache != null;
+ cache.addStorageLocation(StorageLocation.CACHE);
+ cacheCache.putCacheInCache(cache);
+ // Only save the cache in the database if it is requested by the caller and
+ // the cache contains detailed information.
if (!saveFlags.contains(SaveFlag.SAVE_DB)) {
return true;
}
- boolean updateRequired = !cache.gatherMissingFrom(loadCache(cache.getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY));
- // only save a cache to the database if
- // - the cache is detailed
- // - there are changes
- // - the cache is only stored in the CacheCache so far
- if ((!updateRequired || !cache.isDetailed()) && cache.getStorageLocation().contains(StorageLocation.DATABASE)) {
- return false;
- }
+ return cache.isDetailed() && dbUpdateRequired && storeIntoDatabase(cache);
+ }
+ private static boolean storeIntoDatabase(final Geocache cache) {
cache.addStorageLocation(StorageLocation.DATABASE);
cacheCache.putCacheInCache(cache);
Log.d("Saving " + cache.toString() + " (" + cache.getListId() + ") to DB");
@@ -1396,7 +1414,7 @@ public class cgData {
* @param geocodes
* @return Set of loaded caches. Never null.
*/
- public static Set<Geocache> loadCaches(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
+ public static Set<Geocache> loadCaches(final Collection<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
if (CollectionUtils.isEmpty(geocodes)) {
return new HashSet<Geocache>();
}
@@ -1440,7 +1458,7 @@ public class cgData {
}
if (remaining.size() >= 1) {
- Log.i("cgData.loadCaches(" + remaining.toString() + ") failed");
+ Log.d("cgData.loadCaches(" + remaining.toString() + ") returned no results");
}
return result;
}
diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java
index a1fd7d1..b8f63ee 100644
--- a/main/src/cgeo/geocaching/cgeoapplication.java
+++ b/main/src/cgeo/geocaching/cgeoapplication.java
@@ -103,8 +103,8 @@ 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();
+ if (fromActivity instanceof MainActivity) {
+ ((MainActivity) fromActivity).updateCacheCounter();
}
}
};
diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java
index 61a32f1..6dad510 100644
--- a/main/src/cgeo/geocaching/cgeocaches.java
+++ b/main/src/cgeo/geocaching/cgeocaches.java
@@ -2,7 +2,6 @@ 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;
@@ -39,6 +38,7 @@ import cgeo.geocaching.sorting.VisitComparator;
import cgeo.geocaching.ui.CacheListAdapter;
import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.ui.WeakReferenceHandler;
+import cgeo.geocaching.utils.AsyncTaskWithProgress;
import cgeo.geocaching.utils.DateUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -74,6 +74,7 @@ import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
@@ -96,6 +97,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
private static final int MENU_REMOVE_FROM_HISTORY = 23;
private static final int MENU_DROP_CACHE = 24;
private static final int MENU_MOVE_TO_LIST = 25;
+ private static final int MENU_REFRESH = 26;
private static final int MENU_SWITCH_SELECT_MODE = 52;
private static final int SUBMENU_SHOW_MAP = 54;
private static final int SUBMENU_MANAGE_LISTS = 55;
@@ -373,21 +375,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
}
};
- private Handler dropDetailsHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- if (msg.what != MSG_CANCEL) {
- adapter.setSelectMode(false);
-
- refreshCurrentList();
-
- replaceCacheListFromSearch();
-
- progress.dismiss();
- }
- }
- };
private Handler clearOfflineLogsHandler = new Handler() {
@Override
@@ -428,7 +415,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (extras != null) {
Object typeObject = extras.get(Intents.EXTRA_LIST_TYPE);
type = (typeObject instanceof CacheListType) ? (CacheListType) typeObject : CacheListType.OFFLINE;
- coords = (Geopoint) extras.getParcelable(Intents.EXTRAS_COORDS);
+ coords = extras.getParcelable(Intents.EXTRA_COORDS);
}
else {
extras = new Bundle();
@@ -440,6 +427,17 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
}
+ // Add the list selection in code. This way we can leave the XML layout of the action bar the same as for other activities.
+ final View titleBar = findViewById(R.id.actionbar_title);
+ titleBar.setClickable(true);
+ titleBar.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ selectList(v);
+ }
+ });
+
setTitle(title);
setAdapter();
@@ -571,8 +569,11 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
SubMenu subMenu = menu.addSubMenu(0, SUBMENU_MANAGE_HISTORY, 0, res.getString(R.string.caches_manage)).setIcon(R.drawable.ic_menu_save);
subMenu.add(0, MENU_REMOVE_FROM_HISTORY, 0, res.getString(R.string.cache_clear_history)); // remove from history
subMenu.add(0, MENU_EXPORT, 0, res.getString(R.string.export)); // export caches
+ subMenu.add(0, MENU_CLEAR_OFFLINE_LOGS, 0, res.getString(R.string.caches_clear_offlinelogs));
+ menu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.cache_offline_refresh)).setIcon(R.drawable.ic_menu_set_as);
+ } else {
+ menu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.caches_store_offline)).setIcon(R.drawable.ic_menu_set_as); // download details for all caches
}
- menu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.caches_store_offline)).setIcon(R.drawable.ic_menu_set_as); // download details for all caches
}
navigationMenu = CacheListAppFactory.addMenuItems(menu, this, res);
@@ -625,8 +626,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
setVisible(menu, MENU_EXPORT, !isEmpty);
setVisible(menu, MENU_REMOVE_FROM_HISTORY, !isEmpty);
setVisible(menu, MENU_CLEAR_OFFLINE_LOGS, !isEmpty && containsOfflineLogs());
- setVisible(menu, MENU_IMPORT_GPX, isConcrete);
- setVisible(menu, MENU_IMPORT_WEB, isConcrete);
if (navigationMenu != null) {
navigationMenu.setVisible(!isEmpty);
@@ -635,12 +634,12 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
final boolean hasSelection = adapter != null && adapter.getCheckedCount() > 0;
final boolean isNonDefaultList = isConcrete && listId != StoredList.STANDARD_LIST_ID;
- if (type == CacheListType.OFFLINE) { // only offline list
+ if (type == CacheListType.OFFLINE || type == CacheListType.HISTORY) { // only offline list
setMenuItemLabel(menu, MENU_DROP_CACHES, R.string.caches_drop_selected, R.string.caches_drop_all);
menu.findItem(MENU_DROP_CACHES_AND_LIST).setVisible(!hasSelection && isNonDefaultList && !adapter.isFiltered());
setMenuItemLabel(menu, MENU_REFRESH_STORED, R.string.caches_refresh_selected, R.string.caches_refresh_all);
setMenuItemLabel(menu, MENU_MOVE_TO_LIST, R.string.caches_move_selected, R.string.caches_move_all);
- } else { // search and history list (all other than offline)
+ } else { // search and global list (all other than offline and history)
setMenuItemLabel(menu, MENU_REFRESH_STORED, R.string.caches_store_selected, R.string.caches_store_offline);
}
@@ -794,7 +793,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
public void deletePastEvents() {
- progress.show(this, null, res.getString(R.string.caches_drop_progress), true, dropDetailsHandler.obtainMessage(MSG_CANCEL));
final List<Geocache> deletion = new ArrayList<Geocache>();
for (Geocache cache : adapter.getCheckedOrAllCaches()) {
if (cache.isEventCache()) {
@@ -804,7 +802,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
}
}
- new DropDetailsThread(dropDetailsHandler, deletion).start();
+ new DropDetailsTask(false).execute(deletion.toArray(new Geocache[deletion.size()]));
}
public void clearOfflineLogs() {
@@ -858,13 +856,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
if (cache.getCoords() != null) {
menu.add(0, MENU_DEFAULT_NAVIGATION, 0, NavigationAppFactory.getDefaultNavigationApplication().getName());
menu.add(1, MENU_NAVIGATION, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
- LoggingUI.addMenuItems(menu, cache);
+ LoggingUI.addMenuItems(this, menu, cache);
menu.add(0, MENU_CACHE_DETAILS, 0, res.getString(R.string.cache_menu_details));
}
if (cache.isOffline()) {
menu.add(0, MENU_DROP_CACHE, 0, res.getString(R.string.cache_offline_drop));
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));
+ menu.add(0, MENU_REFRESH, 0, res.getString(R.string.cache_menu_refresh));
}
else {
menu.add(0, MENU_STORE_CACHE, 0, res.getString(R.string.cache_offline_store));
@@ -944,6 +943,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}, true, listId);
break;
case MENU_STORE_CACHE:
+ case MENU_REFRESH:
refreshStored(Collections.singletonList(cache));
break;
case MENU_EXPORT:
@@ -1082,6 +1082,11 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
return;
}
+ if (!Network.isNetworkConnected(getApplicationContext())) {
+ showToast(getString(R.string.err_server));
+ return;
+ }
+
if (Settings.getChooseList() && type != CacheListType.OFFLINE) {
// let user select list to store cache in
new StoredList.UserInterface(this).promptForListSelection(R.string.list_title,
@@ -1144,7 +1149,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
public void removeFromHistory() {
final List<Geocache> caches = adapter.getCheckedOrAllCaches();
- final String geocodes[] = new String[caches.size()];
+ final String[] geocodes = new String[caches.size()];
for (int i = 0; i < geocodes.length; i++) {
geocodes[i] = caches.get(i).getGeocode();
}
@@ -1177,10 +1182,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public void onClick(DialogInterface dialog, int id) {
- dropSelected();
- if (removeListAfterwards) {
- removeList(false);
- }
+ dropSelected(removeListAfterwards);
dialog.cancel();
}
});
@@ -1196,9 +1198,9 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
alert.show();
}
- public void dropSelected() {
- progress.show(this, null, res.getString(R.string.caches_drop_progress), true, dropDetailsHandler.obtainMessage(MSG_CANCEL));
- new DropDetailsThread(dropDetailsHandler, adapter.getCheckedOrAllCaches()).start();
+ public void dropSelected(boolean removeListAfterwards) {
+ final List<Geocache> selected = adapter.getCheckedOrAllCaches();
+ new DropDetailsTask(removeListAfterwards).execute(selected.toArray(new Geocache[selected.size()]));
}
/**
@@ -1309,7 +1311,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
public LoadFromWebThread(Handler handlerIn, int listId) {
handler = handlerIn;
- listIdLFW = listId;
+ listIdLFW = StoredList.getConcreteList(listId);
}
public void kill() {
@@ -1383,24 +1385,35 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
}
- private class DropDetailsThread extends Thread {
+ private class DropDetailsTask extends AsyncTaskWithProgress<Geocache, Void> {
- final private Handler handler;
- final private List<Geocache> selected;
+ private final boolean removeListAfterwards;
- public DropDetailsThread(Handler handlerIn, List<Geocache> selectedIn) {
- handler = handlerIn;
- selected = selectedIn;
+ public DropDetailsTask(boolean removeListAfterwards) {
+ super(cgeocaches.this, null, res.getString(R.string.caches_drop_progress), true);
+ this.removeListAfterwards = removeListAfterwards;
}
@Override
- public void run() {
+ protected Void doInBackgroundInternal(Geocache[] caches) {
removeGeoAndDir();
- cgData.markDropped(selected);
- handler.sendEmptyMessage(MSG_DONE);
-
+ cgData.markDropped(Arrays.asList(caches));
startGeoAndDir();
+ return null;
}
+
+ @Override
+ protected void onPostExecuteInternal(Void result) {
+ // remove list in UI because of toast
+ if (removeListAfterwards) {
+ removeList(false);
+ }
+
+ adapter.setSelectMode(false);
+ refreshCurrentList();
+ replaceCacheListFromSearch();
+ }
+
}
private class ClearOfflineLogsThread extends Thread {
@@ -1566,21 +1579,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
CGeoMap.startActivitySearch(this, searchToUse, mapTitle);
}
- @Override
- public void goManual(View view) {
- switch (type) {
- case OFFLINE:
- ActivityMixin.goManual(this, "c:geo-stored");
- break;
- case HISTORY:
- ActivityMixin.goManual(this, "c:geo-history");
- break;
- default:
- ActivityMixin.goManual(this, "c:geo-nearby");
- break;
- }
- }
-
private void refreshCurrentList() {
switchListById(listId);
}
@@ -1667,7 +1665,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
final Intent cachesIntent = new Intent(context, cgeocaches.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.NEAREST);
- cachesIntent.putExtra(Intents.EXTRAS_COORDS, coordsNow);
+ cachesIntent.putExtra(Intents.EXTRA_COORDS, coordsNow);
context.startActivity(cachesIntent);
}
@@ -1680,7 +1678,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
public static void startActivityAddress(final Context context, final Geopoint coords, final String address) {
final Intent addressIntent = new Intent(context, cgeocaches.class);
addressIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.ADDRESS);
- addressIntent.putExtra(Intents.EXTRAS_COORDS, coords);
+ addressIntent.putExtra(Intents.EXTRA_COORDS, coords);
addressIntent.putExtra(Intents.EXTRA_ADDRESS, address);
context.startActivity(addressIntent);
}
@@ -1691,7 +1689,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
}
final Intent cachesIntent = new Intent(context, cgeocaches.class);
cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.COORDINATE);
- cachesIntent.putExtra(Intents.EXTRAS_COORDS, coords);
+ cachesIntent.putExtra(Intents.EXTRA_COORDS, coords);
context.startActivity(cachesIntent);
}
@@ -1725,11 +1723,11 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity
@Override
public Loader<SearchResult> onCreateLoader(int type, Bundle extras) {
- AbstractSearchLoader loader = null;
if (type >= CacheListLoaderType.values().length) {
throw new IllegalArgumentException("invalid loader type " + type);
}
CacheListLoaderType enumType = CacheListLoaderType.values()[type];
+ AbstractSearchLoader loader = null;
switch (enumType) {
case OFFLINE:
listId = Settings.getLastList();
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java
index a60b48d..6d5781f 100644
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java
@@ -19,7 +19,11 @@ public class AndroidLevel8Emulation implements AndroidLevel8Interface {
@Override
public int getRotationOffset(Activity activity) {
final Display display = activity.getWindowManager().getDefaultDisplay();
+
+ // the non deprecated method is available in API 8+ only, so we cannot deal better with this
+ @SuppressWarnings("deprecation")
final int rotation = display.getOrientation();
+
if (rotation == Configuration.ORIENTATION_LANDSCAPE) {
return 90;
}
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index 413291c..905382f 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -6,6 +6,8 @@ import cgeo.geocaching.geopoint.Geopoint;
import org.apache.commons.lang3.StringUtils;
+import android.app.Activity;
+
public abstract class AbstractConnector implements IConnector {
@Override
@@ -19,6 +21,16 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
+ public boolean addToWatchlist(Geocache cache) {
+ return false;
+ }
+
+ @Override
+ public boolean removeFromWatchlist(Geocache cache) {
+ return false;
+ }
+
+ @Override
public boolean supportsOwnCoordinates() {
return false;
}
@@ -54,6 +66,21 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
+ public boolean supportsLogImages() {
+ return false;
+ }
+
+ @Override
+ public boolean canLog(Geocache cache) {
+ return false;
+ }
+
+ @Override
+ public ILoggingManager getLoggingManager(Activity activity, Geocache cache) {
+ return new NoLoggingManager();
+ }
+
+ @Override
public String getLicenseText(final Geocache cache) {
return null;
}
diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
index 561bae2..50f56af 100644
--- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java
+++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
@@ -1,14 +1,15 @@
package cgeo.geocaching.connector;
import cgeo.geocaching.ICache;
+import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
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.OCApiLiveConnector;
import cgeo.geocaching.connector.oc.OCConnector;
-import cgeo.geocaching.connector.oc.OCXMLApiConnector;
import cgeo.geocaching.connector.ox.OXConnector;
import cgeo.geocaching.geopoint.Viewport;
@@ -21,7 +22,7 @@ public final class ConnectorFactory {
private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector();
private static final IConnector[] connectors = new IConnector[] {
GCConnector.getInstance(),
- new OCXMLApiConnector("OpenCaching.DE", "www.opencaching.de", "OC"),
+ new OCApiLiveConnector("Opencaching.de", "www.opencaching.de", "OC", R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret),
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"),
diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java
index 9169b4a..011c507 100644
--- a/main/src/cgeo/geocaching/connector/IConnector.java
+++ b/main/src/cgeo/geocaching/connector/IConnector.java
@@ -5,6 +5,8 @@ import cgeo.geocaching.ICache;
import cgeo.geocaching.enumerations.CacheRealm;
import cgeo.geocaching.geopoint.Geopoint;
+import android.app.Activity;
+
public interface IConnector {
/**
* get name for display (currently only used in links)
@@ -45,6 +47,22 @@ public interface IConnector {
public boolean supportsWatchList();
/**
+ * Add the cache to the watchlist
+ *
+ * @param cache
+ * @return True - success/False - failure
+ */
+ public boolean addToWatchlist(Geocache cache);
+
+ /**
+ * Remove the cache from the watchlist
+ *
+ * @param cache
+ * @return True - success/False - failure
+ */
+ public boolean removeFromWatchlist(Geocache cache);
+
+ /**
* enable/disable favorite points controls in cache details
*
* @return
@@ -59,6 +77,20 @@ public interface IConnector {
public boolean supportsLogging();
/**
+ * enable/disable attaching image to log
+ *
+ * @return
+ */
+ public boolean supportsLogImages();
+
+ /**
+ * Get an ILoggingManager to guide the logging process.
+ *
+ * @return
+ */
+ public ILoggingManager getLoggingManager(Activity activity, Geocache cache);
+
+ /**
* get host name of the connector server for dynamic loading of data
*
* @return
@@ -159,4 +191,13 @@ public interface IConnector {
* @return <code>true</code> if the current user is the cache owner, <code>false</code> otherwise
*/
public boolean isOwner(final ICache cache);
+
+ /**
+ * Check if the cache information is complete enough to be
+ * able to log online.
+ *
+ * @param geocache
+ * @return
+ */
+ public boolean canLog(Geocache geocache);
}
diff --git a/main/src/cgeo/geocaching/connector/ILoggingManager.java b/main/src/cgeo/geocaching/connector/ILoggingManager.java
new file mode 100644
index 0000000..f0029f9
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/ILoggingManager.java
@@ -0,0 +1,32 @@
+package cgeo.geocaching.connector;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.TrackableLog;
+import cgeo.geocaching.enumerations.LogType;
+
+import android.net.Uri;
+
+import java.util.Calendar;
+import java.util.List;
+
+public interface ILoggingManager {
+
+ LogResult postLog(Geocache cache,
+ LogType logType,
+ Calendar date,
+ String log,
+ List<TrackableLog> trackableLogs);
+
+ ImageResult postLogImage(String logId,
+ String imageCaption,
+ String imageDescription,
+ Uri imageUri);
+
+ public boolean hasLoaderError();
+
+ public List<TrackableLog> getTrackables();
+
+ public List<LogType> getPossibleLogTypes();
+
+ public void init();
+}
diff --git a/main/src/cgeo/geocaching/connector/ImageResult.java b/main/src/cgeo/geocaching/connector/ImageResult.java
new file mode 100644
index 0000000..9314cad
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/ImageResult.java
@@ -0,0 +1,23 @@
+package cgeo.geocaching.connector;
+
+import cgeo.geocaching.enumerations.StatusCode;
+
+public class ImageResult {
+
+ private final StatusCode postResult;
+ private final String imageUri;
+
+ public ImageResult(StatusCode postResult, String imageUri) {
+ this.postResult = postResult;
+ this.imageUri = imageUri;
+ }
+
+ public StatusCode getPostResult() {
+ return postResult;
+ }
+
+ public String getImageUri() {
+ return imageUri;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/LogResult.java b/main/src/cgeo/geocaching/connector/LogResult.java
new file mode 100644
index 0000000..62111a4
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/LogResult.java
@@ -0,0 +1,23 @@
+package cgeo.geocaching.connector;
+
+import cgeo.geocaching.enumerations.StatusCode;
+
+public class LogResult {
+
+ private final StatusCode postLogResult;
+ private final String logId;
+
+ public LogResult(StatusCode postLogResult, String logId) {
+ this.postLogResult = postLogResult;
+ this.logId = logId;
+ }
+
+ public StatusCode getPostLogResult() {
+ return postLogResult;
+ }
+
+ public String getLogId() {
+ return logId;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/NoLoggingManager.java b/main/src/cgeo/geocaching/connector/NoLoggingManager.java
new file mode 100644
index 0000000..bfea4ca
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/NoLoggingManager.java
@@ -0,0 +1,46 @@
+package cgeo.geocaching.connector;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.TrackableLog;
+import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.enumerations.StatusCode;
+
+import android.net.Uri;
+
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.List;
+
+public class NoLoggingManager implements ILoggingManager {
+
+ @Override
+ public void init() {
+ // nothing to do
+ }
+
+ @Override
+ public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) {
+ return new LogResult(StatusCode.LOG_POST_ERROR, "");
+ }
+
+ @Override
+ public ImageResult postLogImage(String logId, String imageCaption, String imageDescription, Uri imageUri) {
+ return new ImageResult(StatusCode.LOG_POST_ERROR, "");
+ }
+
+ @Override
+ public boolean hasLoaderError() {
+ return true;
+ }
+
+ @Override
+ public List<TrackableLog> getTrackables() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<LogType> getPossibleLogTypes() {
+ return Collections.emptyList();
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index 50bf096..82bd52a 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -7,6 +7,7 @@ import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
import cgeo.geocaching.cgData;
import cgeo.geocaching.connector.AbstractConnector;
+import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.capability.ISearchByCenter;
import cgeo.geocaching.connector.capability.ISearchByGeocode;
import cgeo.geocaching.connector.capability.ISearchByViewPort;
@@ -20,6 +21,8 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import android.app.Activity;
+
import java.util.regex.Pattern;
public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort {
@@ -27,7 +30,11 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
private static final String CACHE_URL_SHORT = "http://coord.info/";
// Double slash is used to force open in browser
private static final String CACHE_URL_LONG = "http://www.geocaching.com//seek/cache_details.aspx?wp=";
- private static final Pattern gpxZipFilePattern = Pattern.compile("\\d{7,}(_.+)?\\.zip", Pattern.CASE_INSENSITIVE);
+ /**
+ * Pocket queries downloaded from the website use a numeric prefix. The pocket query creator Android app adds a
+ * verbatim "pocketquery" prefix.
+ */
+ private static final Pattern gpxZipFilePattern = Pattern.compile("((\\d{7,})|(pocketquery))" + "(_.+)?" + "\\.zip", Pattern.CASE_INSENSITIVE);
private GCConnector() {
// singleton
@@ -78,6 +85,21 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
+ public boolean supportsLogImages() {
+ return true;
+ }
+
+ @Override
+ public ILoggingManager getLoggingManager(Activity activity, Geocache cache) {
+ return new GCLoggingManager(activity, cache);
+ }
+
+ @Override
+ public boolean canLog(Geocache cache) {
+ return StringUtils.isNotBlank(cache.getCacheId());
+ }
+
+ @Override
public String getName() {
return "GeoCaching.com";
}
@@ -149,7 +171,8 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
- public static boolean addToWatchlist(Geocache cache) {
+ @Override
+ public boolean addToWatchlist(Geocache cache) {
final boolean added = GCParser.addToWatchlist(cache);
if (added) {
cgData.saveChangedCache(cache);
@@ -157,7 +180,8 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
return added;
}
- public static boolean removeFromWatchlist(Geocache cache) {
+ @Override
+ public boolean removeFromWatchlist(Geocache cache) {
final boolean removed = GCParser.removeFromWatchlist(cache);
if (removed) {
cgData.saveChangedCache(cache);
@@ -240,6 +264,6 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
@Override
public boolean isActivated() {
- return true;
+ return Settings.isGCConnectorActive();
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index b66acb7..b4f5845 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -152,7 +152,7 @@ public final class GCConstants {
public final static Pattern PATTERN_MAINTENANCE = Pattern.compile("<span id=\"ctl00_ContentBody_LogBookPanel1_lbConfirm\"[^>]*>([^<]*<font[^>]*>)?([^<]+)(</font>[^<]*)?</span>", Pattern.CASE_INSENSITIVE);
public final static Pattern PATTERN_OK1 = Pattern.compile("<h2[^>]*>[^<]*<span id=\"ctl00_ContentBody_lbHeading\"[^>]*>[^<]*</span>[^<]*</h2>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
public final static Pattern PATTERN_OK2 = Pattern.compile("<div id=[\"|']ctl00_ContentBody_LogBookPanel1_ViewLogPanel[\"|']>", Pattern.CASE_INSENSITIVE);
- public final static Pattern PATTERN_OK_IMAGEUPLOAD = Pattern.compile("<div id=[\"|']ctl00_ContentBody_ImageUploadControl1_uxUploadDonePanel[\"|']>", Pattern.CASE_INSENSITIVE);
+ public final static Pattern PATTERN_IMAGE_UPLOAD_URL = Pattern.compile("title=\"Click for Larger Image\"\\s*src=\"(.*?)\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
public final static Pattern PATTERN_VIEWSTATEFIELDCOUNT = Pattern.compile("id=\"__VIEWSTATEFIELDCOUNT\"[^(value)]+value=\"(\\d+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
public final static Pattern PATTERN_VIEWSTATES = Pattern.compile("id=\"__VIEWSTATE(\\d*)\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
public final static Pattern PATTERN_USERTOKEN = Pattern.compile("userToken\\s*=\\s*'([^']+)'");
diff --git a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
new file mode 100644
index 0000000..0fbd718
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
@@ -0,0 +1,132 @@
+package cgeo.geocaching.connector.gc;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.TrackableLog;
+import cgeo.geocaching.VisitCacheActivity;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.connector.ILoggingManager;
+import cgeo.geocaching.connector.ImageResult;
+import cgeo.geocaching.connector.LogResult;
+import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.enumerations.StatusCode;
+import cgeo.geocaching.loaders.UrlLoader;
+import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.Loader;
+
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.List;
+
+public class GCLoggingManager implements ILoggingManager, LoaderManager.LoaderCallbacks<String> {
+
+ private final VisitCacheActivity activity;
+ private final Geocache cache;
+
+ private String[] viewstates;
+ private List<TrackableLog> trackables;
+ private List<LogType> possibleLogTypes;
+ private boolean hasLoaderError = true;
+
+ public GCLoggingManager(Activity activity, Geocache cache) {
+ this.activity = (VisitCacheActivity) activity;
+ this.cache = cache;
+ }
+
+ @Override
+ public Loader<String> onCreateLoader(int arg0, Bundle arg1) {
+ if (!Settings.isLogin()) { // allow offline logging
+ ActivityMixin.showToast(activity, activity.getResources().getString(R.string.err_login));
+ return null;
+ }
+ return new UrlLoader(activity.getBaseContext(), "http://www.geocaching.com/seek/log.aspx", new Parameters("ID", cache.getCacheId()));
+ }
+
+ @Override
+ public void onLoadFinished(Loader<String> arg0, String page) {
+
+ if (page == null) {
+ hasLoaderError = true;
+ } else {
+
+ viewstates = Login.getViewstates(page);
+ trackables = GCParser.parseTrackableLog(page);
+ possibleLogTypes = GCParser.parseTypes(page);
+
+ hasLoaderError = possibleLogTypes.isEmpty();
+ }
+
+ activity.onLoadFinished();
+ }
+
+ @Override
+ public void onLoaderReset(Loader<String> arg0) {
+ // nothing to do
+ }
+
+ @Override
+ public void init() {
+ activity.getSupportLoaderManager().initLoader(0, null, this);
+ }
+
+ @Override
+ public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) {
+
+ try {
+ final ImmutablePair<StatusCode, String> postResult = GCParser.postLog(cache.getGeocode(), cache.getCacheId(), viewstates, logType,
+ date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE),
+ log, trackableLogs);
+
+ return new LogResult(postResult.left, postResult.right);
+ } catch (Exception e) {
+ Log.e("GCLoggingManager.postLog", e);
+ }
+
+ return new LogResult(StatusCode.LOG_POST_ERROR, "");
+ }
+
+ @Override
+ public ImageResult postLogImage(String logId, String imageCaption, String imageDescription, Uri imageUri) {
+
+ if (StringUtils.isNotBlank(imageUri.getPath())) {
+
+ ImmutablePair<StatusCode, String> imageResult = GCParser.uploadLogImage(logId, imageCaption, imageDescription, imageUri);
+
+ return new ImageResult(imageResult.left, imageResult.right);
+ }
+
+ return new ImageResult(StatusCode.LOGIMAGE_POST_ERROR, "");
+ }
+
+ @Override
+ public boolean hasLoaderError() {
+ return hasLoaderError;
+ }
+
+ @Override
+ public List<TrackableLog> getTrackables() {
+ if (hasLoaderError) {
+ return Collections.emptyList();
+ }
+ return trackables;
+ }
+
+ @Override
+ public List<LogType> getPossibleLogTypes() {
+ if (hasLoaderError) {
+ return Collections.emptyList();
+ }
+ return possibleLogTypes;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index 49f61ef..3143a06 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -92,7 +92,7 @@ public class GCMap {
JSONObject ownerObj = dataObject.getJSONObject("owner");
cache.setOwnerDisplayName(ownerObj.getString("text"));
- result.addCache(cache);
+ result.addAndPutInCache(cache);
}
} catch (JSONException e) {
@@ -231,7 +231,7 @@ public class GCMap {
exclude = true;
}
if (!exclude) {
- searchResult.addCache(cache);
+ searchResult.addAndPutInCache(cache);
}
}
Log.d("Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString());
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index d4e1999..306f45a 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -241,10 +241,10 @@ public abstract class GCParser {
cache.setFavoritePoints(Integer.parseInt(result));
}
} catch (NumberFormatException e) {
- Log.w("GCParser.parseSearch: Failed to parse favourite count");
+ Log.w("GCParser.parseSearch: Failed to parse favorite count");
}
- searchResult.addCache(cache);
+ searchResult.addAndPutInCache(cache);
}
// total caches found
@@ -332,9 +332,11 @@ public abstract class GCParser {
static SearchResult parseCache(final String page, final CancellableHandler handler) {
final SearchResult searchResult = parseCacheFromText(page, handler);
+ // attention: parseCacheFromText already stores implicitely through searchResult.addCache
if (searchResult != null && !searchResult.getGeocodes().isEmpty()) {
final Geocache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
getExtraOnlineInfo(cache, page, handler);
+ // too late: it is already stored through parseCacheFromText
cache.setDetailedUpdatedNow();
if (CancellableHandler.isCancelled(handler)) {
return null;
@@ -455,11 +457,11 @@ public abstract class GCParser {
Log.w("GCParser.parseCache: Failed to parse cache hidden (event) date");
}
- // favourite
+ // favorite
try {
cache.setFavoritePoints(Integer.parseInt(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0")));
} catch (NumberFormatException e) {
- Log.e("Error parsing favourite count", e);
+ Log.e("Error parsing favorite count", e);
}
// cache size
@@ -728,7 +730,8 @@ public abstract class GCParser {
return searchResult;
}
- searchResult.addCache(cache);
+ cache.setDetailedUpdatedNow();
+ searchResult.addAndPutInCache(cache);
return searchResult;
}
@@ -1093,7 +1096,7 @@ public abstract class GCParser {
* the URI for the image to be uploaded
* @return status code to indicate success or failure
*/
- public static StatusCode uploadLogImage(final String logId, final String caption, final String description, final Uri imageUri) {
+ public static ImmutablePair<StatusCode, String> uploadLogImage(final String logId, final String caption, final String description, final Uri imageUri) {
final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/upload.aspx").encodedQuery("LID=" + logId).build().toString();
String page = Network.getResponseData(Network.getRequest(uri));
@@ -1105,7 +1108,7 @@ public abstract class GCParser {
page = Network.getResponseData(Network.getRequest(uri));
} else {
Log.e("Image upload: No login (error: " + loginState + ')');
- return StatusCode.NOT_LOGGED_IN;
+ return ImmutablePair.of(StatusCode.NOT_LOGGED_IN, null);
}
}
@@ -1122,18 +1125,23 @@ public abstract class GCParser {
final File image = new File(imageUri.getPath());
final String response = Network.getResponseData(Network.postRequest(uri, uploadParams, "ctl00$ContentBody$ImageUploadControl1$uxFileUpload", "image/jpeg", image));
- MatcherWrapper matcherOK = new MatcherWrapper(GCConstants.PATTERN_OK_IMAGEUPLOAD, response);
+ MatcherWrapper matcherUrl = new MatcherWrapper(GCConstants.PATTERN_IMAGE_UPLOAD_URL, response);
- if (matcherOK.find()) {
+ if (matcherUrl.find()) {
Log.i("Logimage successfully uploaded.");
-
- return StatusCode.NO_ERROR;
+ final String uploadedImageUrl = matcherUrl.group(1);
+ return ImmutablePair.of(StatusCode.NO_ERROR, uploadedImageUrl);
}
Log.e("GCParser.uploadLogIMage: Failed to upload image because of unknown error");
- return StatusCode.LOGIMAGE_POST_ERROR;
+ return ImmutablePair.of(StatusCode.LOGIMAGE_POST_ERROR, null);
}
+ /**
+ * Post a log to GC.com.
+ *
+ * @return status code of the upload and ID of the log
+ */
public static StatusCode postLogTrackable(final String tbid, final String trackingCode, final String[] viewstates,
final LogType logType, final int year, final int month, final int day, final String log) {
if (Login.isEmpty(viewstates)) {
@@ -1408,7 +1416,11 @@ public abstract class GCParser {
// trackable distance
final String distance = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null);
if (null != distance) {
- trackable.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits()));
+ try {
+ trackable.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits()));
+ } catch (NumberFormatException e) {
+ Log.e("GCParser.parseTrackable: Failed to parse distance", e);
+ }
}
// trackable goal
@@ -1615,15 +1627,8 @@ public abstract class GCParser {
final List<LogType> types = new ArrayList<LogType>();
final MatcherWrapper typeBoxMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPEBOX, page);
- String typesText = null;
- if (typeBoxMatcher.find()) {
- if (typeBoxMatcher.groupCount() > 0) {
- typesText = typeBoxMatcher.group(1);
- }
- }
-
- if (typesText != null) {
-
+ if (typeBoxMatcher.find() && typeBoxMatcher.groupCount() > 0) {
+ String typesText = typeBoxMatcher.group(1);
final MatcherWrapper typeMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPE2, typesText);
while (typeMatcher.find()) {
if (typeMatcher.groupCount() > 1) {
@@ -1639,6 +1644,9 @@ public abstract class GCParser {
}
}
+ // we don't support this log type
+ types.remove(LogType.UPDATE_COORDINATES);
+
return types;
}
diff --git a/main/src/cgeo/geocaching/connector/oc/AttributeParser.java b/main/src/cgeo/geocaching/connector/oc/AttributeParser.java
new file mode 100644
index 0000000..63bee77
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/AttributeParser.java
@@ -0,0 +1,327 @@
+// This is a generated file, do not change manually!
+
+package cgeo.geocaching.connector.oc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class AttributeParser {
+
+ private final static Map<String, Integer> attrMapDe;
+ private final static Map<String, Integer> attrMapPl;
+
+ static {
+ attrMapDe = new HashMap<String, Integer>();
+ attrMapPl = new HashMap<String, Integer>();
+
+ // last header line
+ attrMapDe.put("Listed at Opencaching only", 6);
+ attrMapDe.put("Dostępna tylko na Opencaching", 6);
+ attrMapDe.put("Nur bei Opencaching logbar", 6);
+ attrMapDe.put("Solo loggeable en Opencaching", 6);
+ attrMapDe.put("Loggabile solo su Opencaching", 6);
+ attrMapPl.put("Near a Survey Marker", 54);
+ attrMapPl.put("W pobliżu punktu geodezyjnego", 54);
+ attrMapPl.put("Whereigo Cache", 55);
+ attrMapPl.put("Whereigo Cache", 55);
+ attrMapPl.put("Whereigo Cache", 55);
+ attrMapDe.put("Letterbox Cache", 8);
+ attrMapPl.put("Letterbox Cache", 56);
+ attrMapDe.put("Skrzynka typu Letterbox", 8);
+ attrMapPl.put("Skrzynka typu Letterbox", 56);
+ attrMapDe.put("Letterbox (benötigt Stempel)", 8);
+ attrMapPl.put("Letterbox (benötigt Stempel)", 56);
+ attrMapDe.put("Letterbox (necesita un estampador)", 8);
+ attrMapPl.put("Letterbox (necesita un estampador)", 56);
+ attrMapDe.put("Letterbox (richiede un timbro)", 8);
+ attrMapPl.put("Letterbox (richiede un timbro)", 56);
+ attrMapPl.put("GeoHotel", 43);
+ attrMapPl.put("GeoHotel", 43);
+ attrMapPl.put("GeoHotel", 43);
+ attrMapPl.put("Magnetic cache", 49);
+ attrMapPl.put("Przyczepiona magnesem", 49);
+ attrMapPl.put("magnetischer Cache", 49);
+ attrMapPl.put("Description contains an audio file", 50);
+ attrMapPl.put("Opis zawiera plik audio", 50);
+ attrMapPl.put("Offset cache", 51);
+ attrMapPl.put("Offset cache", 51);
+ attrMapPl.put("Peilungscache", 51);
+ attrMapPl.put("Garmin's wireless beacon", 52);
+ attrMapPl.put("Beacon - Garmin Chirp", 52);
+ attrMapPl.put("Funksignal – Garmin Chirp", 52);
+ attrMapPl.put("Dead Drop USB cache", 53);
+ attrMapPl.put("Dead Drop USB skrzynka", 53);
+ attrMapDe.put("Has a moving target", 31);
+ attrMapDe.put("bewegliches Ziel", 31);
+ attrMapDe.put("Objetivo en movimiento", 31);
+ attrMapDe.put("Oggetto in movimento", 31);
+ attrMapDe.put("Webcam Cache", 32);
+ attrMapDe.put("Webcam Cache", 32);
+ attrMapDe.put("Webcam Cache", 32);
+ attrMapDe.put("Webcam Cache", 32);
+ attrMapDe.put("Other cache type", 57);
+ attrMapDe.put("sonstiger Cachetyp", 57);
+ attrMapDe.put("Otro tipo de cache", 57);
+ attrMapDe.put("Altro tipo di cache", 57);
+ attrMapDe.put("Investigation required", 54);
+ attrMapDe.put("Recherche", 54);
+ attrMapDe.put("Investigación", 54);
+ attrMapDe.put("Ricerca", 54);
+ attrMapDe.put("Puzzle / Mystery", 55);
+ attrMapDe.put("Rätsel", 55);
+ attrMapDe.put("Puzzle / Misterio", 55);
+ attrMapDe.put("Puzzle / Mystery", 55);
+ attrMapDe.put("Arithmetical problem", 56);
+ attrMapDe.put("Rechenaufgabe", 56);
+ attrMapDe.put("Problema matemático", 56);
+ attrMapDe.put("Problema matematico", 56);
+ attrMapDe.put("Ask owner for start conditions", 58);
+ attrMapDe.put("Startbedingungen beim Owner erfragen", 58);
+ attrMapDe.put("Ask owner for start conditions", 58);
+ attrMapDe.put("Ask owner for start conditions", 58);
+ attrMapPl.put("Wheelchair accessible", 44);
+ attrMapPl.put("Dostępna dla niepełnosprawnych", 44);
+ attrMapPl.put("rollstuhltauglich", 44);
+ attrMapDe.put("Near the parking area", 24);
+ attrMapDe.put("nahe beim Auto", 24);
+ attrMapDe.put("Cerca de un Parking", 24);
+ attrMapDe.put("Vicino all'area di parcheggio", 24);
+ attrMapPl.put("Access only by walk", 84);
+ attrMapPl.put("Dostępna tylko pieszo", 84);
+ attrMapDe.put("Long walk", 25);
+ attrMapDe.put("längere Wanderung", 25);
+ attrMapDe.put("Larga caminata", 25);
+ attrMapDe.put("Lunga camminata", 25);
+ attrMapDe.put("Swamp, marsh or wading", 26);
+ attrMapDe.put("sumpfig/matschiges Gelände / waten", 26);
+ attrMapDe.put("Pantano / terreno fangoso", 26);
+ attrMapDe.put("Palude o marcita", 26);
+ attrMapDe.put("Hilly area", 27);
+ attrMapDe.put("hügeliges Gelände", 27);
+ attrMapDe.put("Terreno montañoso", 27);
+ attrMapDe.put("Area collinare", 27);
+ attrMapDe.put("Some climbing (no gear needed)", 28);
+ attrMapDe.put("leichtes Klettern (ohne Ausrüstung)", 28);
+ attrMapDe.put("fácil de subir (sin equipo)", 28);
+ attrMapDe.put("Arrampicata (attrezzatura non necessaria)", 28);
+ attrMapDe.put("Swimming required", 29);
+ attrMapDe.put("Schwimmen erforderlich", 29);
+ attrMapDe.put("Requiere nadar", 29);
+ attrMapDe.put("Nuoto necessario", 29);
+ attrMapDe.put("Access or parking fee", 36);
+ attrMapDe.put("Zugangs- bzw. Parkentgelt", 36);
+ attrMapDe.put("Acceso o parking pagando", 36);
+ attrMapDe.put("Tassa di ingresso o di parcheggio", 36);
+ attrMapPl.put("Bikes allowed", 85);
+ attrMapPl.put("Dostępna rowerem", 85);
+ attrMapPl.put("Hidden in natural surroundings (forests, mountains, etc.)", 60);
+ attrMapPl.put("Umiejscowiona na łonie natury (lasy, góry, itp.)", 60);
+ attrMapPl.put("Historic site", 61);
+ attrMapPl.put("Miejsce historyczne", 61);
+ attrMapDe.put("Point of interest", 30);
+ attrMapDe.put("interessanter Ort", 30);
+ attrMapDe.put("Punto de interes", 30);
+ attrMapDe.put("Punto di interesse", 30);
+ attrMapDe.put("Hidden wihin enclosed rooms (caves, buildings etc.)", 33);
+ attrMapDe.put("in geschlossenen Räumen (Höhle, Gebäude, etc.)", 33);
+ attrMapDe.put("en espacios confinados (cuevas, edificios, etc)", 33);
+ attrMapDe.put("All'interno di stanze chiuse (caverne, edifici, ecc.)", 33);
+ attrMapDe.put("Hidden under water", 34);
+ attrMapDe.put("Im Wasser versteckt", 34);
+ attrMapDe.put("En el agua", 34);
+ attrMapDe.put("Nell'acqua", 34);
+ attrMapDe.put("Parking area nearby", 18);
+ attrMapDe.put("Parkplatz in der Nähe", 18);
+ attrMapDe.put("Parking cercano", 18);
+ attrMapDe.put("Parcheggio nei pressi", 18);
+ attrMapDe.put("Public transportation", 19);
+ attrMapDe.put("erreichbar mit ÖVM", 19);
+ attrMapDe.put("Transporte Público", 19);
+ attrMapDe.put("Trasporto pubblico", 19);
+ attrMapDe.put("Drinking water nearby", 20);
+ attrMapDe.put("Trinkwasser in der Nähe", 20);
+ attrMapDe.put("Agua potable en las cercanias", 20);
+ attrMapDe.put("Acqua potabile nei pressi", 20);
+ attrMapDe.put("Public restrooms nearby", 21);
+ attrMapDe.put("öffentliche Toilette in der Nähe", 21);
+ attrMapDe.put("Aseos públicos cercanos", 21);
+ attrMapDe.put("Bagni pubblici nei pressi", 21);
+ attrMapDe.put("Public phone nearby", 22);
+ attrMapDe.put("Telefon in der Nähe", 22);
+ attrMapDe.put("Teléfono Público en las cercanias", 22);
+ attrMapDe.put("Telefono pubblico nei pressi", 22);
+ attrMapDe.put("First aid available", 23);
+ attrMapDe.put("Erste Hilfe verfügbar", 23);
+ attrMapDe.put("Disponible socorro rapido", 23);
+ attrMapDe.put("Disponibile pronto soccorso", 23);
+ attrMapDe.put("Available 24/7", 38);
+ attrMapDe.put("rund um die Uhr machbar", 38);
+ attrMapDe.put("Disponible las 24 horas", 38);
+ attrMapDe.put("Disponibile 24 ore", 38);
+ attrMapDe.put("Not 24/7", 39);
+ attrMapPl.put("Not 24/7", 80);
+ attrMapDe.put("Dostępna w określonych godzinach", 39);
+ attrMapPl.put("Dostępna w określonych godzinach", 80);
+ attrMapDe.put("nur zu bestimmten Uhrzeiten", 39);
+ attrMapPl.put("nur zu bestimmten Uhrzeiten", 80);
+ attrMapDe.put("Sólo disponible a ciertas horas", 39);
+ attrMapPl.put("Sólo disponible a ciertas horas", 80);
+ attrMapDe.put("Disponibile solo in certi orari", 39);
+ attrMapPl.put("Disponibile solo in certi orari", 80);
+ attrMapDe.put("Not recommended at night", 40);
+ attrMapDe.put("nur tagüber", 40);
+ attrMapDe.put("solo por el día", 40);
+ attrMapDe.put("solo di giorno", 40);
+ attrMapPl.put("Recommended at night", 91);
+ attrMapPl.put("Zalecane szukanie nocą", 91);
+ attrMapPl.put("am besten nachts findbar", 91);
+ attrMapDe.put("Only at night", 1);
+ attrMapDe.put("nur bei Nacht", 1);
+ attrMapDe.put("Sólo por la noche", 1);
+ attrMapDe.put("Solo di notte", 1);
+ attrMapDe.put("All seasons", 42);
+ attrMapDe.put("ganzjähig zugänglich", 42);
+ attrMapDe.put("Todas las temporadas", 42);
+ attrMapDe.put("Tutte le stagioni", 42);
+ attrMapDe.put("Only available during specified seasons", 60);
+ attrMapDe.put("Nur zu bestimmten Zeiten im Jahr", 60);
+ attrMapDe.put("Sólo disponible durante las estaciones especificadas", 60);
+ attrMapDe.put("Disponibile solo in certe stagioni", 60);
+ attrMapDe.put("Breeding season / protected nature", 43);
+ attrMapDe.put("Brutsaison / Naturschutz", 43);
+ attrMapDe.put("Temporada de reproducción / protección de la naturaleza", 43);
+ attrMapDe.put("Stagione di riproduzione / natura protetta", 43);
+ attrMapDe.put("Available during winter", 44);
+ attrMapDe.put("schneesicheres Versteck", 44);
+ attrMapDe.put("Nieve en el escondite", 44);
+ attrMapDe.put("Luogo a prova di neve", 44);
+ attrMapDe.put("Not at high water level", 41);
+ attrMapDe.put("nicht bei Hochwasser oder Flut", 41);
+ attrMapDe.put("Compass required", 47);
+ attrMapPl.put("Compass required", 47);
+ attrMapDe.put("Potrzebny kompas", 47);
+ attrMapPl.put("Potrzebny kompas", 47);
+ attrMapDe.put("Kompass", 47);
+ attrMapPl.put("Kompass", 47);
+ attrMapDe.put("Brújula", 47);
+ attrMapPl.put("Brújula", 47);
+ attrMapDe.put("Bussola", 47);
+ attrMapPl.put("Bussola", 47);
+ attrMapPl.put("Take something to write", 48);
+ attrMapPl.put("Weź coś do pisania", 48);
+ attrMapPl.put("You may need a shovel", 81);
+ attrMapPl.put("Potrzebna łopatka", 81);
+ attrMapDe.put("Flashlight required", 48);
+ attrMapPl.put("Flashlight required", 82);
+ attrMapDe.put("Potrzebna latarka", 48);
+ attrMapPl.put("Potrzebna latarka", 82);
+ attrMapDe.put("Taschenlampe", 48);
+ attrMapPl.put("Taschenlampe", 82);
+ attrMapDe.put("Linterna", 48);
+ attrMapPl.put("Linterna", 82);
+ attrMapDe.put("Lampada tascabile", 48);
+ attrMapPl.put("Lampada tascabile", 82);
+ attrMapDe.put("Climbing gear required", 49);
+ attrMapDe.put("Kletterzeug", 49);
+ attrMapDe.put("Equipo de escalada", 49);
+ attrMapDe.put("Attrezzatura per arrampicata", 49);
+ attrMapDe.put("Cave equipment required", 50);
+ attrMapDe.put("Höhlenzeug", 50);
+ attrMapDe.put("Equipación para cuevas", 50);
+ attrMapDe.put("Attrezzatura per grotta", 50);
+ attrMapDe.put("Diving equipment required", 51);
+ attrMapDe.put("Taucherausrüstung", 51);
+ attrMapDe.put("Diving equipment", 51);
+ attrMapDe.put("Equipo de buceo", 51);
+ attrMapDe.put("Special tools required", 46);
+ attrMapPl.put("Special tools required", 83);
+ attrMapDe.put("Wymagany dodatkowy sprzęt", 46);
+ attrMapPl.put("Wymagany dodatkowy sprzęt", 83);
+ attrMapDe.put("spezielle Ausrüstung", 46);
+ attrMapPl.put("spezielle Ausrüstung", 83);
+ attrMapDe.put("Equipamiento especial", 46);
+ attrMapPl.put("Equipamiento especial", 83);
+ attrMapDe.put("Equipaggiamento speciale", 46);
+ attrMapPl.put("Equipaggiamento speciale", 83);
+ attrMapDe.put("Requires a boat", 52);
+ attrMapPl.put("Requires a boat", 86);
+ attrMapDe.put("Wymaga sprzętu pływającego", 52);
+ attrMapPl.put("Wymaga sprzętu pływającego", 86);
+ attrMapDe.put("Wasserfahrzeug", 52);
+ attrMapPl.put("Wasserfahrzeug", 86);
+ attrMapDe.put("Barca", 52);
+ attrMapPl.put("Barca", 86);
+ attrMapDe.put("Barca", 52);
+ attrMapPl.put("Barca", 86);
+ attrMapDe.put("No GPS required", 35);
+ attrMapDe.put("ohne GPS findbar", 35);
+ attrMapDe.put("Sin GPS", 35);
+ attrMapDe.put("Senza GPS", 35);
+ attrMapDe.put("Dangerous area", 9);
+ attrMapPl.put("Dangerous area", 90);
+ attrMapDe.put("Skrzynka niebezpieczna", 9);
+ attrMapPl.put("Skrzynka niebezpieczna", 90);
+ attrMapDe.put("gefährliches Gebiet", 9);
+ attrMapPl.put("gefährliches Gebiet", 90);
+ attrMapDe.put("Zona Peligrosa", 9);
+ attrMapPl.put("Zona Peligrosa", 90);
+ attrMapDe.put("Area pericolosa", 9);
+ attrMapPl.put("Area pericolosa", 90);
+ attrMapDe.put("Active railway nearby", 10);
+ attrMapDe.put("aktive Eisenbahnlinie in der Nähe", 10);
+ attrMapDe.put("Cerca del ferrocarril activo", 10);
+ attrMapDe.put("Ferrovia attiva nei pressi", 10);
+ attrMapDe.put("Cliff / Rocks", 11);
+ attrMapDe.put("Klippen / Felsen", 11);
+ attrMapDe.put("Acantilado / Rocas", 11);
+ attrMapDe.put("Scogliera / Rocce", 11);
+ attrMapDe.put("Hunting", 12);
+ attrMapDe.put("Jagdgebiet", 12);
+ attrMapDe.put("Zona de Caza", 12);
+ attrMapDe.put("Caccia", 12);
+ attrMapDe.put("Thorns", 13);
+ attrMapDe.put("Dornen", 13);
+ attrMapDe.put("Espinas", 13);
+ attrMapDe.put("Spine", 13);
+ attrMapDe.put("Ticks", 14);
+ attrMapDe.put("Zecken", 14);
+ attrMapDe.put("Garrapatas", 14);
+ attrMapDe.put("Zecche", 14);
+ attrMapDe.put("Abandoned mines", 15);
+ attrMapDe.put("Folgen des Bergbaus", 15);
+ attrMapDe.put("Mina abandonada", 15);
+ attrMapDe.put("Miniere abbandonate", 15);
+ attrMapDe.put("Poisonous plants", 16);
+ attrMapDe.put("giftige Pflanzen", 16);
+ attrMapDe.put("Planta venenosa", 16);
+ attrMapDe.put("Piante velenose", 16);
+ attrMapDe.put("Dangerous animals", 17);
+ attrMapDe.put("giftige/gefährliche Tiere", 17);
+ attrMapDe.put("Animales Peligrosos", 17);
+ attrMapDe.put("Animali pericolosi", 17);
+ attrMapPl.put("Quick cache", 40);
+ attrMapPl.put("Szybka skrzynka", 40);
+ attrMapDe.put("Overnight stay necessary", 37);
+ attrMapDe.put("Übernachtung erforderlich", 37);
+ attrMapDe.put("Necesario pernoctar", 37);
+ attrMapDe.put("Necessario pernottamento", 37);
+ attrMapPl.put("Take your children", 41);
+ attrMapPl.put("Można zabrać dzieci", 41);
+ attrMapDe.put("Suited for children (10-12 yo)", 59);
+ attrMapDe.put("kindgerecht (10-12 Jahre)", 59);
+ attrMapDe.put("Apto para niños (10-12 años)", 59);
+ attrMapDe.put("Suited for children (10-12 anni)", 59);
+ // first trailer line
+
+ }
+
+ public static int getOcDeId(final String name) {
+
+ int result = 0;
+
+ if (attrMapDe.containsKey(name)) {
+ result = attrMapDe.get(name);
+ }
+ return result;
+ }
+}
diff --git a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java
deleted file mode 100644
index 621032f..0000000
--- a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java
+++ /dev/null
@@ -1,754 +0,0 @@
-package cgeo.geocaching.connector.oc;
-
-import cgeo.geocaching.Geocache;
-import cgeo.geocaching.Image;
-import cgeo.geocaching.LogEntry;
-import cgeo.geocaching.R;
-import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgeoapplication;
-import cgeo.geocaching.connector.ConnectorFactory;
-import cgeo.geocaching.connector.IConnector;
-import cgeo.geocaching.connector.gc.GCConnector;
-import cgeo.geocaching.enumerations.CacheAttribute;
-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.content.res.Resources;
-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[] MARKUP = new String[] { "p", "span" };
- 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 final Resources res = cgeoapplication.getInstance().getResources();
-
- private static ImageHolder imageHolder = null;
-
- private static class CacheHolder {
- public Geocache cache;
- public String latitude;
- public String longitude;
- }
-
- private static class CacheLog {
- public String id;
- public String cacheId;
- public LogEntry logEntry;
- }
-
- private static class CacheDescription {
- public String cacheId;
- public String shortDesc;
- public String desc;
- public String hint;
- }
-
- private static class ImageHolder {
- public String url;
- public String objectId;
- protected String title;
- protected boolean isSpoiler = false;
- }
-
- 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;
- default:
- return CacheType.UNKNOWN;
- }
- } 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 Geocache 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 Geocache(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;
- }
-
- private static int attributeId;
-
- public static Collection<Geocache> parseCaches(final InputStream stream) throws IOException {
- // parse and return caches without filtering
- return parseCaches(stream, true);
- }
-
- public static Collection<Geocache> parseCachesFiltered(final InputStream stream) throws IOException {
- // parse caches and filter result
- return parseCaches(stream, false);
- }
-
- private static Collection<Geocache> parseCaches(final InputStream stream, boolean ignoreFiltersIn) throws IOException {
-
- final Map<String, Geocache> caches = new HashMap<String, Geocache>();
- final Map<String, LogEntry> logs = new HashMap<String, LogEntry>();
-
- 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");
-
- final boolean ignoreFilters = ignoreFiltersIn;
-
- // cache
- cacheNode.setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attributes) {
- resetCache(cacheHolder);
- }
-
- });
-
- cacheNode.setEndElementListener(new EndElementListener() {
-
- @Override
- public void end() {
- Geocache cache = cacheHolder.cache;
- Geopoint coords = new Geopoint(cacheHolder.latitude, cacheHolder.longitude);
- cache.setCoords(coords);
- if (caches.size() < CACHE_PARSE_LIMIT && isValid(cache) && (ignoreFilters || !isExcluded(cache))) {
- cache.setDetailedUpdatedNow();
- caches.put(cache.getCacheId(), cache);
- }
- }
-
- private boolean isExcluded(Geocache cache) {
- if (cache.isArchived()) {
- return true;
- }
- if (cache.isDisabled() && Settings.isExcludeDisabledCaches()) {
- return true;
- }
- if ((cache.isFound() || cache.isOwner()) && Settings.isExcludeMyCaches()) {
- return true;
- }
- return !Settings.getCacheType().contains(cache);
- }
-
- private boolean isValid(Geocache cache) {
- return StringUtils.isNotBlank(cache.getGeocode()) && !cache.getCoords().equals(Geopoint.ZERO);
- }
- });
-
- // 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(res.getString(R.string.cache_listed_on, GCConnector.getInstance().getName()) + ": <a href=\"http://coord.info/" + gccode + "\">" + gccode + "</a><br /><br />");
- }
- }
- }
- });
-
- // 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.datehidden
- cacheNode.getChild("datehidden").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- final String content = body.trim();
- cacheHolder.cache.setHidden(parseFullDate(content));
- }
- });
-
- // cache.userid
- final Element useridNode = cacheNode.getChild("userid");
-
- useridNode.setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attributes) {
- if (attributes.getIndex("id") > -1) {
- cacheHolder.cache.setOwnerUserId(attributes.getValue("id"));
- }
- }
- });
-
- useridNode.setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- cacheHolder.cache.setOwnerDisplayName(body);
- }
- });
-
- // cache.attributes.attribute
- final Element attributeNode = cacheNode.getChild("attributes").getChild("attribute");
-
- attributeNode.setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attributes) {
- if (attributes.getIndex("id") > -1) {
- try {
- attributeId = Integer.parseInt(attributes.getValue("id"));
- } catch (NumberFormatException e) {
- Log.w(String.format("Failed to parse attribute id of cache '%s'.", cacheHolder.cache.getGeocode()));
- }
- }
- }
- });
-
- attributeNode.setEndTextElementListener(new EndTextElementListener() {
- @Override
- public void end(String body) {
- CacheAttribute attribute = CacheAttribute.getByOcId(attributeId);
- if (attribute != null) {
- // semantic of attributes on opencaching is always "yes"
- cacheHolder.cache.getAttributes().add(attribute.getAttributeName(true));
- }
- else {
- 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 Geocache cache = caches.get(descHolder.cacheId);
- if (cache != null) {
- cache.setShortDescription(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(stripMarkup(content));
- }
- });
-
- // cachedesc.desc
- cacheDesc.getChild("desc").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- final String content = body.trim();
- descHolder.desc = linkify(stripMarkup(content));
- }
- });
-
- // cachedesc.hint
- cacheDesc.getChild("hint").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- descHolder.hint = body.trim();
- }
- });
-
- // 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 Geocache cache = caches.get(logHolder.cacheId);
- if (cache != null && logHolder.logEntry.type != LogType.UNKNOWN) {
- logs.put(logHolder.id, logHolder.logEntry);
- cache.getLogs().add(0, logHolder.logEntry);
- if ((logHolder.logEntry.type == LogType.FOUND_IT || logHolder.logEntry.type == LogType.ATTENDED)
- && StringUtils.equalsIgnoreCase(logHolder.logEntry.author, Settings.getOCConnectorUserName())) {
- cache.setFound(true);
- cache.setVisitedDate(logHolder.logEntry.date);
- }
- }
- }
- });
-
- // cachelog.id
- cacheLog.getChild("id").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- logHolder.id = StringUtils.trim(body);
- }
- });
-
- // 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);
- }
- });
-
- // pictures
- final Element picture = root.getChild("picture");
-
- picture.setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attrs) {
- imageHolder = new ImageHolder();
- }
- });
-
- picture.setEndElementListener(new EndElementListener() {
-
- @Override
- public void end() {
- if (imageHolder.isSpoiler) {
- final Geocache cache = caches.get(imageHolder.objectId);
- if (cache != null) {
- Image spoiler = new Image(imageHolder.url, imageHolder.title);
- cache.addSpoiler(spoiler);
- }
- }
- else {
- final LogEntry log = logs.get(imageHolder.objectId);
- if (log != null) {
- log.addLogImage(new Image(imageHolder.url, imageHolder.title));
- }
- }
- }
- });
-
- // picture.object
- picture.getChild("object").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- imageHolder.objectId = StringUtils.trim(body);
- }
- });
-
- // picture.title
- picture.getChild("title").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- imageHolder.title = StringUtils.trim(body);
- }
- });
-
- // picture.url
- picture.getChild("url").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- imageHolder.url = StringUtils.trim(body);
- }
- });
-
- // picture.attributes
- picture.getChild("attributes").setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attributes) {
- if (attributes.getIndex("spoiler") > -1) {
- String spoiler = attributes.getValue("spoiler");
- imageHolder.isSpoiler = ("1".equals(spoiler));
- }
- }
- });
-
- 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;
- }
- }
-
- /**
- * Converts local links to absolute links targeting the OC website.
- */
- 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, "<")) {
- return input;
- }
- String result = input.trim();
- for (String tagName : MARKUP) {
- final String startTag = "<" + tagName + ">";
- if (StringUtils.startsWith(result, startTag)) {
- final String endTag = "</" + tagName + ">";
- if (StringUtils.endsWith(result, endTag)) {
- String inner = result.substring(startTag.length(), result.length() - endTag.length()).trim();
- String nested = stripMarkup(inner);
- if (!nested.contains(startTag)) {
- result = nested;
- }
- }
- }
- }
- return result;
- }
-} \ 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 69cf8a4..3780c4d 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
@@ -23,7 +23,7 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode {
@Override
public String getLicenseText(final Geocache cache) {
// NOT TO BE TRANSLATED
- return "<a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a> data licensed under the Creative Commons BY-SA 3.0 License";
+ return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a>, CC-BY-NC-ND, alle Logeinträge © jeweiliger Autor";
}
@Override
@@ -40,4 +40,8 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode {
// currently always active, but only for details download
return true;
}
+
+ public String getCK() {
+ return CryptUtils.rot13(cK);
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
new file mode 100644
index 0000000..4e57831
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
@@ -0,0 +1,82 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.cgData;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.connector.ILoggingManager;
+import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByViewPort;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.Viewport;
+import cgeo.geocaching.utils.CryptUtils;
+
+import android.app.Activity;
+
+public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort {
+
+ private String cS;
+
+ public OCApiLiveConnector(String name, String host, String prefix, int cKResId, int cSResId) {
+ super(name, host, prefix, CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cKResId)));
+
+ cS = CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cSResId));
+ }
+
+ @Override
+ public SearchResult searchByViewport(Viewport viewport, String[] tokens) {
+ return new SearchResult(OkapiClient.getCachesBBox(viewport, this));
+ }
+
+ @Override
+ public SearchResult searchByCenter(Geopoint center) {
+
+ return new SearchResult(OkapiClient.getCachesAround(center, this));
+ }
+
+ public String getCS() {
+ return CryptUtils.rot13(cS);
+ }
+
+ @Override
+ public boolean supportsWatchList() {
+ return true;
+ }
+
+ @Override
+ public boolean addToWatchlist(Geocache cache) {
+ final boolean added = OkapiClient.setWatchState(cache, true, this);
+
+ if (added) {
+ cgData.saveChangedCache(cache);
+ }
+
+ return added;
+ }
+
+ @Override
+ public boolean removeFromWatchlist(Geocache cache) {
+ final boolean removed = OkapiClient.setWatchState(cache, false, this);
+
+ if (removed) {
+ cgData.saveChangedCache(cache);
+ }
+
+ return removed;
+ }
+
+ @Override
+ public boolean supportsLogging() {
+ return true;
+ }
+
+ @Override
+ public ILoggingManager getLoggingManager(Activity activity, Geocache cache) {
+ return new OkapiLoggingManager(activity, this, cache);
+ }
+
+ @Override
+ public boolean canLog(Geocache cache) {
+ return true;
+ }
+}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java
new file mode 100644
index 0000000..779c1c5
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java
@@ -0,0 +1,109 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.network.OAuthAuthorizationActivity;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+
+public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
+
+ private final int siteResId = R.string.auth_ocde;
+
+ public OCAuthorizationActivity() {
+ super("www.opencaching.de",
+ "/okapi/services/oauth/request_token",
+ "/okapi/services/oauth/authorize",
+ "/okapi/services/oauth/access_token",
+ false,
+ cgeoapplication.getInstance().getResources().getString(R.string.oc_de_okapi_consumer_key),
+ cgeoapplication.getInstance().getResources().getString(R.string.oc_de_okapi_consumer_secret));
+ }
+
+ @Override
+ protected ImmutablePair<String, String> getTempToken() {
+ return Settings.getTempOCDEToken();
+ }
+
+ @Override
+ protected void setTempTokens(String tokenPublic, String tokenSecret) {
+ Settings.setOCDETempTokens(tokenPublic, tokenSecret);
+ }
+
+ @Override
+ protected void setTokens(String tokenPublic, String tokenSecret, boolean enable) {
+ Settings.setOCDETokens(tokenPublic, tokenSecret, enable);
+ }
+
+ @Override
+ protected String getAuthTitle() {
+ return res.getString(siteResId);
+ }
+
+ @Override
+ protected String getAuthAgain() {
+ return res.getString(R.string.auth_again_oc);
+ }
+
+ @Override
+ protected String getErrAuthInitialize() {
+ return res.getString(R.string.err_auth_initialize);
+ }
+
+ @Override
+ protected String getAuthStart() {
+ return res.getString(R.string.auth_start_oc);
+ }
+
+ @Override
+ protected String getAuthDialogCompleted() {
+ return res.getString(R.string.auth_dialog_completed_oc, getAuthTitle());
+ }
+
+ @Override
+ protected String getErrAuthProcess() {
+ return res.getString(R.string.err_auth_process);
+ }
+
+ @Override
+ protected String getAuthDialogWait() {
+ return res.getString(R.string.auth_dialog_wait_oc, getAuthTitle());
+ }
+
+ @Override
+ protected String getAuthDialogPinTitle() {
+ return res.getString(R.string.auth_dialog_pin_title_oc);
+ }
+
+ @Override
+ protected String getAuthDialogPinMessage() {
+ return res.getString(R.string.auth_dialog_pin_message_oc, getAuthTitle());
+ }
+
+ @Override
+ protected String getAboutAuth1() {
+ return res.getString(R.string.about_auth_1_oc, getAuthTitle());
+ }
+
+ @Override
+ protected String getAboutAuth2() {
+ return res.getString(R.string.about_auth_2_oc, getAuthTitle(), getAuthTitle());
+ }
+
+ @Override
+ protected String getAuthAuthorize() {
+ return res.getString(R.string.auth_authorize_oc);
+ }
+
+ @Override
+ protected String getAuthPinHint() {
+ return res.getString(R.string.auth_pin_hint_oc, getAuthTitle());
+ }
+
+ @Override
+ protected String getAuthFinish() {
+ return res.getString(R.string.auth_finish_oc);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java
deleted file mode 100644
index 43fdcfc..0000000
--- a/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package cgeo.geocaching.connector.oc;
-
-import cgeo.geocaching.Geocache;
-import cgeo.geocaching.ICache;
-import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.Settings;
-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.ui.Formatter;
-import cgeo.geocaching.utils.CancellableHandler;
-
-import org.apache.commons.lang3.StringUtils;
-
-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 Geocache 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();
- }
-
- @Override
- public boolean isOwner(ICache cache) {
- return StringUtils.equalsIgnoreCase(cache.getOwnerDisplayName(), Settings.getOCConnectorUserName());
- }
-
- @Override
- public String getLicenseText(Geocache cache) {
- // not to be translated
- return "© " + cache.getOwnerDisplayName() + ", " + "<a href=\"" + getCacheUrl(cache) + "\">www.opencaching.de</a>, CC-BY-NC-ND, Stand: " + Formatter.formatFullDate(cache.getUpdated());
- }
-
-}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java b/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java
deleted file mode 100644
index 6767b48..0000000
--- a/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package cgeo.geocaching.connector.oc;
-
-import cgeo.geocaching.Geocache;
-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 Geocache getCache(final String geoCode) {
- try {
- final Parameters params = getOCXmlQueryParameters(true, true, true);
- params.put("wp", geoCode);
- final InputStream data = request(ConnectorFactory.getConnector(geoCode), SERVICE_CACHE, params);
-
- if (data == null) {
- return null;
- }
-
- Collection<Geocache> caches = OC11XMLParser.parseCaches(new GZIPInputStream(data));
- if (caches.iterator().hasNext()) {
- Geocache 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<Geocache> getCachesAround(final Geopoint center, final double distance) {
- try {
- final Parameters params = getOCXmlQueryParameters(false, 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.parseCachesFiltered(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 boolean withImages) {
- return new Parameters("modifiedsince", "20000101000000",
- "user", "0",
- "cache", "1",
- "cachedesc", withDescription ? "1" : "0",
- "cachelog", withLogs ? "1" : "0",
- "picture", withImages ? "1" : "0",
- "removedobject", "0",
- "session", "0",
- "doctype", "0",
- "charset", "utf-8",
- "zip", "gzip",
- "picturefromcachelog", withImages ? "1" : "0");
- }
-}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 0673605..d8d92e1 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -3,16 +3,27 @@ package cgeo.geocaching.connector.oc;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.Image;
import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.cgData;
+import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
+import cgeo.geocaching.connector.LogResult;
+import cgeo.geocaching.connector.gc.GCConnector;
+import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.enumerations.StatusCode;
+import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.network.Network;
+import cgeo.geocaching.network.OAuth;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.Log;
@@ -22,17 +33,40 @@ import org.json.JSONException;
import org.json.JSONObject;
import android.net.Uri;
-import android.text.Html;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
final public class OkapiClient {
+
+ private static final SimpleDateFormat logDateFormat;
+
+ static {
+ logDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.US);
+ logDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
+
+ private static final String CACHE_ATTRNAMES = "attrnames";
+ private static final String WPT_LOCATION = "location";
+ private static final String WPT_DESCRIPTION = "description";
+ private static final String WPT_TYPE = "type";
+ private static final String WPT_NAME = "name";
+ private static final String CACHE_IS_WATCHED = "is_watched";
+ private static final String CACHE_WPTS = "alt_wpts";
+ private static final String CACHE_STATUS_ARCHIVED = "Archived";
+ private static final String CACHE_STATUS_DISABLED = "Temporarily unavailable";
+ private static final String CACHE_IS_FOUND = "is_found";
private static final String CACHE_SIZE = "size";
private static final String CACHE_VOTES = "rating_votes";
private static final String CACHE_NOTFOUNDS = "notfounds";
@@ -64,12 +98,22 @@ final public class OkapiClient {
private static final String USER_USERNAME = "username";
private static final String SERVICE_CACHE = "/okapi/services/caches/geocache";
- private static final String SERVICE_CACHE_FIELDS = "code|name|location|type|status|owner|founds|notfounds|size|difficulty|terrain|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden";
- private static final String SERVICE_NEAREST = "/okapi/services/caches/search/nearest";
+ private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size|is_found";
+ private static final String SERVICE_CACHE_FIELDS = SERVICE_CACHE_CORE_FIELDS + "|owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden|attribution_note|alt_wpts|is_watched|attrnames|gc_code";
+
+ private static final String SERVICE_SEARCH_AND_RETRIEVE = "/okapi/services/caches/shortcuts/search_and_retrieve";
+
+ private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest";
+ private static final String METHOD_SEARCH_BBOX = "services/caches/search/bbox";
+ private static final String METHOD_RETRIEVE_CACHES = "services/caches/geocaches";
+
+ private static final String SERVICE_MARK_CACHE = "/okapi/services/caches/mark";
+
+ private static final String SERVICE_SUBMIT_LOG = "/okapi/services/logs/submit";
public static Geocache getCache(final String geoCode) {
- final Parameters params = new Parameters("cache_code", geoCode, "fields", SERVICE_CACHE_FIELDS);
+ final Parameters params = new Parameters("cache_code", geoCode, "fields", SERVICE_CACHE_FIELDS, "attribution_append", "none");
final JSONObject data = request(ConnectorFactory.getConnector(geoCode), SERVICE_CACHE, params);
if (data == null) {
@@ -81,30 +125,115 @@ final public class OkapiClient {
public static List<Geocache> getCachesAround(final Geopoint center, IConnector connector) {
String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + "|" + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center);
- final Parameters params = new Parameters("center", centerString);
- final JSONObject data = request(connector, SERVICE_NEAREST, params);
+ final Parameters params = new Parameters("search_method", METHOD_SEARCH_NEAREST);
+ final Map<String, String> valueMap = new LinkedHashMap<String, String>();
+ valueMap.put("center", centerString);
+ valueMap.put("limit", "20");
+
+ addFilterParams(valueMap);
+
+ params.add("search_params", new JSONObject(valueMap).toString());
+
+ addRetrieveParams(params);
+
+ final JSONObject data = request(connector, SERVICE_SEARCH_AND_RETRIEVE, params);
if (data == null) {
- return null;
+ return Collections.emptyList();
+ }
+
+ return parseCaches(data);
+ }
+
+ public static List<Geocache> getCachesBBox(final Viewport viewport, IConnector connector) {
+
+ if (viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) {
+ return Collections.emptyList();
+ }
+
+ String bboxString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.bottomLeft)
+ + "|" + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, viewport.bottomLeft)
+ + "|" + GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.topRight)
+ + "|" + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, viewport.topRight);
+ final Parameters params = new Parameters("search_method", METHOD_SEARCH_BBOX);
+ final Map<String, String> valueMap = new LinkedHashMap<String, String>();
+ valueMap.put("bbox", bboxString);
+
+ addFilterParams(valueMap);
+
+ params.add("search_params", new JSONObject(valueMap).toString());
+
+ addRetrieveParams(params);
+
+ final JSONObject data = request(connector, SERVICE_SEARCH_AND_RETRIEVE, params);
+
+ if (data == null) {
+ return Collections.emptyList();
}
return parseCaches(data);
}
+ public static boolean setWatchState(final Geocache cache, final boolean watched, IConnector connector) {
+ final Parameters params = new Parameters("cache_code", cache.getGeocode());
+ params.add("watched", watched ? "true" : "false");
+
+ final JSONObject data = request(connector, SERVICE_MARK_CACHE, params);
+
+ if (data == null) {
+ return false;
+ }
+
+ cache.setOnWatchlist(watched);
+
+ return true;
+ }
+
+ public static LogResult postLog(final Geocache cache, LogType logType, Calendar date, String log, IConnector connector) {
+ final Parameters params = new Parameters("cache_code", cache.getGeocode());
+ params.add("logtype", logType.oc_type);
+ params.add("comment", log);
+ params.add("comment_format", "plaintext");
+ params.add("when", logDateFormat.format(date.getTime()));
+ if (logType.equals(LogType.NEEDS_MAINTENANCE)) {
+ params.add("needs_maintenance", "true");
+ }
+
+ final JSONObject data = request(connector, SERVICE_SUBMIT_LOG, params);
+
+ if (data == null) {
+ return new LogResult(StatusCode.LOG_POST_ERROR, "");
+ }
+
+ try {
+ if (data.getBoolean("success")) {
+ return new LogResult(StatusCode.NO_ERROR, data.getString("log_uuid"));
+ }
+
+ return new LogResult(StatusCode.LOG_POST_ERROR, "");
+ } catch (JSONException e) {
+ Log.e("OkapiClient.postLog", e);
+ }
+ return new LogResult(StatusCode.LOG_POST_ERROR, "");
+ }
+
private static List<Geocache> parseCaches(final JSONObject response) {
try {
- final JSONArray cachesResponse = response.getJSONArray("results");
+ // Check for empty result
+ final String result = response.getString("results");
+ if (StringUtils.isBlank(result) || StringUtils.equals(result, "[]")) {
+ return Collections.emptyList();
+ }
+
+ // Get and iterate result list
+ final JSONObject cachesResponse = response.getJSONObject("results");
if (cachesResponse != null) {
- ArrayList<String> geocodes = new ArrayList<String>(cachesResponse.length());
- for (int i = 0; i < cachesResponse.length(); i++) {
- String geocode = cachesResponse.getString(i);
- if (StringUtils.isNotBlank(geocode)) {
- geocodes.add(geocode);
- }
- }
- List<Geocache> caches = new ArrayList<Geocache>(geocodes.size());
- for (String geocode : geocodes) {
- Geocache cache = getCache(geocode);
+ List<Geocache> caches = new ArrayList<Geocache>(cachesResponse.length());
+ @SuppressWarnings("unchecked")
+ Iterator<String> keys = cachesResponse.keys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key));
if (cache != null) {
caches.add(cache);
}
@@ -112,24 +241,31 @@ final public class OkapiClient {
return caches;
}
} catch (JSONException e) {
- Log.e("OkapiClient.parseCaches", e);
+ Log.e("OkapiClient.parseCachesResult", e);
}
- return null;
+ return Collections.emptyList();
+ }
+
+ private static Geocache parseSmallCache(final JSONObject response) {
+ final Geocache cache = new Geocache();
+ cache.setReliableLatLon(true);
+ try {
+
+ parseCoreCache(response, cache);
+
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
+ } catch (JSONException e) {
+ Log.e("OkapiClient.parseSmallCache", e);
+ }
+ return cache;
}
private static Geocache parseCache(final JSONObject response) {
final Geocache cache = new Geocache();
cache.setReliableLatLon(true);
try {
- cache.setGeocode(response.getString(CACHE_CODE));
- cache.setName(response.getString(CACHE_NAME));
- // not used: names
- setLocation(cache, response.getString(CACHE_LOCATION));
- cache.setType(getCacheType(response.getString(CACHE_TYPE)));
- final String status = response.getString(CACHE_STATUS);
- cache.setDisabled(status.equalsIgnoreCase("Temporarily unavailable"));
- cache.setArchived(status.equalsIgnoreCase("Archived"));
+ parseCoreCache(response, cache);
// not used: url
final JSONObject owner = response.getJSONObject(CACHE_OWNER);
@@ -137,9 +273,7 @@ final public class OkapiClient {
cache.getLogCounts().put(LogType.FOUND_IT, response.getInt(CACHE_FOUNDS));
cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.getInt(CACHE_NOTFOUNDS));
- cache.setSize(getCacheSize(response));
- cache.setDifficulty((float) response.getDouble(CACHE_DIFFICULTY));
- cache.setTerrain((float) response.getDouble(CACHE_TERRAIN));
+
if (!response.isNull(CACHE_RATING)) {
cache.setRating((float) response.getDouble(CACHE_RATING));
}
@@ -147,8 +281,22 @@ final public class OkapiClient {
cache.setFavoritePoints(response.getInt(CACHE_RECOMMENDATIONS));
// not used: req_password
- cache.setDescription(response.getString(CACHE_DESCRIPTION));
- cache.setHint(Html.fromHtml(response.getString(CACHE_HINT)).toString());
+ // Prepend gc-link to description if available
+ StringBuilder description = new StringBuilder(500);
+ if (!response.isNull("gc_code")) {
+ String gccode = response.getString("gc_code");
+ description.append(cgeoapplication.getInstance().getResources()
+ .getString(R.string.cache_listed_on, GCConnector.getInstance().getName()))
+ .append(": <a href=\"http://coord.info/")
+ .append(gccode)
+ .append("\">")
+ .append(gccode)
+ .append("</a><br /><br />");
+ }
+ description.append(response.getString(CACHE_DESCRIPTION));
+ cache.setDescription(description.toString());
+
+ cache.setHint(response.getString(CACHE_HINT));
// not used: hints
final JSONArray images = response.getJSONArray(CACHE_IMAGES);
@@ -163,9 +311,13 @@ final public class OkapiClient {
}
}
- // not used: attrnames
+ cache.setAttributes(parseAttributes(response.getJSONArray(CACHE_ATTRNAMES)));
cache.setLogs(parseLogs(response.getJSONArray(CACHE_LATEST_LOGS)));
cache.setHidden(parseDate(response.getString(CACHE_HIDDEN)));
+ //TODO: Store license per cache
+ //cache.setLicense(response.getString("attribution_note"));
+ cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false);
+ cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED));
cache.setDetailedUpdatedNow();
// save full detailed caches
@@ -176,6 +328,24 @@ final public class OkapiClient {
return cache;
}
+ private static void parseCoreCache(final JSONObject response, final Geocache cache) throws JSONException {
+ cache.setGeocode(response.getString(CACHE_CODE));
+ cache.setName(response.getString(CACHE_NAME));
+ // not used: names
+ setLocation(cache, response.getString(CACHE_LOCATION));
+ cache.setType(getCacheType(response.getString(CACHE_TYPE)));
+
+ final String status = response.getString(CACHE_STATUS);
+ cache.setDisabled(status.equalsIgnoreCase(CACHE_STATUS_DISABLED));
+ cache.setArchived(status.equalsIgnoreCase(CACHE_STATUS_ARCHIVED));
+
+ cache.setSize(getCacheSize(response));
+ cache.setDifficulty((float) response.getDouble(CACHE_DIFFICULTY));
+ cache.setTerrain((float) response.getDouble(CACHE_TERRAIN));
+
+ cache.setFound(response.getBoolean(CACHE_IS_FOUND));
+ }
+
private static String absoluteUrl(String url, String geocode) {
final Uri uri = Uri.parse(url);
@@ -214,6 +384,30 @@ final public class OkapiClient {
return result;
}
+ private static List<Waypoint> parseWaypoints(JSONArray wptsJson) {
+ List<Waypoint> result = null;
+ for (int i = 0; i < wptsJson.length(); i++) {
+ try {
+ JSONObject wptResponse = wptsJson.getJSONObject(i);
+ Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME),
+ parseWptType(wptResponse.getString(WPT_TYPE)),
+ false);
+ wpt.setNote(wptResponse.getString(WPT_DESCRIPTION));
+ Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION));
+ if (pt != null) {
+ wpt.setCoords(pt);
+ }
+ if (result == null) {
+ result = new ArrayList<Waypoint>();
+ }
+ result.add(wpt);
+ } catch (JSONException e) {
+ Log.e("OkapiClient.parseWaypoints", e);
+ }
+ }
+ return result;
+ }
+
private static LogType parseLogType(String logType) {
if ("Found it".equalsIgnoreCase(logType)) {
return LogType.FOUND_IT;
@@ -224,6 +418,31 @@ final public class OkapiClient {
return LogType.NOTE;
}
+ private static WaypointType parseWptType(String wptType) {
+ if ("parking".equalsIgnoreCase(wptType)) {
+ return WaypointType.PARKING;
+ }
+ if ("path".equalsIgnoreCase(wptType)) {
+ return WaypointType.TRAILHEAD;
+ }
+ if ("stage".equalsIgnoreCase(wptType)) {
+ return WaypointType.STAGE;
+ }
+ if ("physical-stage".equalsIgnoreCase(wptType)) {
+ return WaypointType.STAGE;
+ }
+ if ("virtual-stage".equalsIgnoreCase(wptType)) {
+ return WaypointType.PUZZLE;
+ }
+ if ("final".equalsIgnoreCase(wptType)) {
+ return WaypointType.FINAL;
+ }
+ if ("poi".equalsIgnoreCase(wptType)) {
+ return WaypointType.TRAILHEAD;
+ }
+ return WaypointType.WAYPOINT;
+ }
+
private static Date parseDate(final String date) {
final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
final String strippedDate = date.replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
@@ -235,6 +454,36 @@ final public class OkapiClient {
return null;
}
+ private static Geopoint parseCoords(final String location) {
+ final String latitude = StringUtils.substringBefore(location, "|");
+ final String longitude = StringUtils.substringAfter(location, "|");
+ if (StringUtils.isNotBlank(latitude) && StringUtils.isNotBlank(longitude)) {
+ return new Geopoint(latitude, longitude);
+ }
+
+ return null;
+ }
+
+ private static List<String> parseAttributes(JSONArray nameList) {
+
+ List<String> result = new ArrayList<String>();
+
+ for (int i = 0; i < nameList.length(); i++) {
+ try {
+ String name = nameList.getString(i);
+ CacheAttribute attr = CacheAttribute.getByOcId(AttributeParser.getOcDeId(name));
+
+ if (attr != null) {
+ result.add(attr.rawName);
+ }
+ } catch (JSONException e) {
+ Log.e("OkapiClient.parseAttributes", e);
+ }
+ }
+
+ return result;
+ }
+
private static void setLocation(final Geocache cache, final String location) {
final String latitude = StringUtils.substringBefore(location, "|");
final String longitude = StringUtils.substringAfter(location, "|");
@@ -281,6 +530,18 @@ final public class OkapiClient {
if (cacheType.equalsIgnoreCase("Virtual")) {
return CacheType.VIRTUAL;
}
+ if (cacheType.equalsIgnoreCase("Event")) {
+ return CacheType.EVENT;
+ }
+ if (cacheType.equalsIgnoreCase("Webcam")) {
+ return CacheType.WEBCAM;
+ }
+ if (cacheType.equalsIgnoreCase("Math/Physics")) {
+ return CacheType.MYSTERY;
+ }
+ if (cacheType.equalsIgnoreCase("Drive-In")) {
+ return CacheType.TRADITIONAL;
+ }
return CacheType.UNKNOWN;
}
@@ -297,9 +558,10 @@ final public class OkapiClient {
return null;
}
- ((OCApiConnector) connector).addAuthentication(params);
params.add("langpref", getPreferredLanguage());
+ OAuth.signOAuth(host, service, "GET", false, params, Settings.getOCDETokenPublic(), Settings.getOCDETokenSecret(), ((OCApiLiveConnector) connector).getCK(), ((OCApiLiveConnector) connector).getCS());
+
final String uri = "http://" + host + service;
return Network.requestJSON(uri, params);
}
@@ -311,4 +573,43 @@ final public class OkapiClient {
}
return "en";
}
+
+ private static void addFilterParams(final Map<String, String> valueMap) {
+ if (!Settings.isExcludeDisabledCaches()) {
+ valueMap.put("status", "Available|Temporarily unavailable");
+ }
+ if (Settings.isExcludeMyCaches()) {
+ valueMap.put("exclude_my_own", "true");
+ valueMap.put("found_status", "notfound_only");
+ }
+ if (Settings.getCacheType() != CacheType.ALL) {
+ valueMap.put("type", getFilterFromType(Settings.getCacheType()));
+ }
+ }
+
+ private static void addRetrieveParams(final Parameters params) {
+ params.add("retr_method", METHOD_RETRIEVE_CACHES);
+ params.add("retr_params", "{\"fields\": \"" + SERVICE_CACHE_CORE_FIELDS + "\"}");
+ params.add("wrap", "true");
+ }
+
+ private static String getFilterFromType(CacheType cacheType) {
+ switch (cacheType) {
+ case EVENT:
+ return "Event";
+ case MULTI:
+ return "Multi";
+ case MYSTERY:
+ return "Quiz";
+ case TRADITIONAL:
+ return "Traditional";
+ case VIRTUAL:
+ return "Virtual";
+ case WEBCAM:
+ return "Webcam";
+ default:
+ return "";
+ }
+ }
+
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
new file mode 100644
index 0000000..24c6b79
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
@@ -0,0 +1,69 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.TrackableLog;
+import cgeo.geocaching.VisitCacheActivity;
+import cgeo.geocaching.connector.IConnector;
+import cgeo.geocaching.connector.ILoggingManager;
+import cgeo.geocaching.connector.ImageResult;
+import cgeo.geocaching.connector.LogResult;
+import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.enumerations.StatusCode;
+
+import android.app.Activity;
+import android.net.Uri;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.List;
+
+public class OkapiLoggingManager implements ILoggingManager {
+
+ private final IConnector connector;
+ private final Geocache cache;
+ private VisitCacheActivity activity;
+
+ private final static List<LogType> standardLogTypes = Arrays.asList(LogType.FOUND_IT, LogType.DIDNT_FIND_IT, LogType.NOTE, LogType.NEEDS_MAINTENANCE);
+ private final static List<LogType> eventLogTypes = Arrays.asList(LogType.WILL_ATTEND, LogType.ATTENDED, LogType.NOTE);
+
+ public OkapiLoggingManager(Activity activity, IConnector connector, Geocache cache) {
+ this.connector = connector;
+ this.cache = cache;
+ this.activity = (VisitCacheActivity) activity;
+ }
+
+ @Override
+ public void init() {
+ activity.onLoadFinished();
+ }
+
+ @Override
+ public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) {
+ return OkapiClient.postLog(cache, logType, date, log, connector);
+ }
+
+ @Override
+ public ImageResult postLogImage(String logId, String imageCaption, String imageDescription, Uri imageUri) {
+ return new ImageResult(StatusCode.LOG_POST_ERROR, "");
+ }
+
+ @Override
+ public boolean hasLoaderError() {
+ return false;
+ }
+
+ @Override
+ public List<TrackableLog> getTrackables() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<LogType> getPossibleLogTypes() {
+ if (cache.isEventCache()) {
+ return eventLogTypes;
+ }
+
+ return standardLogTypes;
+ }
+}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
index 530869f..243f63d 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
@@ -12,8 +12,8 @@ import java.util.HashMap;
import java.util.Map;
public enum CacheAttribute {
- // THIS LIST IS GENERATED: don't change anything here but in
- // project/attributes/makeEnum.sh
+ // THIS LIST IS GENERATED: don't change anything here but read
+ // project/attributes/readme.txt
DOGS(1, -1, "dogs", R.drawable.attribute_dogs, R.string.attribute_dogs_yes, R.string.attribute_dogs_no),
BICYCLES(32, -1, "bicycles", R.drawable.attribute_bicycles, R.string.attribute_bicycles_yes, R.string.attribute_bicycles_no),
MOTORCYCLES(33, -1, "motorcycles", R.drawable.attribute_motorcycles, R.string.attribute_motorcycles_yes, R.string.attribute_motorcycles_no),
@@ -27,7 +27,7 @@ public enum CacheAttribute {
ONEHOUR(7, -1, "onehour", R.drawable.attribute_onehour, R.string.attribute_onehour_yes, R.string.attribute_onehour_no),
SCENIC(8, -1, "scenic", R.drawable.attribute_scenic, R.string.attribute_scenic_yes, R.string.attribute_scenic_no),
HIKING(9, 25, "hiking", R.drawable.attribute_hiking, R.string.attribute_hiking_yes, R.string.attribute_hiking_no),
- CLIMBING(10, 28, "climbing", R.drawable.attribute_climbing, R.string.attribute_climbing_yes, R.string.attribute_climbing_no),
+ CLIMBING(10, -1, "climbing", R.drawable.attribute_climbing, R.string.attribute_climbing_yes, R.string.attribute_climbing_no),
WADING(11, -1, "wading", R.drawable.attribute_wading, R.string.attribute_wading_yes, R.string.attribute_wading_no),
SWIMMING(12, 29, "swimming", R.drawable.attribute_swimming, R.string.attribute_swimming_yes, R.string.attribute_swimming_no),
AVAILABLE(13, 38, "available", R.drawable.attribute_available, R.string.attribute_available_yes, R.string.attribute_available_no),
@@ -86,6 +86,7 @@ public enum CacheAttribute {
SYRINGE(-1, 23, "syringe", R.drawable.attribute_syringe, R.string.attribute_syringe_yes, R.string.attribute_syringe_no),
SWAMP(-1, 26, "swamp", R.drawable.attribute_swamp, R.string.attribute_swamp_yes, R.string.attribute_swamp_no),
HILLS(-1, 27, "hills", R.drawable.attribute_hills, R.string.attribute_hills_yes, R.string.attribute_hills_no),
+ EASY_CLIMBING(-1, 28, "easy_climbing", R.drawable.attribute_easy_climbing, R.string.attribute_easy_climbing_yes, R.string.attribute_easy_climbing_no),
POI(-1, 30, "poi", R.drawable.attribute_poi, R.string.attribute_poi_yes, R.string.attribute_poi_no),
MOVING_TARGET(-1, 31, "moving_target", R.drawable.attribute_moving_target, R.string.attribute_moving_target_yes, R.string.attribute_moving_target_no),
WEBCAM(-1, 32, "webcam", R.drawable.attribute_webcam, R.string.attribute_webcam_yes, R.string.attribute_webcam_no),
@@ -107,9 +108,10 @@ public enum CacheAttribute {
ARITHMETIC(-1, 56, "arithmetic", R.drawable.attribute_arithmetic, R.string.attribute_arithmetic_yes, R.string.attribute_arithmetic_no),
OTHER_CACHE(-1, 57, "other_cache", R.drawable.attribute_other_cache, R.string.attribute_other_cache_yes, R.string.attribute_other_cache_no),
ASK_OWNER(-1, 58, "ask_owner", R.drawable.attribute_ask_owner, R.string.attribute_ask_owner_yes, R.string.attribute_ask_owner_no),
- UNKNOWN(-1, -1, "unknown", R.drawable.attribute_unknown, R.string.attribute_unknown_yes, R.string.attribute_unknown_no);
- // THIS LIST IS GENERATED: don't change anything here but in
- // project/attributes/makeEnum.sh
+ UNKNOWN(-1, -1, "unknown", R.drawable.attribute_unknown, R.string.attribute_unknown_yes, R.string.attribute_unknown_no),
+ GEOTOUR(67, -1, "geotour", R.drawable.attribute_geotour, R.string.attribute_geotour_yes, R.string.attribute_geotour_no);
+ // THIS LIST IS GENERATED: don't change anything here but read
+ // project/attributes/readme.txt
private static final String INTERNAL_YES = "_yes";
private static final String INTERNAL_NO = "_no";
@@ -146,30 +148,20 @@ public enum CacheAttribute {
}
private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME;
+ private final static SparseArray<CacheAttribute> FIND_BY_GCID = new SparseArray<CacheAttribute>();
+ private final static SparseArray<CacheAttribute> FIND_BY_OCID = new SparseArray<CacheAttribute>();
static {
final HashMap<String, CacheAttribute> mapGcRawNames = new HashMap<String, CacheAttribute>();
for (CacheAttribute attr : values()) {
mapGcRawNames.put(attr.rawName, attr);
- }
- FIND_BY_GCRAWNAME = Collections.unmodifiableMap(mapGcRawNames);
- }
-
- private final static SparseArray<CacheAttribute> FIND_BY_GCID = new SparseArray<CacheAttribute>();
- static {
- for (CacheAttribute attr : values()) {
if (attr.gcid != NO_ID) {
FIND_BY_GCID.put(attr.gcid, attr);
}
- }
- }
-
- private final static SparseArray<CacheAttribute> FIND_BY_OCID = new SparseArray<CacheAttribute>();
- static {
- for (CacheAttribute attr : values()) {
if (attr.ocid != NO_ID) {
FIND_BY_OCID.put(attr.ocid, attr);
}
}
+ FIND_BY_GCRAWNAME = Collections.unmodifiableMap(mapGcRawNames);
}
public static CacheAttribute getByRawName(final String rawName) {
diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java
index 528d3fa..8dbadfd 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheType.java
@@ -29,6 +29,7 @@ public enum CacheType {
PROJECT_APE("ape", "Project Ape Cache", "2555690d-b2bc-4b55-b5ac-0cb704c0b768", R.string.ape, R.drawable.type_ape),
GCHQ("gchq", "Groundspeak HQ", "416f2494-dc17-4b6a-9bab-1a29dd292d8c", R.string.gchq, R.drawable.type_hq),
GPS_EXHIBIT("gps", "GPS Cache Exhibit", "72e69af2-7986-4990-afd9-bc16cbbb4ce3", R.string.gps, R.drawable.type_traditional), // icon missing
+ BLOCK_PARTY("block", "Groundspeak Block Party", "bc2f3df2-1aab-4601-b2ff-b5091f6c02e3", R.string.block, R.drawable.type_event), // icon missing
UNKNOWN("unknown", "unknown", "", R.string.unknown, R.drawable.type_unknown),
/** No real cache type -> filter */
ALL("all", "display all caches", "9a79e6ce-3344-409c-bbe9-496530baf758", R.string.all_types, R.drawable.type_unknown);
@@ -88,7 +89,8 @@ public enum CacheType {
}
public boolean isEvent() {
- return CacheType.EVENT == this || CacheType.MEGA_EVENT == this || CacheType.CITO == this || CacheType.LOSTANDFOUND == this;
+ return CacheType.EVENT == this || CacheType.MEGA_EVENT == this || CacheType.CITO == this ||
+ CacheType.LOSTANDFOUND == this || CacheType.BLOCK_PARTY == this;
}
@Override
@@ -98,7 +100,7 @@ public enum CacheType {
/**
* Whether this type contains the given cache.
- *
+ *
* @param cache
* @return true if this is the ALL type or if this type equals the type of the cache.
*/
@@ -111,4 +113,12 @@ public enum CacheType {
}
return cache.getType() == this;
}
+
+ public boolean applyDistanceRule() {
+ return !isVirtual() && !isEvent();
+ }
+
+ public boolean isVirtual() {
+ return VIRTUAL == this || WEBCAM == this || EARTH == this;
+ }
}
diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java
index 71a5146..9902d3f 100644
--- a/main/src/cgeo/geocaching/enumerations/LogType.java
+++ b/main/src/cgeo/geocaching/enumerations/LogType.java
@@ -15,50 +15,52 @@ import java.util.Map;
*/
public enum LogType {
- 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, 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, 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, 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, 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),
- 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
+ FOUND_IT(2, "2", "found it", "Found it", R.string.log_found, R.drawable.mark_green),
+ DIDNT_FIND_IT(3, "3", "didn't find it", "Didn't find it", R.string.log_dnf, R.drawable.mark_red),
+ NOTE(4, "4", "write note", "Comment", R.string.log_note),
+ 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", "Will attend", R.string.log_attend),
+ ATTENDED(10, "10", "attended", "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", "Comment", 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, 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, 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),
+ 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;
+ public final String oc_type;
private final int stringId;
public final int markerId;
- LogType(int id, String iconName, String type, int stringId, int markerId) {
+ LogType(int id, String iconName, String type, String oc_type, int stringId, int markerId) {
this.id = id;
this.iconName = iconName;
this.type = type;
+ this.oc_type = oc_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);
+ LogType(int id, String iconName, String type, String oc_type, int stringId) {
+ this(id, iconName, type, oc_type, stringId, R.drawable.mark_gray);
}
private final static Map<String, LogType> FIND_BY_ICONNAME;
diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java
index 748c432..79c8106 100644
--- a/main/src/cgeo/geocaching/enumerations/WaypointType.java
+++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java
@@ -72,4 +72,8 @@ public enum WaypointType {
public final String toString() {
return getL10n();
}
+
+ public boolean applyDistanceRule() {
+ return (this == FINAL || this == STAGE);
+ }
}
diff --git a/main/src/cgeo/geocaching/export/AbstractExport.java b/main/src/cgeo/geocaching/export/AbstractExport.java
index 72ea544..e4ba5f0 100644
--- a/main/src/cgeo/geocaching/export/AbstractExport.java
+++ b/main/src/cgeo/geocaching/export/AbstractExport.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.export;
+import cgeo.geocaching.R;
import cgeo.geocaching.cgeoapplication;
abstract class AbstractExport implements Export {
@@ -27,7 +28,7 @@ abstract class AbstractExport implements Export {
/**
* Generates a localized string from a resource id.
- *
+ *
* @param resourceId
* the resource id of the string
* @param params
@@ -43,4 +44,8 @@ abstract class AbstractExport implements Export {
// used in the array adapter of the dialog showing the exports
return getName();
}
+
+ protected String getProgressTitle() {
+ return getString(R.string.export) + ": " + getName();
+ }
}
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
index 5e1805a..a42a48a 100644
--- a/main/src/cgeo/geocaching/export/FieldnoteExport.java
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -5,11 +5,11 @@ import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.ActivityMixin;
-import cgeo.geocaching.activity.Progress;
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.AsyncTaskWithProgress;
import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
@@ -20,12 +20,12 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
-import android.os.AsyncTask;
import android.os.Environment;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.widget.CheckBox;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -57,18 +57,19 @@ class FieldnoteExport extends AbstractExport {
}
@Override
- public void export(final List<Geocache> caches, final Activity activity) {
+ public void export(final List<Geocache> cachesList, final Activity activity) {
+ final Geocache[] caches = cachesList.toArray(new Geocache[cachesList.size()]);
if (null == activity) {
// No activity given, so no user interaction possible.
// Start export with default parameters.
- new ExportTask(caches, null, false, false).execute((Void) null);
+ new ExportTask(null, false, false).execute(caches);
} else {
// Show configuration dialog
getExportOptionsDialog(caches, activity).show();
}
}
- private Dialog getExportOptionsDialog(final List<Geocache> caches, final Activity activity) {
+ private Dialog getExportOptionsDialog(final Geocache[] caches, final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
// AlertDialog has always dark style, so we have to apply it as well always
@@ -91,32 +92,27 @@ class FieldnoteExport extends AbstractExport {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
new ExportTask(
- caches,
activity,
uploadOption.isChecked(),
onlyNewOption.isChecked())
- .execute((Void) null);
+ .execute(caches);
}
});
return builder.create();
}
- private class ExportTask extends AsyncTask<Void, Integer, Boolean> {
- private final List<Geocache> caches;
+ private class ExportTask extends AsyncTaskWithProgress<Geocache, Boolean> {
private final Activity activity;
private final boolean upload;
private final boolean onlyNew;
- private final Progress progress = new Progress();
private File exportFile;
private static final int STATUS_UPLOAD = -1;
/**
- * Instantiates and configurates the task for exporting field notes.
+ * Instantiates and configures the task for exporting field notes.
*
- * @param caches
- * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported
* @param activity
* optional: Show a progress bar and toasts
* @param upload
@@ -124,22 +120,15 @@ class FieldnoteExport extends AbstractExport {
* @param onlyNew
* Upload/export only new logs since last export
*/
- public ExportTask(final List<Geocache> caches, final Activity activity, final boolean upload, final boolean onlyNew) {
- this.caches = caches;
+ public ExportTask(final Activity activity, final boolean upload, final boolean onlyNew) {
+ super(activity, getProgressTitle(), getString(R.string.export_fieldnotes_creating));
this.activity = activity;
this.upload = upload;
this.onlyNew = onlyNew;
}
@Override
- protected void onPreExecute() {
- if (null != activity) {
- progress.show(activity, getString(R.string.export) + ": " + getName(), getString(R.string.export_fieldnotes_creating), true, null);
- }
- }
-
- @Override
- protected Boolean doInBackground(Void... params) {
+ protected Boolean doInBackgroundInternal(Geocache[] caches) {
final StringBuilder fieldNoteBuffer = new StringBuilder();
try {
int i = 0;
@@ -165,16 +154,19 @@ class FieldnoteExport extends AbstractExport {
SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt");
- Writer fw = null;
+ Writer fileWriter = null;
+ BufferedOutputStream buffer = null;
try {
OutputStream os = new FileOutputStream(exportFile);
- fw = new OutputStreamWriter(os, CharEncoding.UTF_16);
- fw.write(fieldNoteBuffer.toString());
+ buffer = new BufferedOutputStream(os);
+ fileWriter = new OutputStreamWriter(buffer, CharEncoding.UTF_16);
+ fileWriter.write(fieldNoteBuffer.toString());
} catch (IOException e) {
Log.e("FieldnoteExport.ExportTask export", e);
return false;
} finally {
- IOUtils.closeQuietly(fw);
+ IOUtils.closeQuietly(fileWriter);
+ IOUtils.closeQuietly(buffer);
}
if (upload) {
@@ -227,10 +219,8 @@ class FieldnoteExport extends AbstractExport {
}
@Override
- protected void onPostExecute(Boolean result) {
+ protected void onPostExecuteInternal(Boolean result) {
if (null != activity) {
- progress.dismiss();
-
if (result) {
// if (onlyNew) {
// // update last export time in settings when doing it ourself (currently we use the date check from gc.com)
@@ -248,12 +238,12 @@ class FieldnoteExport extends AbstractExport {
}
@Override
- protected void onProgressUpdate(Integer... status) {
+ protected void onProgressUpdateInternal(int status) {
if (null != activity) {
- if (STATUS_UPLOAD == status[0]) {
- progress.setMessage(getString(R.string.export_fieldnotes_uploading));
+ if (STATUS_UPLOAD == status) {
+ setMessage(getString(R.string.export_fieldnotes_uploading));
} else {
- progress.setMessage(getString(R.string.export_fieldnotes_creating) + " (" + status[0] + ')');
+ setMessage(getString(R.string.export_fieldnotes_creating) + " (" + status + ')');
}
}
}
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
index b22f80f..66345da 100644
--- a/main/src/cgeo/geocaching/export/GpxExport.java
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -6,11 +6,12 @@ import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
import cgeo.geocaching.Waypoint;
import cgeo.geocaching.cgData;
+import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
-import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.utils.AsyncTaskWithProgress;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.XmlUtils;
@@ -22,25 +23,27 @@ import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Environment;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
class GpxExport extends AbstractExport {
private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
@@ -48,24 +51,30 @@ class GpxExport extends AbstractExport {
public static final String PREFIX_GPX = "http://www.topografix.com/GPX/1/0";
public static final String PREFIX_GROUNDSPEAK = "http://www.groundspeak.com/cache/1/0";
+ /**
+ * During the export, only this number of geocaches is fully loaded into memory.
+ */
+ public static final int CACHES_PER_BATCH = 100;
+
protected GpxExport() {
super(getString(R.string.export_gpx));
}
@Override
public void export(final List<Geocache> caches, final Activity activity) {
+ String[] geocodes = getGeocodes(caches);
if (null == activity) {
// No activity given, so no user interaction possible.
// Start export with default parameters.
- new ExportTask(caches, null).execute((Void) null);
+ new ExportTask(null).execute(geocodes);
} else {
// Show configuration dialog
- getExportDialog(caches, activity).show();
+ getExportDialog(geocodes, activity).show();
}
}
- private Dialog getExportDialog(final List<Geocache> caches, final Activity activity) {
+ private Dialog getExportDialog(final String[] geocodes, final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
// AlertDialog has always dark style, so we have to apply it as well always
@@ -91,55 +100,56 @@ class GpxExport extends AbstractExport {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
- new ExportTask(caches, activity).execute((Void) null);
+ new ExportTask(activity).execute(geocodes);
}
});
return builder.create();
}
- protected class ExportTask extends AsyncTask<Void, Integer, File> {
- private final List<Geocache> caches;
+ private static String[] getGeocodes(final List<Geocache> caches) {
+ ArrayList<String> allGeocodes = new ArrayList<String>(caches.size());
+ for (final Geocache geocache : caches) {
+ allGeocodes.add(geocache.getGeocode());
+ }
+ return allGeocodes.toArray(new String[allGeocodes.size()]);
+ }
+
+ protected class ExportTask extends AsyncTaskWithProgress<String, File> {
private final Activity activity;
- private final Progress progress = new Progress();
+ private int countExported = 0;
/**
* Instantiates and configures the task for exporting field notes.
*
- * @param caches
- * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported
* @param activity
* optional: Show a progress bar and toasts
*/
- public ExportTask(final List<Geocache> caches, final Activity activity) {
- this.caches = caches;
+ public ExportTask(final Activity activity) {
+ super(activity, getProgressTitle());
this.activity = activity;
}
@Override
- protected void onPreExecute() {
- if (null != activity) {
- progress.show(activity, null, getString(R.string.export) + ": " + getName(), ProgressDialog.STYLE_HORIZONTAL, null);
- progress.setMaxProgressAndReset(caches.size());
- }
- }
-
- @Override
- protected File doInBackground(Void... params) {
+ protected File doInBackgroundInternal(String[] geocodes) {
// quick check for being able to write the GPX file
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return null;
}
+ List<String> allGeocodes = new ArrayList<String>(Arrays.asList(geocodes));
+
+ setMessage(cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, allGeocodes.size(), allGeocodes.size()));
+
final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
final File exportFile = new File(Settings.getGpxExportDir() + File.separatorChar + "export_" + fileNameDateFormat.format(new Date()) + ".gpx");
- FileWriter writer = null;
+ BufferedWriter writer = null;
try {
final File exportLocation = new File(Settings.getGpxExportDir());
exportLocation.mkdirs();
final XmlSerializer gpx = new KXmlSerializer();
- writer = new FileWriter(exportFile);
+ writer = new BufferedWriter(new FileWriter(exportFile));
gpx.setOutput(writer);
gpx.startDocument("UTF-8", true);
@@ -153,68 +163,17 @@ class GpxExport extends AbstractExport {
PREFIX_GPX + " http://www.topografix.com/GPX/1/0/gpx.xsd " +
PREFIX_GROUNDSPEAK + " http://www.groundspeak.com/cache/1/0/1/cache.xsd");
- for (int i = 0; i < caches.size(); i++) {
- final Geocache cache = cgData.loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY);
-
- gpx.startTag(PREFIX_GPX, "wpt");
- gpx.attribute("", "lat", Double.toString(cache.getCoords().getLatitude()));
- gpx.attribute("", "lon", Double.toString(cache.getCoords().getLongitude()));
-
- final Date hiddenDate = cache.getHiddenDate();
- if (hiddenDate != null) {
- XmlUtils.simpleText(gpx, PREFIX_GPX, "time", dateFormatZ.format(hiddenDate));
- }
-
- XmlUtils.multipleTexts(gpx, PREFIX_GPX,
- "name", cache.getGeocode(),
- "desc", cache.getName(),
- "url", cache.getUrl(),
- "urlname", cache.getName(),
- "sym", cache.isFound() ? "Geocache Found" : "Geocache",
- "type", "Geocache|" + cache.getType().pattern);
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "cache");
- gpx.attribute("", "id", cache.getCacheId());
- gpx.attribute("", "available", !cache.isDisabled() ? "True" : "False");
- gpx.attribute("", "archives", cache.isArchived() ? "True" : "False");
-
- XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK,
- "name", cache.getName(),
- "placed_by", cache.getOwnerDisplayName(),
- "owner", cache.getOwnerUserId(),
- "type", cache.getType().pattern,
- "container", cache.getSize().id,
- "difficulty", Float.toString(cache.getDifficulty()),
- "terrain", Float.toString(cache.getTerrain()),
- "country", cache.getLocation(),
- "state", "",
- "encoded_hints", cache.getHint());
-
- writeAttributes(gpx, cache);
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "short_description");
- gpx.attribute("", "html", BaseUtils.containsHtml(cache.getShortDescription()) ? "True" : "False");
- gpx.text(cache.getShortDescription());
- gpx.endTag(PREFIX_GROUNDSPEAK, "short_description");
-
- gpx.startTag(PREFIX_GROUNDSPEAK, "long_description");
- gpx.attribute("", "html", BaseUtils.containsHtml(cache.getDescription()) ? "True" : "False");
- gpx.text(cache.getDescription());
- gpx.endTag(PREFIX_GROUNDSPEAK, "long_description");
-
- writeLogs(gpx, cache);
-
- gpx.endTag(PREFIX_GROUNDSPEAK, "cache");
- gpx.endTag(PREFIX_GPX, "wpt");
-
- writeWaypoints(gpx, cache);
-
- publishProgress(i + 1);
+ // Split the overall set of geocodes into small chunks. That is a compromise between memory efficiency (because
+ // we don't load all caches fully into memory) and speed (because we don't query each cache separately).
+ while (!allGeocodes.isEmpty()) {
+ final List<String> batch = allGeocodes.subList(0, Math.min(CACHES_PER_BATCH, allGeocodes.size()));
+ exportBatch(gpx, batch);
+ batch.clear();
}
gpx.endTag(PREFIX_GPX, "gpx");
gpx.endDocument();
- } catch (final IOException e) {
+ } catch (final Exception e) {
Log.e("GpxExport.ExportTask export", e);
if (writer != null) {
@@ -235,6 +194,67 @@ class GpxExport extends AbstractExport {
return exportFile;
}
+ private void exportBatch(final XmlSerializer gpx, Collection<String> geocodesOfBatch) throws IOException {
+ Set<Geocache> caches = cgData.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY);
+ for (Geocache cache : caches) {
+ gpx.startTag(PREFIX_GPX, "wpt");
+ gpx.attribute("", "lat", Double.toString(cache.getCoords().getLatitude()));
+ gpx.attribute("", "lon", Double.toString(cache.getCoords().getLongitude()));
+
+ final Date hiddenDate = cache.getHiddenDate();
+ if (hiddenDate != null) {
+ XmlUtils.simpleText(gpx, PREFIX_GPX, "time", dateFormatZ.format(hiddenDate));
+ }
+
+ XmlUtils.multipleTexts(gpx, PREFIX_GPX,
+ "name", cache.getGeocode(),
+ "desc", cache.getName(),
+ "url", cache.getUrl(),
+ "urlname", cache.getName(),
+ "sym", cache.isFound() ? "Geocache Found" : "Geocache",
+ "type", "Geocache|" + cache.getType().pattern);
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "cache");
+ gpx.attribute("", "id", cache.getCacheId());
+ gpx.attribute("", "available", !cache.isDisabled() ? "True" : "False");
+ gpx.attribute("", "archives", cache.isArchived() ? "True" : "False");
+
+ XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK,
+ "name", cache.getName(),
+ "placed_by", cache.getOwnerDisplayName(),
+ "owner", cache.getOwnerUserId(),
+ "type", cache.getType().pattern,
+ "container", cache.getSize().id,
+ "difficulty", Float.toString(cache.getDifficulty()),
+ "terrain", Float.toString(cache.getTerrain()),
+ "country", cache.getLocation(),
+ "state", "",
+ "encoded_hints", cache.getHint());
+
+ writeAttributes(gpx, cache);
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "short_description");
+ gpx.attribute("", "html", BaseUtils.containsHtml(cache.getShortDescription()) ? "True" : "False");
+ gpx.text(cache.getShortDescription());
+ gpx.endTag(PREFIX_GROUNDSPEAK, "short_description");
+
+ gpx.startTag(PREFIX_GROUNDSPEAK, "long_description");
+ gpx.attribute("", "html", BaseUtils.containsHtml(cache.getDescription()) ? "True" : "False");
+ gpx.text(cache.getDescription());
+ gpx.endTag(PREFIX_GROUNDSPEAK, "long_description");
+
+ writeLogs(gpx, cache);
+
+ gpx.endTag(PREFIX_GROUNDSPEAK, "cache");
+ gpx.endTag(PREFIX_GPX, "wpt");
+
+ writeWaypoints(gpx, cache);
+
+ countExported++;
+ publishProgress(countExported);
+ }
+ }
+
private void writeWaypoints(final XmlSerializer gpx, final Geocache cache) throws IOException {
List<Waypoint> waypoints = cache.getWaypoints();
List<Waypoint> ownWaypoints = new ArrayList<Waypoint>(waypoints.size());
@@ -346,9 +366,8 @@ class GpxExport extends AbstractExport {
}
@Override
- protected void onPostExecute(final File exportFile) {
+ protected void onPostExecuteInternal(final File exportFile) {
if (null != activity) {
- progress.dismiss();
if (exportFile != null) {
ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString());
if (Settings.getShareAfterExport()) {
@@ -364,11 +383,5 @@ class GpxExport extends AbstractExport {
}
}
- @Override
- protected void onProgressUpdate(Integer... status) {
- if (null != activity) {
- progress.setProgress(status[0]);
- }
- }
}
}
diff --git a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
index 5ff0d91..8b02eeb 100644
--- a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
+++ b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
@@ -89,7 +89,6 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
setTheme();
setContentView(R.layout.gpx);
- setTitle();
Bundle extras = getIntent().getExtras();
if (extras != null) {
@@ -146,11 +145,6 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
*/
protected abstract List<File> getBaseFolders();
- /**
- * Triggers the deriving class to set the title
- */
- protected abstract void setTitle();
-
private class SearchFilesThread extends Thread {
private final FileListSelector selector = new FileListSelector();
diff --git a/main/src/cgeo/geocaching/files/FileParser.java b/main/src/cgeo/geocaching/files/FileParser.java
index 50b65a1..f979d74 100644
--- a/main/src/cgeo/geocaching/files/FileParser.java
+++ b/main/src/cgeo/geocaching/files/FileParser.java
@@ -2,7 +2,9 @@ package cgeo.geocaching.files;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.utils.CancellableHandler;
+import cgeo.geocaching.utils.IOUtils;
+import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -16,7 +18,7 @@ import java.util.concurrent.CancellationException;
public abstract class FileParser {
/**
* Parses caches from input stream.
- *
+ *
* @param stream
* @param progressHandler
* for reporting parsing progress (in bytes read from input stream)
@@ -38,11 +40,11 @@ public abstract class FileParser {
* @throws ParserException
*/
public Collection<Geocache> parse(final File file, final CancellableHandler progressHandler) throws IOException, ParserException {
- FileInputStream fis = new FileInputStream(file);
+ BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file));
try {
- return parse(fis, progressHandler);
+ return parse(stream, progressHandler);
} finally {
- fis.close();
+ IOUtils.closeQuietly(stream);
}
}
@@ -59,7 +61,7 @@ public abstract class FileParser {
}
return buffer;
} finally {
- input.close();
+ IOUtils.closeQuietly(input);
}
}
diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java
index b8dcbb3..87c0ec4 100644
--- a/main/src/cgeo/geocaching/files/GPXImporter.java
+++ b/main/src/cgeo/geocaching/files/GPXImporter.java
@@ -1,458 +1,463 @@
-package cgeo.geocaching.files;
-
-import cgeo.geocaching.Geocache;
-import cgeo.geocaching.R;
-import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.Settings;
-import cgeo.geocaching.StaticMapsProvider;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.activity.IAbstractActivity;
-import cgeo.geocaching.activity.Progress;
-import cgeo.geocaching.enumerations.LoadFlags;
-import cgeo.geocaching.utils.CancellableHandler;
-import cgeo.geocaching.utils.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.CancellationException;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-public class GPXImporter {
- static final int IMPORT_STEP_START = 0;
- static final int IMPORT_STEP_READ_FILE = 1;
- static final int IMPORT_STEP_READ_WPT_FILE = 2;
- static final int IMPORT_STEP_STORE_STATIC_MAPS = 4;
- static final int IMPORT_STEP_FINISHED = 5;
- static final int IMPORT_STEP_FINISHED_WITH_ERROR = 6;
- static final int IMPORT_STEP_CANCEL = 7;
- static final int IMPORT_STEP_CANCELED = 8;
- static final int IMPORT_STEP_STATIC_MAPS_SKIPPED = 9;
-
- public static final String GPX_FILE_EXTENSION = ".gpx";
- public static final String ZIP_FILE_EXTENSION = ".zip";
- public static final String WAYPOINTS_FILE_SUFFIX = "-wpts";
- public static final String WAYPOINTS_FILE_SUFFIX_AND_EXTENSION = WAYPOINTS_FILE_SUFFIX + GPX_FILE_EXTENSION;
-
- private static final List<String> GPX_MIME_TYPES = Arrays.asList("text/xml", "application/xml");
- private static final List<String> ZIP_MIME_TYPES = Arrays.asList("application/zip", "application/x-compressed", "application/x-zip-compressed", "application/x-zip", "application/octet-stream");
-
- private Progress progress = new Progress(true);
-
- private Resources res;
- private int listId;
- private IAbstractActivity fromActivity;
- private Handler importFinishedHandler;
-
- public GPXImporter(final IAbstractActivity fromActivity, final int listId, final Handler importFinishedHandler) {
- this.listId = listId;
- this.fromActivity = fromActivity;
- res = ((Activity) fromActivity).getResources();
- this.importFinishedHandler = importFinishedHandler;
- }
-
- /**
- * Import GPX file. Currently supports *.gpx, *.zip (containing gpx files, e.g. PQ queries) or *.loc files.
- *
- * @param file
- * the file to import
- */
- public void importGPX(final File file) {
- if (StringUtils.endsWithIgnoreCase(file.getName(), GPX_FILE_EXTENSION)) {
- new ImportGpxFileThread(file, listId, importStepHandler, progressHandler).start();
- } else if (StringUtils.endsWithIgnoreCase(file.getName(), ZIP_FILE_EXTENSION)) {
- new ImportGpxZipFileThread(file, listId, importStepHandler, progressHandler).start();
- } else {
- new ImportLocFileThread(file, listId, importStepHandler, progressHandler).start();
- }
- }
-
- /**
- * Import GPX provided via intent of activity that instantiated this GPXImporter.
- */
- public void importGPX() {
- final ContentResolver contentResolver = ((Activity) fromActivity).getContentResolver();
- final Intent intent = ((Activity) fromActivity).getIntent();
- final Uri uri = intent.getData();
-
- String mimeType = intent.getType();
- // if mimetype can't be determined (e.g. for emulators email app), derive it from uri file extension
- // contentResolver.getType(uri) doesn't help but throws exception for emulators email app
- // Permission Denial: reading com.android.email.provider.EmailProvider uri
- // Google search says: there is no solution for this problem
- // Gmail doesn't work at all, see #967
- if (mimeType == null) {
- if (StringUtils.endsWithIgnoreCase(uri.getPath(), GPX_FILE_EXTENSION)) {
- mimeType = "application/xml";
- } else {
- // if we can't determine a better type, default to zip import
- // emulator email sends e.g. content://com.android.email.attachmentprovider/1/1/RAW, mimetype=null
- mimeType = "application/zip";
- }
- }
-
- Log.i("importGPX: " + uri + ", mimetype=" + mimeType);
- if (GPX_MIME_TYPES.contains(mimeType)) {
- new ImportGpxAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start();
- } else if (ZIP_MIME_TYPES.contains(mimeType)) {
- new ImportGpxZipAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start();
- } else {
- importFinished();
- }
- }
-
- static abstract class ImportThread extends Thread {
- final int listId;
- final Handler importStepHandler;
- final CancellableHandler progressHandler;
-
- protected ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
- this.listId = listId;
- this.importStepHandler = importStepHandler;
- this.progressHandler = progressHandler;
- }
-
- @Override
- public void run() {
- try {
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_START));
- final Collection<Geocache> caches = doImport();
- Log.i("Imported successfully " + caches.size() + " caches.");
-
- final SearchResult search = new SearchResult();
- for (Geocache cache : caches) {
- search.addCache(cache);
- }
-
- if (Settings.isStoreOfflineMaps() || Settings.isStoreOfflineWpMaps()) {
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_STORE_STATIC_MAPS, R.string.gpx_import_store_static_maps, search.getCount()));
- boolean finishedWithoutCancel = importStaticMaps(search);
- // Skip last message if static maps where canceled
- if (!finishedWithoutCancel) {
- return;
- }
- }
-
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED, search.getCount(), 0, search));
- } catch (IOException e) {
- Log.i("Importing caches failed - error reading data: " + e.getMessage());
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_io, 0, e.getLocalizedMessage()));
- } catch (ParserException e) {
- Log.i("Importing caches failed - data format error" + e.getMessage());
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_parser, 0, e.getLocalizedMessage()));
- } catch (CancellationException e) {
- Log.i("Importing caches canceled");
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_CANCELED));
- } catch (Exception e) {
- Log.e("Importing caches failed - unknown error: ", e);
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_unexpected, 0, e.getLocalizedMessage()));
- }
- }
-
- protected abstract Collection<Geocache> doImport() throws IOException, ParserException;
-
- private boolean importStaticMaps(final SearchResult importedCaches) {
- int storedCacheMaps = 0;
- for (String geocode : importedCaches.getGeocodes()) {
- Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
- Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
- StaticMapsProvider.downloadMaps(cache);
- storedCacheMaps++;
- if (progressHandler.isCancelled()) {
- return false;
- }
- progressHandler.sendMessage(progressHandler.obtainMessage(0, storedCacheMaps, 0));
- }
- return true;
- }
- }
-
- static class ImportLocFileThread extends ImportThread {
- private final File file;
-
- public ImportLocFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
- super(listId, importStepHandler, progressHandler);
- this.file = file;
- }
-
- @Override
- protected Collection<Geocache> doImport() throws IOException, ParserException {
- Log.i("Import LOC file: " + file.getAbsolutePath());
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) file.length()));
- LocParser parser = new LocParser(listId);
- return parser.parse(file, progressHandler);
- }
- }
-
- static abstract class ImportGpxThread extends ImportThread {
-
- protected ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
- super(listId, importStepHandler, progressHandler);
- }
-
- @Override
- protected Collection<Geocache> doImport() throws IOException, ParserException {
- try {
- // try to parse cache file as GPX 10
- return doImport(new GPX10Parser(listId));
- } catch (ParserException pe) {
- // didn't work -> lets try GPX11
- return doImport(new GPX11Parser(listId));
- }
- }
-
- protected abstract Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException;
- }
-
- static class ImportGpxFileThread extends ImportGpxThread {
- private final File cacheFile;
-
- public ImportGpxFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
- super(listId, importStepHandler, progressHandler);
- this.cacheFile = file;
- }
-
- @Override
- protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException {
- Log.i("Import GPX file: " + cacheFile.getAbsolutePath());
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) cacheFile.length()));
- Collection<Geocache> caches = parser.parse(cacheFile, progressHandler);
-
- final String wptsFilename = getWaypointsFileNameForGpxFile(cacheFile);
- if (wptsFilename != null) {
- final File wptsFile = new File(cacheFile.getParentFile(), wptsFilename);
- if (wptsFile.canRead()) {
- Log.i("Import GPX waypoint file: " + wptsFile.getAbsolutePath());
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) wptsFile.length()));
- caches = parser.parse(wptsFile, progressHandler);
- }
- }
- return caches;
- }
- }
-
- static class ImportGpxAttachmentThread extends ImportGpxThread {
- private final Uri uri;
- private ContentResolver contentResolver;
-
- public ImportGpxAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
- super(listId, importStepHandler, progressHandler);
- this.uri = uri;
- this.contentResolver = contentResolver;
- }
-
- @Override
- protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException {
- Log.i("Import GPX from uri: " + uri);
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, -1));
- InputStream is = contentResolver.openInputStream(uri);
- try {
- return parser.parse(is, progressHandler);
- } finally {
- is.close();
- }
- }
- }
-
- static abstract class ImportGpxZipThread extends ImportGpxThread {
-
- protected ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
- super(listId, importStepHandler, progressHandler);
- }
-
- @Override
- protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException {
- Collection<Geocache> caches = Collections.emptySet();
- // can't assume that GPX file comes before waypoint file in zip -> so we need two passes
- // 1. parse GPX files
- ZipInputStream zis = new ZipInputStream(getInputStream());
- try {
- for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis.getNextEntry()) {
- if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), GPX_FILE_EXTENSION)) {
- if (!StringUtils.endsWithIgnoreCase(zipEntry.getName(), WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) {
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) zipEntry.getSize()));
- caches = parser.parse(new NoCloseInputStream(zis), progressHandler);
- }
- } else {
- throw new ParserException("Imported zip is not a GPX zip file.");
- }
- zis.closeEntry();
- }
- } finally {
- zis.close();
- }
-
- // 2. parse waypoint files
- zis = new ZipInputStream(getInputStream());
- try {
- for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis.getNextEntry()) {
- if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) {
- importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) zipEntry.getSize()));
- caches = parser.parse(new NoCloseInputStream(zis), progressHandler);
- }
- zis.closeEntry();
- }
- } finally {
- zis.close();
- }
-
- return caches;
- }
-
- protected abstract InputStream getInputStream() throws IOException;
- }
-
- static class ImportGpxZipFileThread extends ImportGpxZipThread {
- private final File cacheFile;
-
- public ImportGpxZipFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
- super(listId, importStepHandler, progressHandler);
- this.cacheFile = file;
- Log.i("Import zipped GPX: " + file);
- }
-
- @Override
- protected InputStream getInputStream() throws IOException {
- return new FileInputStream(cacheFile);
- }
- }
-
- static class ImportGpxZipAttachmentThread extends ImportGpxZipThread {
- private final Uri uri;
- private ContentResolver contentResolver;
-
- public ImportGpxZipAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
- super(listId, importStepHandler, progressHandler);
- this.uri = uri;
- this.contentResolver = contentResolver;
- Log.i("Import zipped GPX from uri: " + uri);
- }
-
- @Override
- protected InputStream getInputStream() throws IOException {
- return contentResolver.openInputStream(uri);
- }
- }
-
- final private CancellableHandler progressHandler = new CancellableHandler() {
- @Override
- public void handleRegularMessage(Message msg) {
- progress.setProgress(msg.arg1);
- }
- };
-
- final private Handler importStepHandler = new Handler() {
- private boolean showProgressAfterCancel = false;
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case IMPORT_STEP_START:
- Message cancelMessage = importStepHandler.obtainMessage(IMPORT_STEP_CANCEL);
- progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_reading_file), res.getString(R.string.gpx_import_loading_caches), ProgressDialog.STYLE_HORIZONTAL, cancelMessage);
- break;
-
- case IMPORT_STEP_READ_FILE:
- case IMPORT_STEP_READ_WPT_FILE:
- progress.setMessage(res.getString(msg.arg1));
- progress.setMaxProgressAndReset(msg.arg2);
- break;
-
- case IMPORT_STEP_STORE_STATIC_MAPS:
- progress.dismiss();
- Message skipMessage = importStepHandler.obtainMessage(IMPORT_STEP_STATIC_MAPS_SKIPPED, msg.arg2, 0);
- progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_static_maps), res.getString(R.string.gpx_import_store_static_maps), ProgressDialog.STYLE_HORIZONTAL, skipMessage);
- progress.setMaxProgressAndReset(msg.arg2);
- break;
-
- case IMPORT_STEP_STATIC_MAPS_SKIPPED:
- progress.dismiss();
- progressHandler.cancel();
- StringBuilder bufferSkipped = new StringBuilder(20);
- bufferSkipped.append(res.getString(R.string.gpx_import_static_maps_skipped)).append(", ").append(msg.arg1).append(' ').append(res.getString(R.string.gpx_import_caches_imported));
- fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), bufferSkipped.toString());
- importFinished();
- break;
-
- case IMPORT_STEP_FINISHED:
- progress.dismiss();
- fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), msg.arg1 + " " + res.getString(R.string.gpx_import_caches_imported));
- importFinished();
- break;
-
- case IMPORT_STEP_FINISHED_WITH_ERROR:
- progress.dismiss();
- fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_import_failed), res.getString(msg.arg1) + "\n\n" + msg.obj);
- importFinished();
- break;
-
- case IMPORT_STEP_CANCEL:
- progress.dismiss();
- progressHandler.cancel();
- break;
-
- case IMPORT_STEP_CANCELED:
- StringBuilder bufferCanceled = new StringBuilder(20);
- bufferCanceled.append(res.getString(R.string.gpx_import_canceled));
- if (showProgressAfterCancel) {
- bufferCanceled.append(", ").append(progress.getProgress()).append(' ').append(res.getString(R.string.gpx_import_caches_imported));
- }
- fromActivity.showShortToast(bufferCanceled.toString());
- importFinished();
- break;
-
- default:
- break;
- }
- }
- };
-
- /**
- * @param gpxfile
- * the gpx file
- * @return the expected file name of the waypoints file
- */
- static String getWaypointsFileNameForGpxFile(final File gpxfile) {
- if (gpxfile == null || !gpxfile.canRead()) {
- return null;
- }
- final String gpxFileName = gpxfile.getName();
- File dir = gpxfile.getParentFile();
- String[] filenameList = dir.list();
- for (String filename : filenameList) {
- if (!StringUtils.containsIgnoreCase(filename, WAYPOINTS_FILE_SUFFIX)) {
- continue;
- }
- String expectedGpxFileName = StringUtils.substringBeforeLast(filename, WAYPOINTS_FILE_SUFFIX)
- + StringUtils.substringAfterLast(filename, WAYPOINTS_FILE_SUFFIX);
- if (gpxFileName.equals(expectedGpxFileName)) {
- return filename;
- }
- }
- return null;
- }
-
- protected void importFinished() {
- if (importFinishedHandler != null) {
- importFinishedHandler.sendEmptyMessage(0);
- }
- }
-}
+package cgeo.geocaching.files;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.StaticMapsProvider;
+import cgeo.geocaching.cgData;
+import cgeo.geocaching.activity.IAbstractActivity;
+import cgeo.geocaching.activity.Progress;
+import cgeo.geocaching.enumerations.LoadFlags;
+import cgeo.geocaching.utils.CancellableHandler;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class GPXImporter {
+ static final int IMPORT_STEP_START = 0;
+ static final int IMPORT_STEP_READ_FILE = 1;
+ static final int IMPORT_STEP_READ_WPT_FILE = 2;
+ static final int IMPORT_STEP_STORE_STATIC_MAPS = 4;
+ static final int IMPORT_STEP_FINISHED = 5;
+ static final int IMPORT_STEP_FINISHED_WITH_ERROR = 6;
+ static final int IMPORT_STEP_CANCEL = 7;
+ static final int IMPORT_STEP_CANCELED = 8;
+ static final int IMPORT_STEP_STATIC_MAPS_SKIPPED = 9;
+
+ public static final String GPX_FILE_EXTENSION = ".gpx";
+ public static final String ZIP_FILE_EXTENSION = ".zip";
+ public static final String WAYPOINTS_FILE_SUFFIX = "-wpts";
+ public static final String WAYPOINTS_FILE_SUFFIX_AND_EXTENSION = WAYPOINTS_FILE_SUFFIX + GPX_FILE_EXTENSION;
+
+ private static final List<String> GPX_MIME_TYPES = Arrays.asList("text/xml", "application/xml");
+ private static final List<String> ZIP_MIME_TYPES = Arrays.asList("application/zip", "application/x-compressed", "application/x-zip-compressed", "application/x-zip", "application/octet-stream");
+
+ private Progress progress = new Progress(true);
+
+ private Resources res;
+ private int listId;
+ private IAbstractActivity fromActivity;
+ private Handler importFinishedHandler;
+
+ public GPXImporter(final IAbstractActivity fromActivity, final int listId, final Handler importFinishedHandler) {
+ this.listId = listId;
+ this.fromActivity = fromActivity;
+ res = ((Activity) fromActivity).getResources();
+ this.importFinishedHandler = importFinishedHandler;
+ }
+
+ /**
+ * Import GPX file. Currently supports *.gpx, *.zip (containing gpx files, e.g. PQ queries) or *.loc files.
+ *
+ * @param file
+ * the file to import
+ */
+ public void importGPX(final File file) {
+ if (StringUtils.endsWithIgnoreCase(file.getName(), GPX_FILE_EXTENSION)) {
+ new ImportGpxFileThread(file, listId, importStepHandler, progressHandler).start();
+ } else if (StringUtils.endsWithIgnoreCase(file.getName(), ZIP_FILE_EXTENSION)) {
+ new ImportGpxZipFileThread(file, listId, importStepHandler, progressHandler).start();
+ } else {
+ new ImportLocFileThread(file, listId, importStepHandler, progressHandler).start();
+ }
+ }
+
+ /**
+ * Import GPX provided via intent of activity that instantiated this GPXImporter.
+ */
+ public void importGPX() {
+ final ContentResolver contentResolver = ((Activity) fromActivity).getContentResolver();
+ final Intent intent = ((Activity) fromActivity).getIntent();
+ final Uri uri = intent.getData();
+
+ String mimeType = intent.getType();
+ // if mimetype can't be determined (e.g. for emulators email app), derive it from uri file extension
+ // contentResolver.getType(uri) doesn't help but throws exception for emulators email app
+ // Permission Denial: reading com.android.email.provider.EmailProvider uri
+ // Google search says: there is no solution for this problem
+ // Gmail doesn't work at all, see #967
+ if (mimeType == null) {
+ if (StringUtils.endsWithIgnoreCase(uri.getPath(), GPX_FILE_EXTENSION)) {
+ mimeType = "application/xml";
+ } else {
+ // if we can't determine a better type, default to zip import
+ // emulator email sends e.g. content://com.android.email.attachmentprovider/1/1/RAW, mimetype=null
+ mimeType = "application/zip";
+ }
+ }
+
+ Log.i("importGPX: " + uri + ", mimetype=" + mimeType);
+ if (GPX_MIME_TYPES.contains(mimeType)) {
+ new ImportGpxAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start();
+ } else if (ZIP_MIME_TYPES.contains(mimeType)) {
+ new ImportGpxZipAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start();
+ } else {
+ importFinished();
+ }
+ }
+
+ static abstract class ImportThread extends Thread {
+ final int listId;
+ final Handler importStepHandler;
+ final CancellableHandler progressHandler;
+
+ protected ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ this.listId = listId;
+ this.importStepHandler = importStepHandler;
+ this.progressHandler = progressHandler;
+ }
+
+ @Override
+ public void run() {
+ try {
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_START));
+ final Collection<Geocache> caches = doImport();
+ Log.i("Imported successfully " + caches.size() + " caches.");
+
+ final SearchResult search = new SearchResult();
+ for (Geocache cache : caches) {
+ search.addAndPutInCache(cache);
+ }
+
+ if (Settings.isStoreOfflineMaps() || Settings.isStoreOfflineWpMaps()) {
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_STORE_STATIC_MAPS, R.string.gpx_import_store_static_maps, search.getCount()));
+ boolean finishedWithoutCancel = importStaticMaps(search);
+ // Skip last message if static maps where canceled
+ if (!finishedWithoutCancel) {
+ return;
+ }
+ }
+
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED, search.getCount(), 0, search));
+ } catch (IOException e) {
+ Log.i("Importing caches failed - error reading data: " + e.getMessage());
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_io, 0, e.getLocalizedMessage()));
+ } catch (ParserException e) {
+ Log.i("Importing caches failed - data format error" + e.getMessage());
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_parser, 0, e.getLocalizedMessage()));
+ } catch (CancellationException e) {
+ Log.i("Importing caches canceled");
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_CANCELED));
+ } catch (Exception e) {
+ Log.e("Importing caches failed - unknown error: ", e);
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_unexpected, 0, e.getLocalizedMessage()));
+ }
+ }
+
+ protected abstract Collection<Geocache> doImport() throws IOException, ParserException;
+
+ private boolean importStaticMaps(final SearchResult importedCaches) {
+ int storedCacheMaps = 0;
+ for (final String geocode : importedCaches.getGeocodes()) {
+ final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ if (cache != null) {
+ Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
+ StaticMapsProvider.downloadMaps(cache);
+ } else {
+ Log.d("GPXImporter.ImportThread.importStaticMaps: no data found for " + geocode);
+ }
+ storedCacheMaps++;
+ if (progressHandler.isCancelled()) {
+ return false;
+ }
+ progressHandler.sendMessage(progressHandler.obtainMessage(0, storedCacheMaps, 0));
+ }
+ return true;
+ }
+ }
+
+ static class ImportLocFileThread extends ImportThread {
+ private final File file;
+
+ public ImportLocFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ super(listId, importStepHandler, progressHandler);
+ this.file = file;
+ }
+
+ @Override
+ protected Collection<Geocache> doImport() throws IOException, ParserException {
+ Log.i("Import LOC file: " + file.getAbsolutePath());
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) file.length()));
+ LocParser parser = new LocParser(listId);
+ return parser.parse(file, progressHandler);
+ }
+ }
+
+ static abstract class ImportGpxThread extends ImportThread {
+
+ protected ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ super(listId, importStepHandler, progressHandler);
+ }
+
+ @Override
+ protected Collection<Geocache> doImport() throws IOException, ParserException {
+ try {
+ // try to parse cache file as GPX 10
+ return doImport(new GPX10Parser(listId));
+ } catch (ParserException pe) {
+ // didn't work -> lets try GPX11
+ return doImport(new GPX11Parser(listId));
+ }
+ }
+
+ protected abstract Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException;
+ }
+
+ static class ImportGpxFileThread extends ImportGpxThread {
+ private final File cacheFile;
+
+ public ImportGpxFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ super(listId, importStepHandler, progressHandler);
+ this.cacheFile = file;
+ }
+
+ @Override
+ protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException {
+ Log.i("Import GPX file: " + cacheFile.getAbsolutePath());
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) cacheFile.length()));
+ Collection<Geocache> caches = parser.parse(cacheFile, progressHandler);
+
+ final String wptsFilename = getWaypointsFileNameForGpxFile(cacheFile);
+ if (wptsFilename != null) {
+ final File wptsFile = new File(cacheFile.getParentFile(), wptsFilename);
+ if (wptsFile.canRead()) {
+ Log.i("Import GPX waypoint file: " + wptsFile.getAbsolutePath());
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) wptsFile.length()));
+ caches = parser.parse(wptsFile, progressHandler);
+ }
+ }
+ return caches;
+ }
+ }
+
+ static class ImportGpxAttachmentThread extends ImportGpxThread {
+ private final Uri uri;
+ private ContentResolver contentResolver;
+
+ public ImportGpxAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ super(listId, importStepHandler, progressHandler);
+ this.uri = uri;
+ this.contentResolver = contentResolver;
+ }
+
+ @Override
+ protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException {
+ Log.i("Import GPX from uri: " + uri);
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, -1));
+ InputStream is = contentResolver.openInputStream(uri);
+ try {
+ return parser.parse(is, progressHandler);
+ } finally {
+ is.close();
+ }
+ }
+ }
+
+ static abstract class ImportGpxZipThread extends ImportGpxThread {
+
+ protected ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ super(listId, importStepHandler, progressHandler);
+ }
+
+ @Override
+ protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException {
+ Collection<Geocache> caches = Collections.emptySet();
+ // can't assume that GPX file comes before waypoint file in zip -> so we need two passes
+ // 1. parse GPX files
+ ZipInputStream zis = new ZipInputStream(new BufferedInputStream(getInputStream()));
+ try {
+ for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis.getNextEntry()) {
+ if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), GPX_FILE_EXTENSION)) {
+ if (!StringUtils.endsWithIgnoreCase(zipEntry.getName(), WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) {
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) zipEntry.getSize()));
+ caches = parser.parse(new NoCloseInputStream(zis), progressHandler);
+ }
+ } else {
+ throw new ParserException("Imported zip is not a GPX zip file.");
+ }
+ zis.closeEntry();
+ }
+ } finally {
+ zis.close();
+ }
+
+ // 2. parse waypoint files
+ zis = new ZipInputStream(new BufferedInputStream(getInputStream()));
+ try {
+ for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis.getNextEntry()) {
+ if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) {
+ importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) zipEntry.getSize()));
+ caches = parser.parse(new NoCloseInputStream(zis), progressHandler);
+ }
+ zis.closeEntry();
+ }
+ } finally {
+ zis.close();
+ }
+
+ return caches;
+ }
+
+ protected abstract InputStream getInputStream() throws IOException;
+ }
+
+ static class ImportGpxZipFileThread extends ImportGpxZipThread {
+ private final File cacheFile;
+
+ public ImportGpxZipFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ super(listId, importStepHandler, progressHandler);
+ this.cacheFile = file;
+ Log.i("Import zipped GPX: " + file);
+ }
+
+ @Override
+ protected InputStream getInputStream() throws IOException {
+ return new FileInputStream(cacheFile);
+ }
+ }
+
+ static class ImportGpxZipAttachmentThread extends ImportGpxZipThread {
+ private final Uri uri;
+ private ContentResolver contentResolver;
+
+ public ImportGpxZipAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ super(listId, importStepHandler, progressHandler);
+ this.uri = uri;
+ this.contentResolver = contentResolver;
+ Log.i("Import zipped GPX from uri: " + uri);
+ }
+
+ @Override
+ protected InputStream getInputStream() throws IOException {
+ return contentResolver.openInputStream(uri);
+ }
+ }
+
+ final private CancellableHandler progressHandler = new CancellableHandler() {
+ @Override
+ public void handleRegularMessage(Message msg) {
+ progress.setProgress(msg.arg1);
+ }
+ };
+
+ final private Handler importStepHandler = new Handler() {
+ private boolean showProgressAfterCancel = false;
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case IMPORT_STEP_START:
+ Message cancelMessage = importStepHandler.obtainMessage(IMPORT_STEP_CANCEL);
+ progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_reading_file), res.getString(R.string.gpx_import_loading_caches), ProgressDialog.STYLE_HORIZONTAL, cancelMessage);
+ break;
+
+ case IMPORT_STEP_READ_FILE:
+ case IMPORT_STEP_READ_WPT_FILE:
+ progress.setMessage(res.getString(msg.arg1));
+ progress.setMaxProgressAndReset(msg.arg2);
+ break;
+
+ case IMPORT_STEP_STORE_STATIC_MAPS:
+ progress.dismiss();
+ Message skipMessage = importStepHandler.obtainMessage(IMPORT_STEP_STATIC_MAPS_SKIPPED, msg.arg2, 0);
+ progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_static_maps), res.getString(R.string.gpx_import_store_static_maps), ProgressDialog.STYLE_HORIZONTAL, skipMessage);
+ progress.setMaxProgressAndReset(msg.arg2);
+ break;
+
+ case IMPORT_STEP_STATIC_MAPS_SKIPPED:
+ progress.dismiss();
+ progressHandler.cancel();
+ StringBuilder bufferSkipped = new StringBuilder(20);
+ bufferSkipped.append(res.getString(R.string.gpx_import_static_maps_skipped)).append(", ").append(msg.arg1).append(' ').append(res.getString(R.string.gpx_import_caches_imported));
+ fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), bufferSkipped.toString());
+ importFinished();
+ break;
+
+ case IMPORT_STEP_FINISHED:
+ progress.dismiss();
+ fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), msg.arg1 + " " + res.getString(R.string.gpx_import_caches_imported));
+ importFinished();
+ break;
+
+ case IMPORT_STEP_FINISHED_WITH_ERROR:
+ progress.dismiss();
+ fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_import_failed), res.getString(msg.arg1) + "\n\n" + msg.obj);
+ importFinished();
+ break;
+
+ case IMPORT_STEP_CANCEL:
+ progress.dismiss();
+ progressHandler.cancel();
+ break;
+
+ case IMPORT_STEP_CANCELED:
+ StringBuilder bufferCanceled = new StringBuilder(20);
+ bufferCanceled.append(res.getString(R.string.gpx_import_canceled));
+ if (showProgressAfterCancel) {
+ bufferCanceled.append(", ").append(progress.getProgress()).append(' ').append(res.getString(R.string.gpx_import_caches_imported));
+ }
+ fromActivity.showShortToast(bufferCanceled.toString());
+ importFinished();
+ break;
+
+ default:
+ break;
+ }
+ }
+ };
+
+ /**
+ * @param gpxfile
+ * the gpx file
+ * @return the expected file name of the waypoints file
+ */
+ static String getWaypointsFileNameForGpxFile(final File gpxfile) {
+ if (gpxfile == null || !gpxfile.canRead()) {
+ return null;
+ }
+ final String gpxFileName = gpxfile.getName();
+ File dir = gpxfile.getParentFile();
+ String[] filenameList = dir.list();
+ for (String filename : filenameList) {
+ if (!StringUtils.containsIgnoreCase(filename, WAYPOINTS_FILE_SUFFIX)) {
+ continue;
+ }
+ String expectedGpxFileName = StringUtils.substringBeforeLast(filename, WAYPOINTS_FILE_SUFFIX)
+ + StringUtils.substringAfterLast(filename, WAYPOINTS_FILE_SUFFIX);
+ if (gpxFileName.equals(expectedGpxFileName)) {
+ return filename;
+ }
+ }
+ return null;
+ }
+
+ protected void importFinished() {
+ if (importFinishedHandler != null) {
+ importFinishedHandler.sendEmptyMessage(0);
+ }
+ }
+}
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index 96c90cc..4150b87 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -183,6 +183,7 @@ public abstract class GPXParser extends FileParser {
R.string.attribute_treeclimbing_yes, // 64
R.string.attribute_frontyard_yes, // 65
R.string.attribute_teamwork_yes, // 66
+ R.string.attribute_geotour_yes, // 67
};
private static final String YES = "_yes";
private static final String NO = "_no";
diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java
index f59f15c..0f3e0e1 100644
--- a/main/src/cgeo/geocaching/files/LocalStorage.java
+++ b/main/src/cgeo/geocaching/files/LocalStorage.java
@@ -2,14 +2,18 @@ package cgeo.geocaching.files;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.CryptUtils;
+import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.apache.commons.lang3.StringUtils;
import android.os.Environment;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -275,19 +279,14 @@ public class LocalStorage {
destination.getParentFile().mkdirs();
InputStream input = null;
- OutputStream output;
+ OutputStream output = null;
try {
- input = new FileInputStream(source);
- output = new FileOutputStream(destination);
+ input = new BufferedInputStream(new FileInputStream(source));
+ output = new BufferedOutputStream(new FileOutputStream(destination));
} catch (FileNotFoundException e) {
Log.e("LocalStorage.copy: could not open file", e);
- if (input != null) {
- try {
- input.close();
- } catch (IOException e1) {
- // ignore
- }
- }
+ IOUtils.closeQuietly(input);
+ IOUtils.closeQuietly(output);
return false;
}
diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
index 7520e2e..6b2366c 100644
--- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java
+++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
@@ -2,11 +2,11 @@ package cgeo.geocaching.files;
import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
+import cgeo.geocaching.activity.AbstractListActivity;
import cgeo.geocaching.activity.ActivityMixin;
import org.apache.commons.lang3.StringUtils;
-import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -31,7 +31,7 @@ import java.util.List;
/**
* Dialog for choosing a file or directory.
*/
-public class SimpleDirChooser extends ListActivity {
+public class SimpleDirChooser extends AbstractListActivity {
private static final String PARENT_DIR = ".. ";
private File currentDir;
private FileArrayAdapter adapter;
@@ -46,7 +46,6 @@ public class SimpleDirChooser extends ListActivity {
ActivityMixin.setTheme(this);
setContentView(R.layout.simple_dir_chooser);
- setTitle(this.getResources().getString(R.string.simple_dir_chooser_title));
fill(currentDir);
@@ -106,13 +105,13 @@ public class SimpleDirChooser extends ListActivity {
public class FileArrayAdapter extends ArrayAdapter<Option> {
- private Context content;
+ private Context context;
private int id;
private List<Option> items;
public FileArrayAdapter(Context context, int simpleDirItemResId, List<Option> objects) {
super(context, simpleDirItemResId, objects);
- this.content = context;
+ this.context = context;
this.id = simpleDirItemResId;
this.items = objects;
}
@@ -126,7 +125,7 @@ public class SimpleDirChooser extends ListActivity {
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
- LayoutInflater vi = (LayoutInflater) content.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(id, null);
}
@@ -187,13 +186,12 @@ public class SimpleDirChooser extends ListActivity {
if (currentOption != lastOption) {
currentOption.setChecked(true);
lastPosition = position;
- okButton.setEnabled(true);
- okButton.setVisibility(View.VISIBLE);
} else {
lastPosition = -1;
- okButton.setEnabled(false);
- okButton.setVisibility(View.INVISIBLE);
}
+ final boolean enabled = currentOption.isChecked() && !currentOption.getName().equals(PARENT_DIR);
+ okButton.setEnabled(enabled);
+ okButton.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
adapter.notifyDataSetChanged();
}
}
@@ -238,7 +236,7 @@ public class SimpleDirChooser extends ListActivity {
@Override
public boolean accept(File dir, String filename) {
File file = new File(dir, filename);
- return file.isDirectory();
+ return file.isDirectory() && file.canWrite();
}
}
diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java
index 4b6f382..cadcf49 100644
--- a/main/src/cgeo/geocaching/filter/AttributeFilter.java
+++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java
@@ -1,16 +1,16 @@
package cgeo.geocaching.filter;
-import cgeo.geocaching.R;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.LoadFlags.LoadFlag;
-import org.apache.commons.lang3.StringUtils;
-
import android.content.res.Resources;
import java.util.EnumSet;
+import java.util.LinkedList;
+import java.util.List;
class AttributeFilter extends AbstractFilter {
@@ -24,13 +24,7 @@ class AttributeFilter extends AbstractFilter {
private static String getName(final String attribute, final Resources res, final String packageName) {
// dynamically search for a translation of the attribute
final int id = res.getIdentifier(attribute, "string", packageName);
- if (id > 0) {
- final String translated = res.getString(id);
- if (StringUtils.isNotBlank(translated)) {
- return translated;
- }
- }
- return attribute;
+ return id > 0 ? res.getString(id) : attribute;
}
@Override
@@ -45,14 +39,13 @@ class AttributeFilter extends AbstractFilter {
public static class Factory implements IFilterFactory {
@Override
- public IFilter[] getFilters() {
+ public List<IFilter> getFilters() {
final String packageName = cgeoapplication.getInstance().getBaseContext().getPackageName();
final Resources res = cgeoapplication.getInstance().getResources();
- final String[] ids = res.getStringArray(R.array.attribute_ids);
- final IFilter[] filters = new IFilter[ids.length];
- for (int i = 0; i < ids.length; i++) {
- filters[i] = new AttributeFilter(getName("attribute_" + ids[i], res, packageName), ids[i]);
+ final List<IFilter> filters = new LinkedList<IFilter>();
+ for (final String id: res.getStringArray(R.array.attribute_ids)) {
+ filters.add(new AttributeFilter(getName("attribute_" + id, res, packageName), id));
}
return filters;
}
diff --git a/main/src/cgeo/geocaching/filter/DifficultyFilter.java b/main/src/cgeo/geocaching/filter/DifficultyFilter.java
index c0ec61a..8099a51 100644
--- a/main/src/cgeo/geocaching/filter/DifficultyFilter.java
+++ b/main/src/cgeo/geocaching/filter/DifficultyFilter.java
@@ -4,6 +4,7 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import java.util.ArrayList;
+import java.util.List;
class DifficultyFilter extends AbstractRangeFilter {
@@ -19,12 +20,12 @@ class DifficultyFilter extends AbstractRangeFilter {
public static class Factory implements IFilterFactory {
@Override
- public IFilter[] getFilters() {
+ public List<IFilter> getFilters() {
final ArrayList<IFilter> filters = new ArrayList<IFilter>(5);
for (int difficulty = 1; difficulty <= 5; difficulty++) {
filters.add(new DifficultyFilter(difficulty));
}
- return filters.toArray(new IFilter[filters.size()]);
+ return filters;
}
}
diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
index be63a08..a1d42cc 100644
--- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java
+++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
@@ -16,6 +16,7 @@ import android.widget.ArrayAdapter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
public final class FilterUserInterface {
@@ -101,9 +102,9 @@ public final class FilterUserInterface {
}
private void selectFromFactory(final IFilterFactory factory, final String menuTitle, final RunnableWithArgument<IFilter> runAfterwards) {
- final IFilter[] filters = factory.getFilters();
- if (filters.length == 1) {
- runAfterwards.run(filters[0]);
+ final List<IFilter> filters = Collections.unmodifiableList(factory.getFilters());
+ if (filters.size() == 1) {
+ runAfterwards.run(filters.get(0));
return;
}
@@ -114,7 +115,7 @@ public final class FilterUserInterface {
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
- runAfterwards.run(filters[item]);
+ runAfterwards.run(filters.get(item));
}
});
diff --git a/main/src/cgeo/geocaching/filter/IFilterFactory.java b/main/src/cgeo/geocaching/filter/IFilterFactory.java
index 3491fd7..e750639 100644
--- a/main/src/cgeo/geocaching/filter/IFilterFactory.java
+++ b/main/src/cgeo/geocaching/filter/IFilterFactory.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.filter;
+import java.util.List;
+
interface IFilterFactory {
- public IFilter[] getFilters();
+ public List<? extends IFilter> getFilters();
}
diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
index f3e57de..74befda 100644
--- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java
+++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
@@ -4,6 +4,9 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.cgeoapplication;
+import java.util.Collections;
+import java.util.List;
+
class ModifiedFilter extends AbstractFilter implements IFilterFactory {
public ModifiedFilter() {
@@ -17,7 +20,7 @@ class ModifiedFilter extends AbstractFilter implements IFilterFactory {
}
@Override
- public IFilter[] getFilters() {
- return new IFilter[] { this };
+ public List<ModifiedFilter> getFilters() {
+ return Collections.singletonList(this);
}
}
diff --git a/main/src/cgeo/geocaching/filter/OriginFilter.java b/main/src/cgeo/geocaching/filter/OriginFilter.java
index a880092..bd4e41e 100644
--- a/main/src/cgeo/geocaching/filter/OriginFilter.java
+++ b/main/src/cgeo/geocaching/filter/OriginFilter.java
@@ -7,6 +7,7 @@ import cgeo.geocaching.connector.IConnector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
public class OriginFilter extends AbstractFilter {
@@ -25,7 +26,7 @@ public class OriginFilter extends AbstractFilter {
public static final class Factory implements IFilterFactory {
@Override
- public IFilter[] getFilters() {
+ public List<OriginFilter> getFilters() {
final ArrayList<OriginFilter> filters = new ArrayList<OriginFilter>();
for (IConnector connector : ConnectorFactory.getConnectors()) {
filters.add(new OriginFilter(connector));
@@ -40,7 +41,7 @@ public class OriginFilter extends AbstractFilter {
}
});
- return filters.toArray(new OriginFilter[filters.size()]);
+ return filters;
}
}
diff --git a/main/src/cgeo/geocaching/filter/SizeFilter.java b/main/src/cgeo/geocaching/filter/SizeFilter.java
index 7a34c83..8ddc475 100644
--- a/main/src/cgeo/geocaching/filter/SizeFilter.java
+++ b/main/src/cgeo/geocaching/filter/SizeFilter.java
@@ -3,7 +3,8 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.enumerations.CacheSize;
-import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
class SizeFilter extends AbstractFilter {
private final CacheSize cacheSize;
@@ -26,15 +27,15 @@ class SizeFilter extends AbstractFilter {
public static class Factory implements IFilterFactory {
@Override
- public IFilter[] getFilters() {
+ public List<IFilter> getFilters() {
final CacheSize[] cacheSizes = CacheSize.values();
- final ArrayList<SizeFilter> filters = new ArrayList<SizeFilter>();
+ final List<IFilter> filters = new LinkedList<IFilter>();
for (CacheSize cacheSize : cacheSizes) {
if (cacheSize != CacheSize.UNKNOWN) {
filters.add(new SizeFilter(cacheSize));
}
}
- return filters.toArray(new SizeFilter[filters.size()]);
+ return filters;
}
}
diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java
index 0df47c1..e18128d 100644
--- a/main/src/cgeo/geocaching/filter/StateFilter.java
+++ b/main/src/cgeo/geocaching/filter/StateFilter.java
@@ -9,6 +9,7 @@ import android.content.res.Resources;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
abstract class StateFilter extends AbstractFilter {
@@ -86,17 +87,41 @@ abstract class StateFilter extends AbstractFilter {
}
}
+ static class StateStoredFilter extends StateFilter {
+ public StateStoredFilter() {
+ super(res.getString(R.string.cache_status_stored));
+ }
+
+ @Override
+ public boolean accepts(Geocache cache) {
+ return cache.isOffline();
+ }
+ }
+
+ static class StateNotStoredFilter extends StateFilter {
+ public StateNotStoredFilter() {
+ super(res.getString(R.string.cache_status_not_stored));
+ }
+
+ @Override
+ public boolean accepts(Geocache cache) {
+ return !cache.isOffline();
+ }
+ }
+
public static class Factory implements IFilterFactory {
@Override
- public IFilter[] getFilters() {
- final ArrayList<StateFilter> filters = new ArrayList<StateFilter>();
+ public List<StateFilter> getFilters() {
+ final List<StateFilter> filters = new ArrayList<StateFilter>(6);
filters.add(new StateFoundFilter());
filters.add(new StateArchivedFilter());
filters.add(new StateDisabledFilter());
filters.add(new StatePremiumFilter());
filters.add(new StateNonPremiumFilter());
filters.add(new StateOfflineLogFilter());
+ filters.add(new StateStoredFilter());
+ filters.add(new StateNotStoredFilter());
Collections.sort(filters, new Comparator<StateFilter>() {
@@ -106,7 +131,7 @@ abstract class StateFilter extends AbstractFilter {
}
});
- return filters.toArray(new StateFilter[filters.size()]);
+ return filters;
}
}
diff --git a/main/src/cgeo/geocaching/filter/TerrainFilter.java b/main/src/cgeo/geocaching/filter/TerrainFilter.java
index f7703d5..87372c6 100644
--- a/main/src/cgeo/geocaching/filter/TerrainFilter.java
+++ b/main/src/cgeo/geocaching/filter/TerrainFilter.java
@@ -1,10 +1,10 @@
package cgeo.geocaching.filter;
-
-import cgeo.geocaching.R;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
import java.util.ArrayList;
+import java.util.List;
class TerrainFilter extends AbstractRangeFilter {
@@ -19,12 +19,12 @@ class TerrainFilter extends AbstractRangeFilter {
public static class Factory implements IFilterFactory {
@Override
- public IFilter[] getFilters() {
+ public List<IFilter> getFilters() {
final ArrayList<IFilter> filters = new ArrayList<IFilter>(5);
for (int terrain = 1; terrain <= 5; terrain++) {
filters.add(new TerrainFilter(terrain));
}
- return filters.toArray(new IFilter[filters.size()]);
+ return filters;
}
}
diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java
index 3225daa..5eff8a7 100644
--- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java
+++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java
@@ -1,9 +1,12 @@
package cgeo.geocaching.filter;
-import cgeo.geocaching.R;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.R;
import cgeo.geocaching.cgeoapplication;
+import java.util.Collections;
+import java.util.List;
+
class TrackablesFilter extends AbstractFilter implements IFilterFactory {
public TrackablesFilter() {
super(cgeoapplication.getInstance().getString(R.string.caches_filter_track));
@@ -15,8 +18,8 @@ class TrackablesFilter extends AbstractFilter implements IFilterFactory {
}
@Override
- public IFilter[] getFilters() {
- return new IFilter[] { this };
+ public List<TrackablesFilter> getFilters() {
+ return Collections.singletonList(this);
}
}
diff --git a/main/src/cgeo/geocaching/filter/TypeFilter.java b/main/src/cgeo/geocaching/filter/TypeFilter.java
index eeab552..ea0ccff 100644
--- a/main/src/cgeo/geocaching/filter/TypeFilter.java
+++ b/main/src/cgeo/geocaching/filter/TypeFilter.java
@@ -3,7 +3,8 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.enumerations.CacheType;
-import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
class TypeFilter extends AbstractFilter {
private final CacheType cacheType;
@@ -26,15 +27,15 @@ class TypeFilter extends AbstractFilter {
public static class Factory implements IFilterFactory {
@Override
- public IFilter[] getFilters() {
+ public List<IFilter> getFilters() {
final CacheType[] types = CacheType.values();
- final ArrayList<IFilter> filters = new ArrayList<IFilter>(types.length);
+ final List<IFilter> filters = new LinkedList<IFilter>();
for (CacheType cacheType : types) {
if (cacheType != CacheType.ALL) {
filters.add(new TypeFilter(cacheType));
}
}
- return filters.toArray(new IFilter[filters.size()]);
+ return filters;
}
}
diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java
index a053f31..f6cfb84 100644
--- a/main/src/cgeo/geocaching/gcvote/GCVote.java
+++ b/main/src/cgeo/geocaching/gcvote/GCVote.java
@@ -173,12 +173,15 @@ public final class GCVote {
/**
* Transmit user vote to gcvote.com
- *
+ *
* @param cache
* @param vote
- * @return
+ * @return {@code true} if the rating was submitted successfully
*/
public static boolean setRating(Geocache cache, double vote) {
+ if (!Settings.isGCvoteLogin()) {
+ return false;
+ }
if (!cache.supportsGCVote()) {
return false;
}
diff --git a/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java
index ca2461c..09ea459 100644
--- a/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java
+++ b/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java
@@ -19,7 +19,11 @@ public class CoordsGeocacheListLoader extends AbstractSearchLoader {
@Override
public SearchResult runSearch() {
- SearchResult search = GCParser.searchByCoords(coords, Settings.getCacheType(), Settings.isShowCaptcha(), this);
+
+ SearchResult search = new SearchResult();
+ if (Settings.isGCConnectorActive()) {
+ search = GCParser.searchByCoords(coords, Settings.getCacheType(), Settings.isShowCaptcha(), this);
+ }
for (ISearchByCenter centerConn : ConnectorFactory.getSearchByCenterConnectors()) {
if (centerConn.isActivated()) {
diff --git a/main/src/cgeo/geocaching/maps/AbstractMap.java b/main/src/cgeo/geocaching/maps/AbstractMap.java
index c028e51..d9ee751 100644
--- a/main/src/cgeo/geocaching/maps/AbstractMap.java
+++ b/main/src/cgeo/geocaching/maps/AbstractMap.java
@@ -63,8 +63,6 @@ public abstract class AbstractMap {
public abstract void goHome(View view);
- public abstract void goManual(View view);
-
public abstract void onSaveInstanceState(final Bundle outState);
}
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index 30bbadf..97c4b7e 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -116,24 +116,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private static final String EXTRAS_MAP_MODE = "mapMode";
private static final String EXTRAS_LIVE_ENABLED = "liveEnabled";
- private static final int MENU_SELECT_MAPVIEW = 1;
- private static final int MENU_MAP_LIVE = 2;
- private static final int MENU_STORE_CACHES = 3;
- private static final int SUBMENU_MODES = 4;
- private static final int MENU_TRAIL_MODE = 81;
- private static final int MENU_THEME_MODE = 82;
- private static final int MENU_CIRCLE_MODE = 83;
- private static final int SUBMENU_STRATEGY = 5;
- private static final int MENU_STRATEGY_FASTEST = 51;
- private static final int MENU_STRATEGY_FAST = 52;
- private static final int MENU_STRATEGY_AUTO = 53;
- private static final int MENU_STRATEGY_DETAILED = 74;
-
- private static final int MENU_AS_LIST = 7;
-
private static final String BUNDLE_MAP_SOURCE = "mapSource";
private static final String BUNDLE_MAP_STATE = "mapState";
private static final String BUNDLE_LIVE_ENABLED = "liveEnabled";
+ private static final String BUNDLE_TRAIL_HISTORY = "trailHistory";
private Resources res = null;
private MapItemFactory mapItemFactory = null;
@@ -173,8 +159,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private static final int[][] INSET_FOUND = { { 0, 0, 21, 28 }, { 0, 0, 25, 35 } }; // top left, 12x12 / 16x16
private static final int[][] INSET_USERMODIFIEDCOORDS = { { 21, 28, 0, 0 }, { 19, 25, 0, 0 } }; // bottom right, 12x12 / 26x26
private static final int[][] INSET_PERSONALNOTE = { { 0, 28, 21, 0 }, { 0, 25, 19, 0 } }; // bottom left, 12x12 / 26x26
- private static final int MENU_GROUP_MAP_SOURCES = 1;
- private static final int MENU_GROUP_MAP_STRATEGY = 2;
private SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>();
/** Count of caches currently visible */
@@ -360,6 +344,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
outState.putInt(BUNDLE_MAP_SOURCE, currentSourceId);
outState.putIntArray(BUNDLE_MAP_STATE, currentMapState());
outState.putBoolean(BUNDLE_LIVE_ENABLED, isLiveEnabled);
+ if (overlayPosition != null) {
+ outState.putParcelableArrayList(BUNDLE_TRAIL_HISTORY, overlayPosition.getHistory());
+ }
}
@Override
@@ -382,9 +369,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (extras != null) {
mapMode = (MapMode) extras.get(EXTRAS_MAP_MODE);
isLiveEnabled = extras.getBoolean(EXTRAS_LIVE_ENABLED, false);
- searchIntent = (SearchResult) extras.getParcelable(EXTRAS_SEARCH);
+ searchIntent = extras.getParcelable(EXTRAS_SEARCH);
geocodeIntent = extras.getString(EXTRAS_GEOCODE);
- coordsIntent = (Geopoint) extras.getParcelable(EXTRAS_COORDS);
+ coordsIntent = extras.getParcelable(EXTRAS_COORDS);
waypointTypeIntent = WaypointType.findById(extras.getString(EXTRAS_WPTTYPE));
mapStateIntent = extras.getIntArray(EXTRAS_MAPSTATE);
mapTitle = extras.getString(EXTRAS_MAP_TITLE);
@@ -397,11 +384,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
mapTitle = res.getString(R.string.map_map);
}
+ ArrayList<Location> trailHistory = null;
+
// Get fresh map information from the bundle if any
if (savedInstanceState != null) {
currentSourceId = savedInstanceState.getInt(BUNDLE_MAP_SOURCE, Settings.getMapSource().getNumericalId());
mapStateIntent = savedInstanceState.getIntArray(BUNDLE_MAP_STATE);
isLiveEnabled = savedInstanceState.getBoolean(BUNDLE_LIVE_ENABLED, false);
+ trailHistory = savedInstanceState.getParcelableArrayList(BUNDLE_TRAIL_HISTORY);
} else {
currentSourceId = Settings.getMapSource().getNumericalId();
}
@@ -438,6 +428,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (overlayPosition == null) {
overlayPosition = mapView.createAddPositionOverlay(activity);
+ if (trailHistory != null) {
+ overlayPosition.setHistory(trailHistory);
+ }
}
if (overlayScale == null) {
@@ -541,36 +534,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
@Override
public boolean onCreateOptionsMenu(Menu menu) {
+ // menu inflation happens in Google/Mapsforge specific classes
+ super.onCreateOptionsMenu(menu);
- SubMenu submenu = menu.addSubMenu(0, MENU_SELECT_MAPVIEW, 0, res.getString(R.string.map_view_map)).setIcon(R.drawable.ic_menu_mapmode);
- addMapViewMenuItems(submenu);
+ MapProviderFactory.addMapviewMenuItems(menu);
- menu.add(0, MENU_MAP_LIVE, 0, res.getString(R.string.map_live_disable)).setIcon(R.drawable.ic_menu_refresh);
- menu.add(0, MENU_STORE_CACHES, 0, res.getString(R.string.caches_store_offline)).setIcon(R.drawable.ic_menu_set_as).setEnabled(false);
- SubMenu subMenuModes = menu.addSubMenu(0, SUBMENU_MODES, 0, res.getString(R.string.map_modes)).setIcon(R.drawable.ic_menu_mark);
- subMenuModes.add(0, MENU_TRAIL_MODE, 0, res.getString(R.string.map_trail_hide)).setIcon(R.drawable.ic_menu_trail);
- subMenuModes.add(0, MENU_CIRCLE_MODE, 0, res.getString(R.string.map_circles_hide)).setIcon(R.drawable.ic_menu_circle);
- subMenuModes.add(0, MENU_THEME_MODE, 0, res.getString(R.string.map_theme_select)).setIcon(R.drawable.ic_menu_preferences);
-
- Strategy strategy = Settings.getLiveMapStrategy();
- SubMenu subMenuStrategy = menu.addSubMenu(0, SUBMENU_STRATEGY, 0, res.getString(R.string.map_strategy)).setIcon(R.drawable.ic_menu_preferences);
+ final SubMenu subMenuStrategy = menu.findItem(R.id.submenu_strategy).getSubMenu();
subMenuStrategy.setHeaderTitle(res.getString(R.string.map_strategy_title));
- subMenuStrategy.add(MENU_GROUP_MAP_STRATEGY, MENU_STRATEGY_FASTEST, 0, Strategy.FASTEST.getL10n()).setCheckable(true).setChecked(strategy == Strategy.FASTEST);
- subMenuStrategy.add(MENU_GROUP_MAP_STRATEGY, MENU_STRATEGY_FAST, 0, Strategy.FAST.getL10n()).setCheckable(true).setChecked(strategy == Strategy.FAST);
- subMenuStrategy.add(MENU_GROUP_MAP_STRATEGY, MENU_STRATEGY_AUTO, 0, Strategy.AUTO.getL10n()).setCheckable(true).setChecked(strategy == Strategy.AUTO);
- subMenuStrategy.add(MENU_GROUP_MAP_STRATEGY, MENU_STRATEGY_DETAILED, 0, Strategy.DETAILED.getL10n()).setCheckable(true).setChecked(strategy == Strategy.DETAILED);
- subMenuStrategy.setGroupCheckable(MENU_GROUP_MAP_STRATEGY, true, true);
-
- menu.add(0, MENU_AS_LIST, 0, res.getString(R.string.map_as_list)).setIcon(R.drawable.ic_menu_agenda);
-
return true;
}
- private static void addMapViewMenuItems(final Menu menu) {
- MapProviderFactory.addMapviewMenuItems(menu, MENU_GROUP_MAP_SOURCES);
- menu.setGroupCheckable(MENU_GROUP_MAP_SOURCES, true, true);
- }
-
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
@@ -582,14 +555,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
try {
- MenuItem item = menu.findItem(MENU_TRAIL_MODE);
+ MenuItem item = menu.findItem(R.id.menu_trail_mode);
if (Settings.isMapTrail()) {
item.setTitle(res.getString(R.string.map_trail_hide));
} else {
item.setTitle(res.getString(R.string.map_trail_show));
}
- item = menu.findItem(MENU_MAP_LIVE); // live map
+ item = menu.findItem(R.id.menu_map_live); // live map
if (isLiveEnabled) {
item.setTitle(res.getString(R.string.map_live_disable));
} else {
@@ -597,21 +570,27 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
final Set<String> geocodesInViewport = getGeocodesForCachesInViewport();
- menu.findItem(MENU_STORE_CACHES).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches());
+ menu.findItem(R.id.menu_store_caches).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches());
- item = menu.findItem(MENU_CIRCLE_MODE); // show circles
+ item = menu.findItem(R.id.menu_circle_mode); // show circles
if (overlayCaches != null && overlayCaches.getCircles()) {
item.setTitle(res.getString(R.string.map_circles_hide));
} else {
item.setTitle(res.getString(R.string.map_circles_show));
}
- item = menu.findItem(MENU_THEME_MODE); // show theme selection
+ item = menu.findItem(R.id.menu_theme_mode); // show theme selection
item.setVisible(mapView.hasMapThemes());
- menu.findItem(MENU_AS_LIST).setEnabled(isLiveEnabled && !isLoading());
+ menu.findItem(R.id.menu_as_list).setEnabled(isLiveEnabled && !isLoading());
- menu.findItem(SUBMENU_STRATEGY).setEnabled(isLiveEnabled);
+ menu.findItem(R.id.submenu_strategy).setEnabled(isLiveEnabled);
+
+ Strategy strategy = Settings.getLiveMapStrategy();
+ menu.findItem(R.id.menu_strategy_fastest).setChecked(strategy == Strategy.FASTEST);
+ menu.findItem(R.id.menu_strategy_fast).setChecked(strategy == Strategy.FAST);
+ menu.findItem(R.id.menu_strategy_auto).setChecked(strategy == Strategy.AUTO);
+ menu.findItem(R.id.menu_strategy_detailed).setChecked(strategy == Strategy.DETAILED);
} catch (Exception e) {
Log.e("cgeomap.onPrepareOptionsMenu", e);
}
@@ -623,12 +602,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
public boolean onOptionsItemSelected(MenuItem item) {
final int id = item.getItemId();
switch (id) {
- case MENU_TRAIL_MODE:
+ case R.id.menu_trail_mode:
Settings.setMapTrail(!Settings.isMapTrail());
mapView.repaintRequired(overlayPosition);
ActivityMixin.invalidateOptionsMenu(activity);
return true;
- case MENU_MAP_LIVE:
+ case R.id.menu_map_live:
isLiveEnabled = !isLiveEnabled;
if (mapMode == MapMode.LIVE) {
Settings.setLiveMap(isLiveEnabled);
@@ -638,7 +617,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
searchIntent = null;
ActivityMixin.invalidateOptionsMenu(activity);
return true;
- case MENU_STORE_CACHES:
+ case R.id.menu_store_caches:
if (!isLoading()) {
final Set<String> geocodesInViewport = getGeocodesForCachesInViewport();
final List<String> geocodes = new ArrayList<String>();
@@ -672,7 +651,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
return true;
- case MENU_CIRCLE_MODE:
+ case R.id.menu_circle_mode:
if (overlayCaches == null) {
return false;
}
@@ -681,29 +660,29 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
mapView.repaintRequired(overlayCaches);
ActivityMixin.invalidateOptionsMenu(activity);
return true;
- case MENU_THEME_MODE:
+ case R.id.menu_theme_mode:
selectMapTheme();
return true;
- case MENU_AS_LIST: {
+ case R.id.menu_as_list: {
cgeocaches.startActivityMap(activity, new SearchResult(getGeocodesForCachesInViewport()));
return true;
}
- case MENU_STRATEGY_FASTEST: {
+ case R.id.menu_strategy_fastest: {
item.setChecked(true);
Settings.setLiveMapStrategy(Strategy.FASTEST);
return true;
}
- case MENU_STRATEGY_FAST: {
+ case R.id.menu_strategy_fast: {
item.setChecked(true);
Settings.setLiveMapStrategy(Strategy.FAST);
return true;
}
- case MENU_STRATEGY_AUTO: {
+ case R.id.menu_strategy_auto: {
item.setChecked(true);
Settings.setLiveMapStrategy(Strategy.AUTO);
return true;
}
- case MENU_STRATEGY_DETAILED: {
+ case R.id.menu_strategy_detailed: {
item.setChecked(true);
Settings.setLiveMapStrategy(Strategy.DETAILED);
return true;
@@ -751,9 +730,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
@Override
public void onClick(DialogInterface dialog, int newItem) {
- if (newItem == selectedItem) {
- // no change
- } else {
+ if (newItem != selectedItem) {
// Adjust index because of <default> selection
if (newItem > 0) {
Settings.setCustomRenderThemeFile(themeFiles[newItem - 1].getPath());
@@ -1179,7 +1156,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens);
if (searchResult != null) {
downloaded = true;
- if (searchResult.getError() == StatusCode.NOT_LOGGED_IN) {
+ if (searchResult.getError() == StatusCode.NOT_LOGGED_IN && Settings.isGCConnectorActive()) {
Login.login();
tokens = null;
} else {
@@ -1578,12 +1555,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
ActivityMixin.goHome(activity);
}
- // open manual entry
- @Override
- public void goManual(View view) {
- ActivityMixin.goManual(activity, "c:geo-live-map");
- }
-
@Override
public View makeView() {
ImageView imageView = new ImageView(activity);
@@ -1645,7 +1616,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
private CachesOverlayItemImpl getCacheItem(final Geocache cache) {
- final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(cache, cache.getType());
+ final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(cache, cache.getType().applyDistanceRule());
final int hashcode = new HashCodeBuilder()
.append(cache.isReliableLatLon())
@@ -1725,7 +1696,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
private CachesOverlayItemImpl getWaypointItem(final Waypoint waypoint) {
- final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(waypoint, null);
+ final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(waypoint, waypoint.getWaypointType().applyDistanceRule());
Drawable marker = getResources().getDrawable(!waypoint.isVisited() ? R.drawable.marker : R.drawable.marker_transparent);
final Drawable[] layers = new Drawable[] {
marker,
diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java
index 9bb4cef..74c92eb 100644
--- a/main/src/cgeo/geocaching/maps/CachesOverlay.java
+++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java
@@ -1,11 +1,11 @@
package cgeo.geocaching.maps;
import cgeo.geocaching.CachePopup;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.IWaypoint;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
import cgeo.geocaching.WaypointPopup;
-import cgeo.geocaching.Geocache;
import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.connector.gc.GCMap;
@@ -58,14 +58,14 @@ public class CachesOverlay extends AbstractItemizedOverlay {
mapItemFactory = mapProvider.getMapItemFactory();
}
- public void updateItems(CachesOverlayItemImpl item) {
+ void updateItems(CachesOverlayItemImpl item) {
List<CachesOverlayItemImpl> itemsPre = new ArrayList<CachesOverlayItemImpl>();
itemsPre.add(item);
updateItems(itemsPre);
}
- public void updateItems(List<CachesOverlayItemImpl> itemsPre) {
+ void updateItems(List<CachesOverlayItemImpl> itemsPre) {
if (itemsPre == null) {
return;
}
@@ -86,11 +86,11 @@ public class CachesOverlay extends AbstractItemizedOverlay {
}
}
- public boolean getCircles() {
+ boolean getCircles() {
return displayCircles;
}
- public void switchCircles() {
+ void switchCircles() {
displayCircles = !displayCircles;
}
@@ -130,12 +130,7 @@ public class CachesOverlay extends AbstractItemizedOverlay {
final GeoPointImpl itemGeo = mapItemFactory.getGeoPointBase(itemCoord);
projection.toPixels(itemGeo, center);
- final CacheType type = item.getType();
- if (type == null || type == CacheType.MULTI || type == CacheType.MYSTERY || type == CacheType.VIRTUAL || type.isEvent()) {
- blockedCircle.setColor(0x66000000);
- blockedCircle.setStyle(Style.STROKE);
- canvas.drawCircle(center.x, center.y, radius, blockedCircle);
- } else {
+ if (item.applyDistanceRule()) {
blockedCircle.setColor(0x66BB0000);
blockedCircle.setStyle(Style.STROKE);
canvas.drawCircle(center.x, center.y, radius, blockedCircle);
@@ -143,6 +138,10 @@ public class CachesOverlay extends AbstractItemizedOverlay {
blockedCircle.setColor(0x44BB0000);
blockedCircle.setStyle(Style.FILL);
canvas.drawCircle(center.x, center.y, radius, blockedCircle);
+ } else {
+ blockedCircle.setColor(0x66000000);
+ blockedCircle.setStyle(Style.STROKE);
+ canvas.drawCircle(center.x, center.y, radius, blockedCircle);
}
}
canvas.setDrawFilter(removeFilter);
@@ -209,9 +208,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);
diff --git a/main/src/cgeo/geocaching/maps/MapProviderFactory.java b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
index 483189f..5ce8ab6 100644
--- a/main/src/cgeo/geocaching/maps/MapProviderFactory.java
+++ b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps;
+import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
import cgeo.geocaching.maps.google.GoogleMapProvider;
import cgeo.geocaching.maps.interfaces.MapProvider;
@@ -7,6 +8,7 @@ import cgeo.geocaching.maps.interfaces.MapSource;
import cgeo.geocaching.maps.mapsforge.MapsforgeMapProvider;
import android.view.Menu;
+import android.view.SubMenu;
import java.util.ArrayList;
import java.util.List;
@@ -43,13 +45,16 @@ public class MapProviderFactory {
return provider1 == provider2 && provider1.isSameActivity(source1, source2);
}
- public static void addMapviewMenuItems(final Menu parentMenu, final int groupId) {
+ public static void addMapviewMenuItems(Menu menu) {
+ final SubMenu parentMenu = menu.findItem(R.id.menu_select_mapview).getSubMenu();
+
final int currentSource = Settings.getMapSource().getNumericalId();
for (int i = 0; i < mapSources.size(); i++) {
final MapSource mapSource = mapSources.get(i);
final int id = mapSource.getNumericalId();
- parentMenu.add(groupId, id, i, mapSource.getName()).setCheckable(true).setChecked(id == currentSource);
+ parentMenu.add(R.id.menu_group_map_sources, id, i, mapSource.getName()).setCheckable(true).setChecked(id == currentSource);
}
+ parentMenu.setGroupCheckable(R.id.menu_group_map_sources, true, true);
}
public static MapSource getMapSource(int id) {
diff --git a/main/src/cgeo/geocaching/maps/PositionOverlay.java b/main/src/cgeo/geocaching/maps/PositionOverlay.java
index fec67ef..08acd2f 100644
--- a/main/src/cgeo/geocaching/maps/PositionOverlay.java
+++ b/main/src/cgeo/geocaching/maps/PositionOverlay.java
@@ -22,7 +22,6 @@ import android.graphics.Point;
import android.location.Location;
import java.util.ArrayList;
-import java.util.List;
public class PositionOverlay implements GeneralOverlay {
private Location coordinates = null;
@@ -39,7 +38,7 @@ public class PositionOverlay implements GeneralOverlay {
private PaintFlagsDrawFilter setfil = null;
private PaintFlagsDrawFilter remfil = null;
private Location historyRecent = null;
- private List<Location> history = new ArrayList<Location>();
+ private ArrayList<Location> history = new ArrayList<Location>();
private Point historyPointN = new Point();
private Point historyPointP = new Point();
private Activity activity;
@@ -229,4 +228,12 @@ public class PositionOverlay implements GeneralOverlay {
public OverlayImpl getOverlayImpl() {
return this.ovlImpl;
}
+
+ public ArrayList<Location> getHistory() {
+ return history;
+ }
+
+ public void setHistory(ArrayList<Location> inHistory) {
+ history = inHistory;
+ }
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java b/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java
index 4868a30..21d78a0 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlay.java
@@ -73,12 +73,12 @@ public class GoogleCacheOverlay extends ItemizedOverlay<GoogleCacheOverlayItem>
@Override
public Drawable superBoundCenter(Drawable markerIn) {
- return super.boundCenter(markerIn);
+ return ItemizedOverlay.boundCenter(markerIn);
}
@Override
public Drawable superBoundCenterBottom(Drawable marker) {
- return super.boundCenterBottom(marker);
+ return ItemizedOverlay.boundCenterBottom(marker);
}
@Override
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlayItem.java b/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlayItem.java
index 2ac66af..b26654a 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlayItem.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleCacheOverlayItem.java
@@ -1,21 +1,20 @@
package cgeo.geocaching.maps.google;
import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.OverlayItem;
public class GoogleCacheOverlayItem extends OverlayItem implements CachesOverlayItemImpl {
- final private CacheType cacheType;
final private IWaypoint coord;
+ final private boolean applyDistanceRule;
- public GoogleCacheOverlayItem(final IWaypoint coordinate, final CacheType type) {
+ public GoogleCacheOverlayItem(final IWaypoint coordinate, boolean applyDistanceRule) {
super(new GeoPoint(coordinate.getCoords().getLatitudeE6(), coordinate.getCoords().getLongitudeE6()), coordinate.getName(), "");
- this.cacheType = type;
this.coord = coordinate;
+ this.applyDistanceRule = applyDistanceRule;
}
@Override
@@ -24,8 +23,8 @@ public class GoogleCacheOverlayItem extends OverlayItem implements CachesOverlay
}
@Override
- public CacheType getType() {
- return cacheType;
+ public boolean applyDistanceRule() {
+ return applyDistanceRule;
}
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java
index 5649d19..dcff363 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.R;
import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.maps.AbstractMap;
import cgeo.geocaching.maps.CGeoMap;
@@ -83,7 +84,9 @@ public class GoogleMapActivity extends MapActivity implements MapActivityImpl, F
@Override
public boolean superOnCreateOptionsMenu(Menu menu) {
- return super.onCreateOptionsMenu(menu);
+ final boolean result = super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.map_activity, menu);
+ return result;
}
@Override
@@ -122,12 +125,6 @@ public class GoogleMapActivity extends MapActivity implements MapActivityImpl, F
mapBase.goHome(view);
}
- // open manual entry
- @Override
- 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/google/GoogleMapItemFactory.java b/main/src/cgeo/geocaching/maps/google/GoogleMapItemFactory.java
index f40c799..c708dc5 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapItemFactory.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapItemFactory.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.maps.google;
import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
@@ -15,7 +14,7 @@ public class GoogleMapItemFactory implements MapItemFactory {
}
@Override
- public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, final CacheType type) {
- return new GoogleCacheOverlayItem(coordinate, type);
+ public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, boolean applyDistanceRule) {
+ return new GoogleCacheOverlayItem(coordinate, applyDistanceRule);
}
}
diff --git a/main/src/cgeo/geocaching/maps/interfaces/CachesOverlayItemImpl.java b/main/src/cgeo/geocaching/maps/interfaces/CachesOverlayItemImpl.java
index 5bf3ed2..03fa21f 100644
--- a/main/src/cgeo/geocaching/maps/interfaces/CachesOverlayItemImpl.java
+++ b/main/src/cgeo/geocaching/maps/interfaces/CachesOverlayItemImpl.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.maps.interfaces;
import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.enumerations.CacheType;
/**
* Covers the common functions of the provider-specific
@@ -11,6 +10,5 @@ public interface CachesOverlayItemImpl extends OverlayItemImpl {
public IWaypoint getCoord();
- public CacheType getType();
-
+ public boolean applyDistanceRule();
}
diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java
index dc7dca5..e7deebd 100644
--- a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java
+++ b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java
@@ -35,6 +35,4 @@ public interface MapActivityImpl {
public abstract void goHome(View view);
- public abstract void goManual(View view);
-
}
diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java b/main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java
index e02d472..22c6698 100644
--- a/main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java
+++ b/main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java
@@ -1,13 +1,12 @@
package cgeo.geocaching.maps.interfaces;
import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Geopoint;
public interface MapItemFactory {
public GeoPointImpl getGeoPointBase(final Geopoint coords);
- public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint iWaypoint, final CacheType type);
+ public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint iWaypoint, final boolean applyDistanceRule);
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java
index 0bd2484..9e14e36 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java
@@ -71,12 +71,12 @@ public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlay
@Override
public Drawable superBoundCenter(Drawable markerIn) {
- return super.boundCenter(markerIn);
+ return ItemizedOverlay.boundCenter(markerIn);
}
@Override
public Drawable superBoundCenterBottom(Drawable marker) {
- return super.boundCenterBottom(marker);
+ return ItemizedOverlay.boundCenterBottom(marker);
}
@Override
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java
index 29f13b3..27ca664 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.maps.mapsforge;
import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl;
import org.mapsforge.android.maps.overlay.OverlayItem;
@@ -10,14 +9,14 @@ import org.mapsforge.core.GeoPoint;
import android.graphics.drawable.Drawable;
public class MapsforgeCacheOverlayItem extends OverlayItem implements CachesOverlayItemImpl {
- final private CacheType cacheType;
final private IWaypoint coord;
+ final private boolean applyDistanceRule;
- public MapsforgeCacheOverlayItem(IWaypoint coordinate, final CacheType type) {
+ public MapsforgeCacheOverlayItem(IWaypoint coordinate, boolean applyDistanceRule) {
super(new GeoPoint(coordinate.getCoords().getLatitudeE6(), coordinate.getCoords().getLongitudeE6()), coordinate.getName(), "");
- this.cacheType = type;
this.coord = coordinate;
+ this.applyDistanceRule = applyDistanceRule;
}
@Override
@@ -26,13 +25,13 @@ public class MapsforgeCacheOverlayItem extends OverlayItem implements CachesOver
}
@Override
- public CacheType getType() {
- return cacheType;
+ public Drawable getMarker(int index) {
+ return getMarker();
}
@Override
- public Drawable getMarker(int index) {
- return getMarker();
+ public boolean applyDistanceRule() {
+ return applyDistanceRule;
}
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java
index f850402..232fe3c 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.R;
import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.maps.AbstractMap;
import cgeo.geocaching.maps.CGeoMap;
@@ -78,7 +79,9 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl
@Override
public boolean superOnCreateOptionsMenu(Menu menu) {
- return super.onCreateOptionsMenu(menu);
+ final boolean result = super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.map_activity, menu);
+ return result;
}
@Override
@@ -117,12 +120,6 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl
mapBase.goHome(view);
}
- // open manual entry
- @Override
- 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/MapsforgeMapItemFactory.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapItemFactory.java
index 10fcb03..4ade09c 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapItemFactory.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapItemFactory.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.maps.mapsforge;
import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
@@ -15,8 +14,8 @@ public class MapsforgeMapItemFactory implements MapItemFactory {
}
@Override
- public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, final CacheType type) {
- return new MapsforgeCacheOverlayItem(coordinate, type);
+ public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, boolean applyDistanceRule) {
+ return new MapsforgeCacheOverlayItem(coordinate, applyDistanceRule);
}
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java
index 581548f..30355fd 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java
@@ -71,12 +71,12 @@ public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlay
@Override
public Drawable superBoundCenter(Drawable markerIn) {
- return super.boundCenter(markerIn);
+ return ItemizedOverlay.boundCenter(markerIn);
}
@Override
public Drawable superBoundCenterBottom(Drawable marker) {
- return super.boundCenterBottom(marker);
+ return ItemizedOverlay.boundCenterBottom(marker);
}
@Override
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlayItem.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlayItem.java
index 6b74de5..4e4a358 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlayItem.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlayItem.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.maps.mapsforge.v024;
import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl;
import org.mapsforge.android.mapsold.GeoPoint;
@@ -10,14 +9,14 @@ import org.mapsforge.android.mapsold.OverlayItem;
import android.graphics.drawable.Drawable;
public class MapsforgeCacheOverlayItem extends OverlayItem implements CachesOverlayItemImpl {
- final private CacheType cacheType;
final private IWaypoint coord;
+ final private boolean applyDistanceRule;
- public MapsforgeCacheOverlayItem(IWaypoint coordinate, final CacheType type) {
+ public MapsforgeCacheOverlayItem(IWaypoint coordinate, boolean applyDistanceRule) {
super(new GeoPoint(coordinate.getCoords().getLatitudeE6(), coordinate.getCoords().getLongitudeE6()), coordinate.getName(), "");
- this.cacheType = type;
this.coord = coordinate;
+ this.applyDistanceRule = applyDistanceRule;
}
@Override
@@ -26,13 +25,13 @@ public class MapsforgeCacheOverlayItem extends OverlayItem implements CachesOver
}
@Override
- public CacheType getType() {
- return cacheType;
+ public Drawable getMarker(int index) {
+ return getMarker();
}
@Override
- public Drawable getMarker(int index) {
- return getMarker();
+ public boolean applyDistanceRule() {
+ return applyDistanceRule;
}
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
index ed8a7bc..33ed30e 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
@@ -117,12 +117,6 @@ public class MapsforgeMapActivity024 extends MapActivity implements MapActivityI
mapBase.goHome(view);
}
- // open manual entry
- @Override
- 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/MapsforgeMapItemFactory024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapItemFactory024.java
index 5c64592..4f1d34c 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapItemFactory024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapItemFactory024.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.maps.mapsforge.v024;
import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
@@ -15,7 +14,7 @@ public class MapsforgeMapItemFactory024 implements MapItemFactory {
}
@Override
- public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, final CacheType type) {
- return new MapsforgeCacheOverlayItem(coordinate, type);
+ public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, boolean applyDistanceRule) {
+ return new MapsforgeCacheOverlayItem(coordinate, applyDistanceRule);
}
}
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index 38498d6..d5b610c 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.files.LocalStorage;
+import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.ImageHelper;
import cgeo.geocaching.utils.Log;
@@ -21,10 +22,10 @@ import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.text.Html;
+import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.IOException;
import java.util.Date;
public class HtmlImage implements Html.ImageGetter {
@@ -66,6 +67,7 @@ public class HtmlImage implements Html.ImageGetter {
bfOptions = new BitmapFactory.Options();
bfOptions.inTempStorage = new byte[16 * 1024];
+ bfOptions.inPreferredConfig = Bitmap.Config.RGB_565;
Point displaySize = Compatibility.getDisplaySize();
this.maxWidth = displaySize.x - 25;
@@ -194,7 +196,11 @@ public class HtmlImage implements Html.ImageGetter {
if (file.exists()) {
if (listId >= StoredList.STANDARD_LIST_ID || file.lastModified() > (new Date().getTime() - (24 * 60 * 60 * 1000)) || forceKeep) {
setSampleSize(file);
- return BitmapFactory.decodeFile(file.getPath(), bfOptions);
+ final Bitmap image = BitmapFactory.decodeFile(file.getPath(), bfOptions);
+ if (image == null) {
+ Log.e("Cannot decode bitmap from " + file.getPath());
+ }
+ return image;
}
}
return null;
@@ -205,20 +211,14 @@ public class HtmlImage implements Html.ImageGetter {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
- FileInputStream fis = null;
+ BufferedInputStream stream = null;
try {
- fis = new FileInputStream(file);
- BitmapFactory.decodeStream(fis, null, options);
+ stream = new BufferedInputStream(new FileInputStream(file));
+ BitmapFactory.decodeStream(stream, null, options);
} catch (FileNotFoundException e) {
Log.e("HtmlImage.setSampleSize", e);
} finally {
- if (fis != null) {
- try {
- fis.close();
- } catch (IOException e) {
- // ignore
- }
- }
+ IOUtils.closeQuietly(stream);
}
int scale = 1;
diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java
index eb6a6ac..5a8cbb2 100644
--- a/main/src/cgeo/geocaching/network/Network.java
+++ b/main/src/cgeo/geocaching/network/Network.java
@@ -40,6 +40,9 @@ import org.apache.commons.lang3.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
import android.net.Uri;
import java.io.File;
@@ -471,4 +474,19 @@ public abstract class Network {
return null;
}
+ /**
+ * Checks if the device has network connection.
+ *
+ * @param context
+ * context of the application, cannot be null
+ *
+ * @return <code>true</code> if the device is connected to the network.
+ */
+ public static boolean isNetworkConnected(Context context) {
+ ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo activeNetwork = conMan.getActiveNetworkInfo();
+
+ return activeNetwork != null && activeNetwork.isConnected();
+ }
+
}
diff --git a/main/src/cgeo/geocaching/network/OAuth.java b/main/src/cgeo/geocaching/network/OAuth.java
index 0b7a261..6740096 100644
--- a/main/src/cgeo/geocaching/network/OAuth.java
+++ b/main/src/cgeo/geocaching/network/OAuth.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.network;
-import cgeo.geocaching.Settings;
import cgeo.geocaching.utils.CryptUtils;
import ch.boye.httpclientandroidlib.NameValuePair;
+
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
@@ -11,9 +11,17 @@ import java.util.Date;
import java.util.List;
public class OAuth {
- public static void signOAuth(final String host, final String path, final String method, final boolean https, final Parameters params, final String token, final String tokenSecret) {
+ public static void signOAuth(final String host,
+ final String path,
+ final String method,
+ final boolean https,
+ final Parameters params,
+ final String token,
+ final String tokenSecret,
+ final String consumerKey,
+ final String consumerSecret) {
params.put(
- "oauth_consumer_key", Settings.getKeyConsumerPublic(),
+ "oauth_consumer_key", consumerKey,
"oauth_nonce", CryptUtils.md5(Long.toString(System.currentTimeMillis())),
"oauth_signature_method", "HMAC-SHA1",
"oauth_timestamp", Long.toString(new Date().getTime() / 1000),
@@ -26,7 +34,7 @@ public class OAuth {
paramsEncoded.add(nameValue.getName() + "=" + Network.rfc3986URLEncode(nameValue.getValue()));
}
- final String keysPacked = Settings.getKeyConsumerSecret() + "&" + StringUtils.defaultString(tokenSecret); // both even if empty some of them!
+ final String keysPacked = consumerSecret + "&" + StringUtils.defaultString(tokenSecret); // both even if empty some of them!
final String requestPacked = method + "&" + Network.rfc3986URLEncode((https ? "https" : "http") + "://" + host + path) + "&" + Network.rfc3986URLEncode(StringUtils.join(paramsEncoded.toArray(), '&'));
params.put("oauth_signature", CryptUtils.base64Encode(CryptUtils.hashHmac(requestPacked, keysPacked)));
}
diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
new file mode 100644
index 0000000..751443e
--- /dev/null
+++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java
@@ -0,0 +1,326 @@
+package cgeo.geocaching.network;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
+
+import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.util.regex.Pattern;
+
+public abstract class OAuthAuthorizationActivity extends AbstractActivity {
+
+ private String host;
+ private String pathRequest;
+ private String pathAuthorize;
+ private String pathAccess;
+ private boolean https;
+ private String consumerKey;
+ private String consumerSecret;
+ private String OAtoken = null;
+ private String OAtokenSecret = null;
+ private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([a-zA-Z0-9\\-\\_.]+)");
+ private final Pattern paramsPattern2 = Pattern.compile("oauth_token_secret=([a-zA-Z0-9\\-\\_.]+)");
+ private Button startButton = null;
+ private EditText pinEntry = null;
+ private Button pinEntryButton = null;
+ private ProgressDialog requestTokenDialog = null;
+ private ProgressDialog changeTokensDialog = null;
+ private Handler requestTokenHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (requestTokenDialog != null && requestTokenDialog.isShowing()) {
+ requestTokenDialog.dismiss();
+ }
+
+ startButton.setOnClickListener(new StartListener());
+ startButton.setEnabled(true);
+
+ if (msg.what == 1) {
+ startButton.setText(getAuthAgain());
+
+ pinEntry.setVisibility(View.VISIBLE);
+ pinEntryButton.setVisibility(View.VISIBLE);
+ pinEntryButton.setOnClickListener(new ConfirmPINListener());
+ } else {
+ showToast(getErrAuthInitialize());
+ startButton.setText(getAuthStart());
+ }
+ }
+
+ };
+ private Handler changeTokensHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (changeTokensDialog != null && changeTokensDialog.isShowing()) {
+ changeTokensDialog.dismiss();
+ }
+
+ pinEntryButton.setOnClickListener(new ConfirmPINListener());
+ pinEntryButton.setEnabled(true);
+
+ if (msg.what == 1) {
+ showToast(getAuthDialogCompleted());
+
+ pinEntryButton.setVisibility(View.GONE);
+
+ finish();
+ } else {
+ showToast(getErrAuthProcess());
+
+ pinEntry.setVisibility(View.GONE);
+ pinEntryButton.setVisibility(View.GONE);
+ startButton.setText(getAuthStart());
+ }
+ }
+ };
+
+ public OAuthAuthorizationActivity(String host,
+ String pathRequest,
+ String pathAuthorize,
+ String pathAccess,
+ boolean https,
+ String consumerKey,
+ String consumerSecret) {
+ this.host = host;
+ this.pathRequest = pathRequest;
+ this.pathAuthorize = pathAuthorize;
+ this.pathAccess = pathAccess;
+ this.https = https;
+ this.consumerKey = consumerKey;
+ this.consumerSecret = consumerSecret;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState, R.layout.authorization_activity);
+
+ setTitle(getAuthTitle());
+
+ init();
+ }
+
+ private void init() {
+ startButton = (Button) findViewById(R.id.start);
+ pinEntry = (EditText) findViewById(R.id.pin);
+ pinEntryButton = (Button) findViewById(R.id.pin_button);
+
+ TextView auth = (TextView) findViewById(R.id.auth_1);
+ auth.setText(getAboutAuth1());
+ auth = (TextView) findViewById(R.id.auth_2);
+ auth.setText(getAboutAuth2());
+
+ ImmutablePair<String, String> tempToken = getTempToken();
+ OAtoken = tempToken.left;
+ OAtokenSecret = tempToken.right;
+
+ startButton.setText(getAuthAuthorize());
+ pinEntryButton.setText(getAuthFinish());
+
+ startButton.setEnabled(true);
+ startButton.setOnClickListener(new StartListener());
+
+ if (StringUtils.isBlank(OAtoken) && StringUtils.isBlank(OAtokenSecret)) {
+ // start authorization process
+ startButton.setText(getAuthStart());
+ } else {
+ // already have temporary tokens, continue from pin
+ startButton.setText(getAuthAgain());
+
+ pinEntry.setHint(getAuthPinHint());
+ pinEntry.setVisibility(View.VISIBLE);
+ pinEntryButton.setVisibility(View.VISIBLE);
+ pinEntryButton.setOnClickListener(new ConfirmPINListener());
+ }
+ }
+
+ private void requestToken() {
+
+ int status = 0;
+ try {
+ final Parameters params = new Parameters();
+ params.put("oauth_callback", "oob");
+ final String method = "GET";
+ OAuth.signOAuth(host, pathRequest, method, https, params, null, null, consumerKey, consumerSecret);
+ final String line = Network.getResponseData(Network.getRequest(getUrlPrefix() + host + pathRequest, params));
+
+ if (StringUtils.isNotBlank(line)) {
+ final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line);
+ if (paramsMatcher1.find()) {
+ OAtoken = paramsMatcher1.group(1);
+ }
+ final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line);
+ if (paramsMatcher2.find()) {
+ OAtokenSecret = paramsMatcher2.group(1);
+ }
+
+ if (StringUtils.isNotBlank(OAtoken) && StringUtils.isNotBlank(OAtokenSecret)) {
+ setTempTokens(OAtoken, OAtokenSecret);
+ try {
+ final Parameters paramsBrowser = new Parameters();
+ paramsBrowser.put("oauth_token", OAtoken);
+ final String encodedParams = EntityUtils.toString(new UrlEncodedFormEntity(paramsBrowser));
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getUrlPrefix() + host + pathAuthorize + "?" + encodedParams)));
+ status = 1;
+ } catch (Exception e) {
+ Log.e("OAuthAuthorizationActivity.requestToken(2)", e);
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e("OAuthAuthorizationActivity.requestToken(1)", e);
+ }
+
+ requestTokenHandler.sendEmptyMessage(status);
+ }
+
+ private void changeToken() {
+
+ int status = 0;
+
+ try {
+ final Parameters params = new Parameters("oauth_verifier", pinEntry.getText().toString());
+
+ final String method = "POST";
+ OAuth.signOAuth(host, pathAccess, method, https, params, OAtoken, OAtokenSecret, consumerKey, consumerSecret);
+ final String line = StringUtils.defaultString(Network.getResponseData(Network.postRequest(getUrlPrefix() + host + pathAccess, params)));
+
+ OAtoken = "";
+ OAtokenSecret = "";
+
+ final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line);
+ if (paramsMatcher1.find()) {
+ OAtoken = paramsMatcher1.group(1);
+ }
+ final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line);
+ if (paramsMatcher2.find() && paramsMatcher2.groupCount() > 0) {
+ OAtokenSecret = paramsMatcher2.group(1);
+ }
+
+ if (StringUtils.isBlank(OAtoken) && StringUtils.isBlank(OAtokenSecret)) {
+ OAtoken = "";
+ OAtokenSecret = "";
+ setTokens(null, null, false);
+ } else {
+ setTokens(OAtoken, OAtokenSecret, true);
+ status = 1;
+ }
+ } catch (Exception e) {
+ Log.e("OAuthAuthorizationActivity.changeToken", e);
+ }
+
+ changeTokensHandler.sendEmptyMessage(status);
+ }
+
+ private String getUrlPrefix() {
+ return https ? "https://" : "http://";
+ }
+
+ private class StartListener implements View.OnClickListener {
+
+ @Override
+ public void onClick(View arg0) {
+ if (requestTokenDialog == null) {
+ requestTokenDialog = new ProgressDialog(OAuthAuthorizationActivity.this);
+ requestTokenDialog.setCancelable(false);
+ requestTokenDialog.setMessage(getAuthDialogWait());
+ }
+ requestTokenDialog.show();
+ startButton.setEnabled(false);
+ startButton.setOnTouchListener(null);
+ startButton.setOnClickListener(null);
+
+ setTempTokens(null, null);
+ (new Thread() {
+
+ @Override
+ public void run() {
+ requestToken();
+ }
+ }).start();
+ }
+ }
+
+ private class ConfirmPINListener implements View.OnClickListener {
+
+ @Override
+ public void onClick(View arg0) {
+ if (StringUtils.isEmpty(((EditText) findViewById(R.id.pin)).getText().toString())) {
+ helpDialog(getAuthDialogPinTitle(), getAuthDialogPinMessage());
+ return;
+ }
+
+ if (changeTokensDialog == null) {
+ changeTokensDialog = new ProgressDialog(OAuthAuthorizationActivity.this);
+ changeTokensDialog.setCancelable(false);
+ changeTokensDialog.setMessage(getAuthDialogWait());
+ }
+ changeTokensDialog.show();
+ pinEntryButton.setEnabled(false);
+ pinEntryButton.setOnTouchListener(null);
+ pinEntryButton.setOnClickListener(null);
+
+ (new Thread() {
+
+ @Override
+ public void run() {
+ changeToken();
+ }
+ }).start();
+ }
+ }
+
+ protected abstract ImmutablePair<String, String> getTempToken();
+
+ protected abstract void setTempTokens(String tokenPublic, String tokenSecret);
+
+ protected abstract void setTokens(String tokenPublic, String tokenSecret, boolean enable);
+
+ // get resources from derived class
+
+ protected abstract String getAuthTitle();
+
+ protected abstract String getAuthAgain();
+
+ protected abstract String getErrAuthInitialize();
+
+ protected abstract String getAuthStart();
+
+ protected abstract String getAuthDialogCompleted();
+
+ protected abstract String getErrAuthProcess();
+
+ protected abstract String getAuthDialogWait();
+
+ protected abstract String getAuthDialogPinTitle();
+
+ protected abstract String getAuthDialogPinMessage();
+
+ protected abstract String getAboutAuth1();
+
+ protected abstract String getAboutAuth2();
+
+ protected abstract String getAuthAuthorize();
+
+ protected abstract String getAuthPinHint();
+
+ protected abstract String getAuthFinish();
+}
diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java
index 1953e1d..bfc77ba 100644
--- a/main/src/cgeo/geocaching/network/StatusUpdater.java
+++ b/main/src/cgeo/geocaching/network/StatusUpdater.java
@@ -3,6 +3,7 @@ package cgeo.geocaching.network;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.MemorySubject;
import cgeo.geocaching.utils.PeriodicHandler;
+import cgeo.geocaching.utils.PeriodicHandler.PeriodicHandlerListener;
import cgeo.geocaching.utils.Version;
import org.json.JSONException;
@@ -12,7 +13,7 @@ import android.os.Looper;
import java.util.Locale;
-public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implements Runnable {
+public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implements Runnable, PeriodicHandlerListener {
static public class Status {
final public String message;
@@ -28,7 +29,8 @@ public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implement
}
}
- private void requestUpdate() {
+ @Override
+ public void onPeriodic() {
final JSONObject response =
Network.requestJSON("http://status.cgeo.org/api/status.json",
new Parameters("version_code", String.valueOf(Version.getVersionCode(cgeoapplication.getInstance())),
@@ -50,12 +52,7 @@ public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implement
@Override
public void run() {
Looper.prepare();
- new PeriodicHandler(1800000L) {
- @Override
- public void act() {
- requestUpdate();
- }
- }.start();
+ new PeriodicHandler(1800000L, this).start();
Looper.loop();
}
diff --git a/main/src/cgeo/geocaching/speech/SpeechService.java b/main/src/cgeo/geocaching/speech/SpeechService.java
new file mode 100644
index 0000000..7226014
--- /dev/null
+++ b/main/src/cgeo/geocaching/speech/SpeechService.java
@@ -0,0 +1,188 @@
+package cgeo.geocaching.speech;
+
+import cgeo.geocaching.DirectionProvider;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.utils.GeoDirHandler;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.Activity;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeech.OnInitListener;
+
+import java.util.Locale;
+
+/**
+ * Service to speak the compass directions.
+ *
+ */
+public class SpeechService extends Service implements OnInitListener {
+
+ private static final int SPEECH_MINPAUSE_SECONDS = 5;
+ private static final int SPEECH_MAXPAUSE_SECONDS = 30;
+ private static final String EXTRA_TARGET_COORDS = "target";
+ private static Activity startingActivity;
+ private static boolean isRunning = false;
+ /**
+ * Text to speech API of Android
+ */
+ private TextToSpeech tts;
+ /**
+ * TTS has been initialized and we can speak.
+ */
+ private boolean initialized = false;
+ protected float direction;
+ protected Geopoint position;
+ protected boolean directionInitialized;
+ protected boolean positionInitialized;
+
+ GeoDirHandler geoHandler = new GeoDirHandler() {
+ @Override
+ protected void updateDirection(float newDirection) {
+ direction = DirectionProvider.getDirectionNow(startingActivity, newDirection);
+ directionInitialized = true;
+ updateCompass();
+ }
+
+ @Override
+ protected void updateGeoData(cgeo.geocaching.IGeoData newGeo) {
+ position = newGeo.getCoords();
+ positionInitialized = true;
+ if (newGeo.getSpeed() > 5) {
+ direction = newGeo.getBearing();
+ directionInitialized = true;
+ }
+ updateCompass();
+ }
+ };
+ /**
+ * remember when we talked the last time
+ */
+ private long lastSpeechTime = 0;
+ private float lastSpeechDistance = 0.0f;
+ private Geopoint target;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ protected void updateCompass() {
+ // make sure we have both sensor values before talking
+ if (!positionInitialized || !directionInitialized) {
+ return;
+ }
+
+ // avoid any calculation, if the delay since the last output is not long enough
+ final long now = System.currentTimeMillis();
+ if (now - lastSpeechTime <= SPEECH_MINPAUSE_SECONDS * 1000) {
+ return;
+ }
+
+ // to speak, we want max pause to have elapsed or distance to geopoint to have changed by a given amount
+ final float distance = position.distanceTo(target);
+ if (now - lastSpeechTime <= SPEECH_MAXPAUSE_SECONDS * 1000) {
+ if (Math.abs(lastSpeechDistance - distance) < getDeltaForDistance(distance)) {
+ return;
+ }
+ }
+
+ final String text = TextFactory.getText(position, target, direction);
+ if (StringUtils.isNotEmpty(text)) {
+ lastSpeechTime = System.currentTimeMillis();
+ lastSpeechDistance = distance;
+ speak(text);
+ }
+ }
+
+ /**
+ * Return distance required to be moved based on overall distance.<br>
+ *
+ * @param distance
+ * in km
+ * @return delta in km
+ */
+ private static float getDeltaForDistance(final float distance) {
+ if (distance > 1.0) {
+ return 0.2f;
+ } else if (distance > 0.05) {
+ return distance / 5.0f;
+ }
+
+ return 0f;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ tts = new TextToSpeech(this, this);
+ }
+
+ @Override
+ public void onDestroy() {
+ geoHandler.stopGeoAndDir();
+ if (tts != null) {
+ tts.stop();
+ tts.shutdown();
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public void onInit(int status) {
+ // The text to speech system takes some time to initialize.
+ if (status != TextToSpeech.SUCCESS) {
+ Log.e("Text to speech cannot be initialized.");
+ return;
+ }
+
+ int switchLocale = tts.setLanguage(Locale.getDefault());
+
+ if (switchLocale == TextToSpeech.LANG_MISSING_DATA
+ || switchLocale == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("Current languge not supported by text to speech.");
+ return;
+ }
+
+ initialized = true;
+
+ geoHandler.startGeoAndDir();
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent != null) {
+ target = intent.getParcelableExtra(EXTRA_TARGET_COORDS);
+ }
+ return START_NOT_STICKY;
+ }
+
+ private void speak(final String text) {
+ if (!initialized) {
+ return;
+ }
+ tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
+ }
+
+ public static void startService(final Activity activity, Geopoint dstCoords) {
+ isRunning = true;
+ startingActivity = activity;
+ Intent talkingService = new Intent(activity, SpeechService.class);
+ talkingService.putExtra(EXTRA_TARGET_COORDS, dstCoords);
+ activity.startService(talkingService);
+ }
+
+ public static void stopService(final Activity activity) {
+ isRunning = false;
+ activity.stopService(new Intent(activity, SpeechService.class));
+ }
+
+ public static boolean isRunning() {
+ return isRunning;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/speech/TextFactory.java b/main/src/cgeo/geocaching/speech/TextFactory.java
new file mode 100644
index 0000000..0e13564
--- /dev/null
+++ b/main/src/cgeo/geocaching/speech/TextFactory.java
@@ -0,0 +1,71 @@
+package cgeo.geocaching.speech;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.IConversion;
+import cgeo.geocaching.utils.AngleUtils;
+
+import java.util.Locale;
+
+/**
+ * Creates the output to be read by TTS.
+ *
+ */
+public class TextFactory {
+ public static String getText(Geopoint position, Geopoint target, float direction) {
+ if (position == null || target == null) {
+ return null;
+ }
+ return getDirection(position, target, direction) + ". " + getDistance(position, target);
+ }
+
+ private static String getDistance(Geopoint position, Geopoint target) {
+ float kilometers = position.distanceTo(target);
+
+ if (Settings.isUseMetricUnits()) {
+ if (kilometers >= 5.0) {
+ return getString(R.string.tts_kilometers, String.valueOf(Math.round(kilometers)));
+ }
+ if (kilometers >= 1.0) {
+ String digits = String.format(Locale.getDefault(), "%.1f", kilometers);
+ return getString(R.string.tts_kilometers, digits);
+ }
+ int meters = (int) (kilometers * 1000.0);
+ if (meters > 50) {
+ return getString(R.string.tts_meters, String.valueOf(Math.round(meters / 10.0) * 10));
+ }
+ return getString(R.string.tts_meters, String.valueOf(meters));
+ }
+
+ float miles = kilometers / IConversion.MILES_TO_KILOMETER;
+ if (miles >= 3.0) {
+ return getString(R.string.tts_miles, String.valueOf(Math.round(miles)));
+ }
+ if (miles >= 0.2) { // approx 1000 ft
+ String digits = String.format(Locale.getDefault(), "%.1f", miles);
+ return getString(R.string.tts_miles, digits);
+ }
+ int feet = (int) (kilometers * 1000.0 * IConversion.METERS_TO_FEET);
+ if (feet > 300) {
+ return getString(R.string.tts_feet, String.valueOf(Math.round(feet / 10.0) * 10));
+ }
+ return getString(R.string.tts_feet, String.valueOf(feet));
+ }
+
+ private static String getString(int resourceId, Object... formatArgs) {
+ return cgeoapplication.getInstance().getString(resourceId, formatArgs);
+ }
+
+ private static String getDirection(Geopoint position, Geopoint target, float direction) {
+ final int bearing = (int) position.bearingTo(target);
+ int degrees = (int) AngleUtils.normalize(bearing - direction);
+
+ int hours = (degrees + 15) / 30;
+ if (hours == 0) {
+ hours = 12;
+ }
+ return getString(R.string.tts_oclock, String.valueOf(hours));
+ }
+}
diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java
index f30830e..525b7f0 100644
--- a/main/src/cgeo/geocaching/twitter/Twitter.java
+++ b/main/src/cgeo/geocaching/twitter/Twitter.java
@@ -15,7 +15,10 @@ import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
+import org.apache.commons.lang3.StringUtils;
+
public final class Twitter {
+ private static final String HASH_PREFIX_WITH_BLANK = " #";
public static final int MAX_TWEET_SIZE = 140;
public static void postTweet(final cgeoapplication app, final String status, final Geopoint coords) {
@@ -35,7 +38,7 @@ public final class Twitter {
"display_coordinates", "true");
}
- OAuth.signOAuth("api.twitter.com", "/1/statuses/update.json", "POST", false, parameters, Settings.getTokenPublic(), Settings.getTokenSecret());
+ OAuth.signOAuth("api.twitter.com", "/1/statuses/update.json", "POST", false, parameters, Settings.getTokenPublic(), Settings.getTokenSecret(), Settings.getKeyConsumerPublic(), Settings.getKeyConsumerSecret());
final HttpResponse httpResponse = Network.postRequest("http://api.twitter.com/1/statuses/update.json", parameters);
if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) {
Log.i("Tweet posted");
@@ -47,49 +50,56 @@ public final class Twitter {
}
}
- public static String appendHashTag(final String status, final String tag) {
- String result = status;
- if (result.length() + 2 + tag.length() <= 140) {
- result += " #" + tag;
+ public static void appendHashTag(final StringBuilder status, final String tag) {
+ if (status.length() + HASH_PREFIX_WITH_BLANK.length() + tag.length() <= MAX_TWEET_SIZE) {
+ final String tagWithPrefix = HASH_PREFIX_WITH_BLANK + tag;
+ if (status.indexOf(tagWithPrefix, 0) == -1) {
+ status.append(tagWithPrefix);
+ }
}
- return result;
}
public static void postTweetCache(String geocode) {
- final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
- String status;
- final String url = cache.getUrl();
- if (url.length() >= 100) {
- status = "I found " + url;
+ if (!Settings.isUseTwitter()) {
+ return;
}
- else {
- String name = cache.getName();
- status = "I found " + name + " (" + url + ")";
- if (status.length() > MAX_TWEET_SIZE) {
- name = name.substring(0, name.length() - (status.length() - MAX_TWEET_SIZE) - 1) + '…';
- }
- status = "I found " + name + " (" + url + ")";
- status = appendHashTag(status, "cgeo");
- status = appendHashTag(status, "geocaching");
+ if (!Settings.isTwitterLoginValid()) {
+ return;
}
+ final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ postTweet(cgeoapplication.getInstance(), getStatusMessage(cache), null);
+ }
+
+ static String getStatusMessage(Geocache cache) {
+ String name = cache.getName();
+ if (name.length() > 100) {
+ name = name.substring(0, 100) + '…';
+ }
+ final String url = StringUtils.defaultString(cache.getUrl());
+ return fillTemplate(Settings.getCacheTwitterMessage(), name, url);
+ }
- postTweet(cgeoapplication.getInstance(), status, null);
+ private static String fillTemplate(String template, String name, final String url) {
+ String result = StringUtils.replace(template, "[NAME]", name);
+ result = StringUtils.replace(result, "[URL]", url);
+ StringBuilder builder = new StringBuilder(result);
+ appendHashTag(builder, "cgeo");
+ appendHashTag(builder, "geocaching");
+ return builder.toString();
}
public static void postTweetTrackable(String geocode) {
final Trackable trackable = cgData.loadTrackable(geocode);
+ postTweet(cgeoapplication.getInstance(), getStatusMessage(trackable), null);
+ }
+
+ static String getStatusMessage(Trackable trackable) {
String name = trackable.getName();
if (name.length() > 82) {
name = name.substring(0, 81) + '…';
}
- StringBuilder builder = new StringBuilder("I touched ");
- builder.append(name);
- if (trackable.getUrl() != null) {
- builder.append(" (").append(trackable.getUrl()).append(')');
- }
- builder.append('!');
- String status = appendHashTag(builder.toString(), "cgeo");
- status = appendHashTag(status, "geocaching");
- postTweet(cgeoapplication.getInstance(), status, null);
+ String url = StringUtils.defaultString(trackable.getUrl());
+ String status = Settings.getTrackableTwitterMessage();
+ return fillTemplate(status, name, url);
}
}
diff --git a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
index 3d9f283..7146a62 100644
--- a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
@@ -2,268 +2,105 @@ package cgeo.geocaching.twitter;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.activity.AbstractActivity;
-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 cgeo.geocaching.network.OAuthAuthorizationActivity;
-import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
-import ch.boye.httpclientandroidlib.util.EntityUtils;
-
-import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
-import android.app.ProgressDialog;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
-
-import java.util.regex.Pattern;
-
-public class TwitterAuthorizationActivity extends AbstractActivity {
- private String OAtoken = null;
- private String OAtokenSecret = null;
- private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([a-zA-Z0-9\\-\\_.]+)");
- private final Pattern paramsPattern2 = Pattern.compile("oauth_token_secret=([a-zA-Z0-9\\-\\_.]+)");
- private Button startButton = null;
- private EditText pinEntry = null;
- private Button pinEntryButton = null;
- private ProgressDialog requestTokenDialog = null;
- private ProgressDialog changeTokensDialog = null;
- private Handler requestTokenHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- if (requestTokenDialog != null && requestTokenDialog.isShowing()) {
- requestTokenDialog.dismiss();
- }
-
- startButton.setOnClickListener(new StartListener());
- startButton.setEnabled(true);
-
- if (msg.what == 1) {
- startButton.setText(res.getString(R.string.auth_again));
-
- pinEntry.setVisibility(View.VISIBLE);
- pinEntryButton.setVisibility(View.VISIBLE);
- pinEntryButton.setOnClickListener(new ConfirmPINListener());
- } else {
- showToast(res.getString(R.string.err_auth_initialize));
- startButton.setText(res.getString(R.string.auth_start));
- }
- }
- };
- private Handler changeTokensHandler = new Handler() {
+public class TwitterAuthorizationActivity extends OAuthAuthorizationActivity {
- @Override
- public void handleMessage(Message msg) {
- if (changeTokensDialog != null && changeTokensDialog.isShowing()) {
- changeTokensDialog.dismiss();
- }
-
- pinEntryButton.setOnClickListener(new ConfirmPINListener());
- pinEntryButton.setEnabled(true);
-
- if (msg.what == 1) {
- showToast(res.getString(R.string.auth_dialog_completed));
-
- pinEntryButton.setVisibility(View.GONE);
-
- finish();
- } else {
- showToast(res.getString(R.string.err_auth_process));
-
- pinEntry.setVisibility(View.GONE);
- pinEntryButton.setVisibility(View.GONE);
- startButton.setText(res.getString(R.string.auth_start));
- }
- }
- };
+ public TwitterAuthorizationActivity() {
+ super("api.twitter.com",
+ "/oauth/request_token",
+ "/oauth/authorize",
+ "/oauth/access_token",
+ true,
+ Settings.getKeyConsumerPublic(),
+ Settings.getKeyConsumerSecret());
+ }
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.twitter_authorization_activity);
- setTitle(res.getString(R.string.auth_twitter));
-
- init();
+ protected ImmutablePair<String, String> getTempToken() {
+ return Settings.getTempToken();
}
@Override
- public void onResume() {
- super.onResume();
-
+ protected void setTempTokens(String tokenPublic, String tokenSecret) {
+ Settings.setTwitterTempTokens(tokenPublic, tokenSecret);
}
- private void init() {
- startButton = (Button) findViewById(R.id.start);
- pinEntry = (EditText) findViewById(R.id.pin);
- pinEntryButton = (Button) findViewById(R.id.pin_button);
-
- ImmutablePair<String, String> tempToken = Settings.getTempToken();
- OAtoken = tempToken.left;
- OAtokenSecret = tempToken.right;
-
- startButton.setEnabled(true);
- startButton.setOnClickListener(new StartListener());
-
- if (StringUtils.isBlank(OAtoken) && StringUtils.isBlank(OAtokenSecret)) {
- // start authorization process
- startButton.setText(res.getString(R.string.auth_start));
- } else {
- // already have temporary tokens, continue from pin
- startButton.setText(res.getString(R.string.auth_again));
-
- pinEntry.setVisibility(View.VISIBLE);
- pinEntryButton.setVisibility(View.VISIBLE);
- pinEntryButton.setOnClickListener(new ConfirmPINListener());
- }
+ @Override
+ protected void setTokens(String tokenPublic, String tokenSecret, boolean enable) {
+ Settings.setTwitterTokens(tokenPublic, tokenSecret, enable);
}
- private void requestToken() {
-
- 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 MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line);
- if (paramsMatcher1.find()) {
- OAtoken = paramsMatcher1.group(1);
- }
- final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line);
- if (paramsMatcher2.find()) {
- OAtokenSecret = paramsMatcher2.group(1);
- }
-
- if (StringUtils.isNotBlank(OAtoken) && StringUtils.isNotBlank(OAtokenSecret)) {
- Settings.setTwitterTempTokens(OAtoken, OAtokenSecret);
- 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);
- }
- }
- }
- } catch (Exception e) {
- Log.e("TwitterAuthorizationActivity.requestToken(1)", e);
- }
-
- requestTokenHandler.sendEmptyMessage(status);
+ @Override
+ protected String getAuthTitle() {
+ return res.getString(R.string.auth_twitter);
}
- private void changeToken() {
-
- 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 = "";
+ @Override
+ protected String getAuthAgain() {
+ return res.getString(R.string.auth_again);
+ }
- final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line);
- if (paramsMatcher1.find()) {
- OAtoken = paramsMatcher1.group(1);
- }
- final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line);
- if (paramsMatcher2.find() && paramsMatcher2.groupCount() > 0) {
- OAtokenSecret = paramsMatcher2.group(1);
- }
+ @Override
+ protected String getErrAuthInitialize() {
+ return res.getString(R.string.err_auth_initialize);
+ }
- if (StringUtils.isBlank(OAtoken) && StringUtils.isBlank(OAtokenSecret)) {
- OAtoken = "";
- OAtokenSecret = "";
- Settings.setTwitterTokens(null, null, false);
- } else {
- Settings.setTwitterTokens(OAtoken, OAtokenSecret, true);
- status = 1;
- }
- } catch (Exception e) {
- Log.e("TwitterAuthorizationActivity.changeToken", e);
- }
+ @Override
+ protected String getAuthStart() {
+ return res.getString(R.string.auth_start);
+ }
- changeTokensHandler.sendEmptyMessage(status);
+ @Override
+ protected String getAuthDialogCompleted() {
+ return res.getString(R.string.auth_dialog_completed);
}
- private class StartListener implements View.OnClickListener {
+ @Override
+ protected String getErrAuthProcess() {
+ return res.getString(R.string.err_auth_process);
+ }
- @Override
- public void onClick(View arg0) {
- if (requestTokenDialog == null) {
- requestTokenDialog = new ProgressDialog(TwitterAuthorizationActivity.this);
- requestTokenDialog.setCancelable(false);
- requestTokenDialog.setMessage(res.getString(R.string.auth_dialog_wait));
- }
- requestTokenDialog.show();
- startButton.setEnabled(false);
- startButton.setOnTouchListener(null);
- startButton.setOnClickListener(null);
+ @Override
+ protected String getAuthDialogWait() {
+ return res.getString(R.string.auth_dialog_wait);
+ }
- Settings.setTwitterTempTokens(null, null);
- (new Thread() {
+ @Override
+ protected String getAuthDialogPinTitle() {
+ return res.getString(R.string.auth_dialog_pin_title);
+ }
- @Override
- public void run() {
- requestToken();
- }
- }).start();
- }
+ @Override
+ protected String getAuthDialogPinMessage() {
+ return res.getString(R.string.auth_dialog_pin_message);
}
- private class ConfirmPINListener implements View.OnClickListener {
+ @Override
+ protected String getAboutAuth1() {
+ return res.getString(R.string.about_auth_1);
+ }
- @Override
- public void onClick(View arg0) {
- 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;
- }
+ @Override
+ protected String getAboutAuth2() {
+ return res.getString(R.string.about_auth_2);
+ }
- if (changeTokensDialog == null) {
- changeTokensDialog = new ProgressDialog(TwitterAuthorizationActivity.this);
- changeTokensDialog.setCancelable(false);
- changeTokensDialog.setMessage(res.getString(R.string.auth_dialog_wait));
- }
- changeTokensDialog.show();
- pinEntryButton.setEnabled(false);
- pinEntryButton.setOnTouchListener(null);
- pinEntryButton.setOnClickListener(null);
+ @Override
+ protected String getAuthAuthorize() {
+ return res.getString(R.string.auth_authorize);
+ }
- (new Thread() {
+ @Override
+ protected String getAuthPinHint() {
+ return res.getString(R.string.auth_pin_hint);
+ }
- @Override
- public void run() {
- changeToken();
- }
- }).start();
- }
+ @Override
+ protected String getAuthFinish() {
+ return res.getString(R.string.auth_finish);
}
+
}
diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
index e98bd77..80f01e2 100644
--- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
+++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
@@ -2,6 +2,7 @@ package cgeo.geocaching.ui;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
@@ -154,4 +155,24 @@ public final class CacheDetailsCreator {
}
add(R.string.cache_distance, text);
}
+
+ public void addDistance(final Waypoint wpt, final TextView waypointDistanceView) {
+ Float distance = null;
+ if (wpt.getCoords() != null) {
+ final Geopoint currentCoords = cgeoapplication.getInstance().currentGeo().getCoords();
+ if (currentCoords != null) {
+ distance = currentCoords.distanceTo(wpt);
+ }
+ }
+ String text = "--";
+ if (distance != null) {
+ text = Units.getDistanceFromKilometers(distance);
+ }
+ else if (waypointDistanceView != null) {
+ // if there is already a distance in waypointDistance, use it instead of resetting to default.
+ // this prevents displaying "--" while waiting for a new position update (See bug #1468)
+ text = waypointDistanceView.getText().toString();
+ }
+ add(R.string.cache_distance, text);
+ }
}
diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
index 42b774e..c27c387 100644
--- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
@@ -1,5 +1,8 @@
package cgeo.geocaching.ui;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.geocaching.CacheDetailActivity;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
@@ -77,13 +80,13 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
private static final int[] RATING_BACKGROUND = new int[3];
static {
if (Settings.isLightSkin()) {
- RATING_BACKGROUND[0] = R.drawable.favourite_background_red_light;
- RATING_BACKGROUND[1] = R.drawable.favourite_background_orange_light;
- RATING_BACKGROUND[2] = R.drawable.favourite_background_green_light;
+ RATING_BACKGROUND[0] = R.drawable.favorite_background_red_light;
+ RATING_BACKGROUND[1] = R.drawable.favorite_background_orange_light;
+ RATING_BACKGROUND[2] = R.drawable.favorite_background_green_light;
} else {
- RATING_BACKGROUND[0] = R.drawable.favourite_background_red_dark;
- RATING_BACKGROUND[1] = R.drawable.favourite_background_orange_dark;
- RATING_BACKGROUND[2] = R.drawable.favourite_background_green_dark;
+ RATING_BACKGROUND[0] = R.drawable.favorite_background_red_dark;
+ RATING_BACKGROUND[1] = R.drawable.favorite_background_orange_dark;
+ RATING_BACKGROUND[2] = R.drawable.favorite_background_green_dark;
}
}
@@ -91,16 +94,21 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
* view holder for the cache list adapter
*
*/
- private static class ViewHolder {
- CheckBox checkbox;
- ImageView logStatusMark;
- TextView text;
- TextView favourite;
- TextView info;
- ImageView inventory;
- DistanceView distance;
- CompassMiniView direction;
- ImageView dirImg;
+ protected static class ViewHolder {
+ @InjectView(R.id.checkbox) protected CheckBox checkbox;
+ @InjectView(R.id.log_status_mark) protected ImageView logStatusMark;
+ @InjectView(R.id.text) protected TextView text;
+ @InjectView(R.id.distance) protected DistanceView distance;
+ @InjectView(R.id.favorite) protected TextView favorite;
+ @InjectView(R.id.info) protected TextView info;
+ @InjectView(R.id.inventory) protected ImageView inventory;
+ @InjectView(R.id.direction) protected CompassMiniView direction;
+ @InjectView(R.id.dirimg) protected ImageView dirImg;
+
+ public ViewHolder(View view) {
+ Views.inject(this, view);
+ view.setTag(this);
+ }
}
public CacheListAdapter(final Activity activity, final List<Geocache> list, CacheListType cacheListType) {
@@ -350,18 +358,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
if (v == null) {
v = inflater.inflate(R.layout.caches_item, null);
- holder = new ViewHolder();
- holder.checkbox = (CheckBox) v.findViewById(R.id.checkbox);
- holder.logStatusMark = (ImageView) v.findViewById(R.id.log_status_mark);
- holder.text = (TextView) v.findViewById(R.id.text);
- holder.distance = (DistanceView) v.findViewById(R.id.distance);
- holder.direction = (CompassMiniView) v.findViewById(R.id.direction);
- holder.dirImg = (ImageView) v.findViewById(R.id.dirimg);
- holder.inventory = (ImageView) v.findViewById(R.id.inventory);
- holder.favourite = (TextView) v.findViewById(R.id.favourite);
- holder.info = (TextView) v.findViewById(R.id.info);
-
- v.setTag(holder);
+ holder = new ViewHolder(v);
} else {
holder = (ViewHolder) v.getTag();
}
@@ -453,14 +450,14 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
holder.direction.setVisibility(View.GONE);
}
- holder.favourite.setText(Integer.toString(cache.getFavoritePoints()));
+ holder.favorite.setText(Integer.toString(cache.getFavoritePoints()));
int favoriteBack;
// set default background, neither vote nor rating may be available
if (lightSkin) {
- favoriteBack = R.drawable.favourite_background_light;
+ favoriteBack = R.drawable.favorite_background_light;
} else {
- favoriteBack = R.drawable.favourite_background_dark;
+ favoriteBack = R.drawable.favorite_background_dark;
}
final float myVote = cache.getMyVote();
if (myVote > 0) { // use my own rating for display, if I have voted
@@ -481,7 +478,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> {
favoriteBack = RATING_BACKGROUND[0];
}
}
- holder.favourite.setBackgroundResource(favoriteBack);
+ holder.favorite.setBackgroundResource(favoriteBack);
if (cacheListType == CacheListType.HISTORY && cache.getVisitedDate() > 0) {
holder.info.setText(Formatter.formatCacheInfoHistory(cache));
diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java
index 0ef3a43..c926057 100644
--- a/main/src/cgeo/geocaching/ui/CompassView.java
+++ b/main/src/cgeo/geocaching/ui/CompassView.java
@@ -3,6 +3,7 @@ package cgeo.geocaching.ui;
import cgeo.geocaching.R;
import cgeo.geocaching.utils.AngleUtils;
import cgeo.geocaching.utils.PeriodicHandler;
+import cgeo.geocaching.utils.PeriodicHandler.PeriodicHandlerListener;
import android.content.Context;
import android.graphics.Bitmap;
@@ -14,7 +15,7 @@ import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.View;
-public class CompassView extends View {
+public class CompassView extends View implements PeriodicHandlerListener {
private Context context = null;
private Bitmap compassUnderlay = null;
@@ -48,7 +49,7 @@ public class CompassView extends View {
private int compassOverlayWidth = 0;
private int compassOverlayHeight = 0;
private boolean initialDisplay;
- private final RedrawHandler redrawHandler = new RedrawHandler();
+ private final PeriodicHandler redrawHandler = new PeriodicHandler(40, this);
public CompassView(Context contextIn) {
super(contextIn);
@@ -145,26 +146,18 @@ public class CompassView extends View {
return AngleUtils.normalize(actual + offset);
}
- private class RedrawHandler extends PeriodicHandler {
-
- public RedrawHandler() {
- super(40);
- }
-
- @Override
- public void act() {
- final float newAzimuthShown = smoothUpdate(northMeasured, azimuthShown);
- final float newCacheHeadingShown = smoothUpdate(cacheHeadingMeasured, cacheHeadingShown);
- if (Math.abs(AngleUtils.difference(azimuthShown, newAzimuthShown)) >= 2 ||
- Math.abs(AngleUtils.difference(cacheHeadingShown, newCacheHeadingShown)) >= 2) {
- synchronized(CompassView.this) {
- azimuthShown = newAzimuthShown;
- cacheHeadingShown = newCacheHeadingShown;
- }
- invalidate();
+ @Override
+ public void onPeriodic() {
+ final float newAzimuthShown = smoothUpdate(northMeasured, azimuthShown);
+ final float newCacheHeadingShown = smoothUpdate(cacheHeadingMeasured, cacheHeadingShown);
+ if (Math.abs(AngleUtils.difference(azimuthShown, newAzimuthShown)) >= 2 ||
+ Math.abs(AngleUtils.difference(cacheHeadingShown, newCacheHeadingShown)) >= 2) {
+ synchronized(this) {
+ azimuthShown = newAzimuthShown;
+ cacheHeadingShown = newCacheHeadingShown;
}
+ invalidate();
}
-
}
@Override
diff --git a/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java b/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java
new file mode 100644
index 0000000..afadb33
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java
@@ -0,0 +1,38 @@
+package cgeo.geocaching.ui;
+
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.GeopointFormatter;
+
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+/**
+ * view click listener to automatically switch different coordinate formats
+ *
+ */
+public class CoordinatesFormatSwitcher implements OnClickListener {
+
+ private static GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] {
+ GeopointFormatter.Format.LAT_LON_DECMINUTE,
+ GeopointFormatter.Format.LAT_LON_DECSECOND,
+ GeopointFormatter.Format.LAT_LON_DECDEGREE
+ };
+
+ private int position = 0;
+
+ private final Geopoint coordinates;
+
+ public CoordinatesFormatSwitcher(final Geopoint coordinates) {
+ this.coordinates = coordinates;
+ }
+
+ @Override
+ public void onClick(View view) {
+ position = (position + 1) % availableFormats.length;
+ TextView textView = (TextView) view;
+ // rotate coordinate formats on click
+ textView.setText(coordinates.format(availableFormats[position]));
+ }
+
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java b/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java
index 4ba88ae..f10e13a 100644
--- a/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java
+++ b/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java
@@ -16,6 +16,12 @@ public class DecryptTextClickListener implements View.OnClickListener {
try {
final TextView logView = (TextView) view;
+
+ // do not run the click listener if a link was clicked
+ if (logView.getSelectionStart() != -1 || logView.getSelectionEnd() != -1) {
+ return;
+ }
+
CharSequence text = logView.getText();
if (text instanceof Spannable) {
Spannable span = (Spannable) text;
diff --git a/main/src/cgeo/geocaching/ui/EditNoteDialog.java b/main/src/cgeo/geocaching/ui/EditNoteDialog.java
new file mode 100644
index 0000000..bbf0618
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/EditNoteDialog.java
@@ -0,0 +1,70 @@
+package cgeo.geocaching.ui;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.R.string;
+
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager.LayoutParams;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+public class EditNoteDialog extends DialogFragment implements OnEditorActionListener {
+
+ public interface EditNoteDialogListener {
+ void onFinishEditNoteDialog(final String inputText);
+ }
+
+ public static final String ARGUMENT_INITIAL_NOTE = "initialNote";
+
+ private EditText mEditText;
+ private String initialNote;
+
+ public static EditNoteDialog newInstance(final String initialNote) {
+ EditNoteDialog dialog = new EditNoteDialog();
+
+ Bundle arguments = new Bundle();
+ arguments.putString(EditNoteDialog.ARGUMENT_INITIAL_NOTE, initialNote);
+ dialog.setArguments(arguments);
+
+ return dialog;
+ }
+
+ @Override
+ public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+ final Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_edit_note, container);
+ mEditText = (EditText) view.findViewById(R.id.note);
+ initialNote = getArguments().getString(ARGUMENT_INITIAL_NOTE);
+ if (initialNote != null) {
+ mEditText.setText(initialNote);
+ initialNote = null;
+ }
+ getDialog().setTitle(string.cache_personal_note);
+ mEditText.requestFocus();
+ getDialog().getWindow().setSoftInputMode(
+ LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ mEditText.setOnEditorActionListener(this);
+
+ return view;
+ }
+
+ @Override
+ public boolean onEditorAction(final TextView v, final int actionId, final KeyEvent event) {
+ if (EditorInfo.IME_ACTION_DONE == actionId) {
+ final EditNoteDialogListener activity = (EditNoteDialogListener) getActivity();
+ activity.onFinishEditNoteDialog(mEditText.getText().toString());
+ dismiss();
+ return true;
+ }
+ return false;
+ }
+
+
+}
diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java
index 9464114..a0ffe84 100644
--- a/main/src/cgeo/geocaching/ui/ImagesList.java
+++ b/main/src/cgeo/geocaching/ui/ImagesList.java
@@ -11,7 +11,6 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
-import android.app.ProgressDialog;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -31,6 +30,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Collection;
@@ -39,23 +39,18 @@ import java.util.List;
public class ImagesList {
- private static final int MENU_FILE = 201;
- private static final int MENU_BROWSER = 202;
-
private BitmapDrawable currentDrawable;
private Image currentImage;
public enum ImageType {
- LogImages(R.string.cache_log_images_title, R.string.cache_log_images_loading),
- SpoilerImages(R.string.cache_spoiler_images_title, R.string.cache_spoiler_images_loading),
- AllImages(R.string.cache_images_title, R.string.cache_images_loading);
+ LogImages(R.string.cache_log_images_title),
+ SpoilerImages(R.string.cache_spoiler_images_title),
+ AllImages(R.string.cache_images_title);
private final int titleResId;
- private final int loadingResId;
- ImageType(final int title, final int loading) {
+ ImageType(final int title) {
this.titleResId = title;
- this.loadingResId = loading;
}
public int getTitle() {
@@ -64,9 +59,6 @@ public class ImagesList {
}
private LayoutInflater inflater = null;
- private ProgressDialog progressDialog = null;
- private int count = 0;
- private int countDone = 0;
private final Activity activity;
// We could use a Set here, but we will insert no duplicates, so there is no need to check for uniqueness.
private final Collection<Bitmap> bitmaps = new LinkedList<Bitmap>();
@@ -83,18 +75,10 @@ public class ImagesList {
inflater = activity.getLayoutInflater();
}
- public void loadImages(final View parentView, final List<Image> images, ImageType imageType, final boolean offline) {
+ public void loadImages(final View parentView, final List<Image> images, final boolean offline) {
imagesView = (LinearLayout) parentView.findViewById(R.id.spoiler_list);
- count = images.size();
- progressDialog = new ProgressDialog(activity);
- progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- progressDialog.setMessage(activity.getString(imageType.loadingResId));
- progressDialog.setCancelable(true);
- progressDialog.setMax(count);
- progressDialog.show();
-
for (final Image img : images) {
LinearLayout rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, null);
@@ -154,19 +138,12 @@ public class ImagesList {
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new LayoutParams(bounds.width(), bounds.height()));
+ view.findViewById(R.id.progress_bar).setVisibility(View.GONE);
view.addView(imageView);
imageView.setId(image.hashCode());
images.put(imageView.getId(), img);
}
-
- synchronized (activity) {
- countDone++;
- progressDialog.setProgress(countDone);
- if (progressDialog.getProgress() >= count) {
- progressDialog.dismiss();
- }
- }
}
}
@@ -179,10 +156,9 @@ public class ImagesList {
}
public void onCreateContextMenu(ContextMenu menu, View v) {
+ activity.getMenuInflater().inflate(R.menu.images_list_context, menu);
final Resources res = activity.getResources();
menu.setHeaderTitle(res.getString(R.string.cache_image));
- menu.add(0, MENU_FILE, 0, res.getString(R.string.cache_image_open_file));
- menu.add(0, MENU_BROWSER, 0, res.getString(R.string.cache_image_open_browser));
final ImageView view = (ImageView) v;
currentDrawable = (BitmapDrawable) view.getDrawable();
currentImage = images.get(view.getId());
@@ -190,10 +166,10 @@ public class ImagesList {
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case MENU_FILE:
+ case R.id.image_open_file:
viewImageInStandardApp(currentDrawable);
return true;
- case MENU_BROWSER:
+ case R.id.image_open_browser:
if (currentImage != null) {
currentImage.openInBrowser(activity);
}
@@ -205,15 +181,15 @@ public class ImagesList {
private void viewImageInStandardApp(final BitmapDrawable image) {
final File file = LocalStorage.getStorageFile(null, "temp.jpg", false, true);
- FileOutputStream fos = null;
+ BufferedOutputStream stream = null;
try {
- fos = new FileOutputStream(file);
- image.getBitmap().compress(CompressFormat.JPEG, 100, fos);
+ stream = new BufferedOutputStream(new FileOutputStream(file));
+ image.getBitmap().compress(CompressFormat.JPEG, 100, stream);
} catch (Exception e) {
Log.e("ImagesActivity.handleMessage.onClick", e);
return;
} finally {
- IOUtils.closeQuietly(fos);
+ IOUtils.closeQuietly(stream);
}
final Intent intent = new Intent();
diff --git a/main/src/cgeo/geocaching/ui/LoggingUI.java b/main/src/cgeo/geocaching/ui/LoggingUI.java
index 2615947..1ba15a2 100644
--- a/main/src/cgeo/geocaching/ui/LoggingUI.java
+++ b/main/src/cgeo/geocaching/ui/LoggingUI.java
@@ -61,31 +61,12 @@ public class LoggingUI extends AbstractUIFactory {
}
}
- private static final int MENU_ICON_LOG_VISIT = R.drawable.ic_menu_edit;
- private static final int MENU_LOG_VISIT = 100;
- private static final int MENU_LOG_VISIT_OFFLINE = 101;
-
- public static void addMenuItems(final Menu menu, final Geocache cache) {
- if (cache == null) {
- return;
- }
- if (!cache.supportsLogging()) {
- return;
- }
- if (Settings.getLogOffline()) {
- menu.add(0, MENU_LOG_VISIT_OFFLINE, 0, res.getString(R.string.cache_menu_visit_offline)).setIcon(MENU_ICON_LOG_VISIT);
- }
- else {
- menu.add(0, MENU_LOG_VISIT, 0, res.getString(R.string.cache_menu_visit)).setIcon(MENU_ICON_LOG_VISIT);
- }
- }
-
public static boolean onMenuItemSelected(final MenuItem item, IAbstractActivity activity, Geocache cache) {
switch (item.getItemId()) {
- case MENU_LOG_VISIT:
+ case R.id.menu_log_visit:
cache.logVisit(activity);
return true;
- case MENU_LOG_VISIT_OFFLINE:
+ case R.id.menu_log_visit_offline:
showOfflineMenu(cache, (Activity) activity);
return true;
default:
@@ -136,10 +117,17 @@ public class LoggingUI extends AbstractUIFactory {
}
- public static void onPrepareOptionsMenu(Menu menu) {
- final MenuItem item = menu.findItem(MENU_LOG_VISIT);
- if (item != null) {
- item.setEnabled(Settings.isLogin());
- }
+ public static void onPrepareOptionsMenu(Menu menu, Geocache cache) {
+ final MenuItem itemLog = menu.findItem(R.id.menu_log_visit);
+ itemLog.setVisible(cache.supportsLogging() && !Settings.getLogOffline());
+ itemLog.setEnabled(Settings.isLogin());
+
+ final MenuItem itemOffline = menu.findItem(R.id.menu_log_visit_offline);
+ itemOffline.setVisible(cache.supportsLogging() && Settings.getLogOffline());
+ }
+
+ public static void addMenuItems(Activity activity, Menu menu, Geocache cache) {
+ activity.getMenuInflater().inflate(R.menu.logging_ui, menu);
+ onPrepareOptionsMenu(menu, cache);
}
}
diff --git a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
index dada8fd..3d93a56 100644
--- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
@@ -74,14 +74,6 @@ public class CoordinatesInputDialog extends Dialog {
setContentView(R.layout.coords);
- findViewById(R.id.actionBarManualbutton).setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View view) {
- ActivityMixin.goManual(context, "c:geo-geocoordinate-input");
- }
- });
-
final Spinner spinner = (Spinner) findViewById(R.id.spinnerCoordinateFormats);
final ArrayAdapter<CharSequence> adapter =
ArrayAdapter.createFromResource(context,
diff --git a/main/src/cgeo/geocaching/ui/dialog/EditorDialog.java b/main/src/cgeo/geocaching/ui/dialog/EditorDialog.java
deleted file mode 100644
index 4db69e5..0000000
--- a/main/src/cgeo/geocaching/ui/dialog/EditorDialog.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package cgeo.geocaching.ui.dialog;
-
-import cgeo.geocaching.CacheDetailActivity;
-import cgeo.geocaching.R;
-import cgeo.geocaching.activity.ActivityMixin;
-
-import android.app.Dialog;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.Window;
-import android.widget.Button;
-import android.widget.EditText;
-
-public class EditorDialog extends Dialog {
-
- private CharSequence editorText;
- private EditorUpdate editorUpdate;
-
- public EditorDialog(CacheDetailActivity cacheDetailActivity, CharSequence editable) {
- super(cacheDetailActivity, ActivityMixin.getTheme());
- this.editorText = editable;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.editor);
-
- final EditText editText = (EditText) findViewById(R.id.editorEditText);
- editText.setText(editorText);
-
- final Button buttonSave = (Button) findViewById(R.id.editorSave);
- buttonSave.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- editorUpdate.update(editText.getEditableText());
- EditorDialog.this.hide();
- }
- });
- }
-
- public interface EditorUpdate {
- public void update(CharSequence editorText);
- }
-
- public void setOnEditorUpdate(EditorUpdate editorUpdate) {
- this.editorUpdate = editorUpdate;
-
- }
-
- @Override
- public void show() {
- super.show();
- getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
- }
-
-}
diff --git a/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java
new file mode 100644
index 0000000..7526d92
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java
@@ -0,0 +1,139 @@
+package cgeo.geocaching.utils;
+
+import cgeo.geocaching.activity.Progress;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.os.AsyncTask;
+
+/**
+ * AsyncTask which automatically shows a progress dialog. Use it like the {@code AsyncTask} class, but leave away the
+ * middle template parameter. Override {@link #doInBackgroundInternal(Object[])} and related methods.
+ * <p>
+ * If no style is given, the progress dialog uses "determinate" style with known maximum. The progress maximum is
+ * automatically derived from the number of {@code Params} given to the task in {@link #execute(Object...)}.
+ * </p>
+ *
+ * @param <Params>
+ * @param <Result>
+ */
+public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Params, Integer, Result> {
+
+ private final Progress progress = new Progress();
+ private final Activity activity;
+ private final String progressTitle;
+ private final String progressMessage;
+ private boolean indeterminate = false;
+
+ /**
+ * Creates an AsyncTask with progress dialog.
+ *
+ * @param activity
+ * @param progressTitle
+ * @param progressMessage
+ */
+ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final String progressMessage) {
+ this(activity, progressTitle, progressMessage, false);
+ }
+
+ /**
+ * Creates an AsyncTask with progress dialog.
+ *
+ * @param activity
+ * @param progressTitle
+ */
+ public AsyncTaskWithProgress(final Activity activity, final String progressTitle) {
+ this(activity, progressTitle, null);
+ }
+
+ /**
+ * Creates an AsyncTask with progress dialog.
+ *
+ * @param activity
+ * @param progressTitle
+ * @param progressMessage
+ */
+ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final String progressMessage, boolean indeterminate) {
+ this.activity = activity;
+ this.progressTitle = progressTitle;
+ this.progressMessage = progressMessage;
+ this.indeterminate = indeterminate;
+ }
+
+ /**
+ * Creates an AsyncTask with progress dialog.
+ *
+ * @param activity
+ * @param progressTitle
+ */
+ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, boolean indeterminate) {
+ this(activity, progressTitle, null, indeterminate);
+ }
+
+ @Override
+ protected final void onPreExecute() {
+ if (null != activity) {
+ if (indeterminate) {
+ progress.show(activity, progressTitle, progressMessage, true, null);
+ }
+ else {
+ progress.show(activity, progressTitle, progressMessage, ProgressDialog.STYLE_HORIZONTAL, null);
+ }
+ }
+ onPreExecuteInternal();
+ }
+
+ /**
+ * This method should typically be overridden by sub classes instead of {@link #onPreExecute()}.
+ */
+ protected void onPreExecuteInternal() {
+ // empty by default
+ }
+
+ @Override
+ protected final void onPostExecute(Result result) {
+ onPostExecuteInternal(result);
+ if (null != activity) {
+ progress.dismiss();
+ }
+ }
+
+ /**
+ * This method should typically be overridden by sub classes instead of {@link #onPostExecute(Object)}.
+ *
+ * @param result
+ */
+ protected void onPostExecuteInternal(Result result) {
+ // empty by default
+ }
+
+ @Override
+ protected final void onProgressUpdate(Integer... status) {
+ final int progressValue = status[0];
+ if (null != activity && progressValue >= 0) {
+ progress.setProgress(progressValue);
+ }
+ onProgressUpdateInternal(progressValue);
+ }
+
+ /**
+ * This method should by overridden by sub classes instead of {@link #onProgressUpdate(Integer...)}.
+ */
+ protected void onProgressUpdateInternal(@SuppressWarnings("unused") int progress) {
+ // empty by default
+ }
+
+ protected void setMessage(final String message) {
+ progress.setMessage(message);
+ }
+
+ @Override
+ protected final Result doInBackground(Params... params) {
+ if (params != null) {
+ progress.setMaxProgressAndReset(params.length);
+ }
+ return doInBackgroundInternal(params);
+ }
+
+ protected abstract Result doInBackgroundInternal(Params[] params);
+}
diff --git a/main/src/cgeo/geocaching/utils/BaseUtils.java b/main/src/cgeo/geocaching/utils/BaseUtils.java
index 82e48cb..b8006ad 100644
--- a/main/src/cgeo/geocaching/utils/BaseUtils.java
+++ b/main/src/cgeo/geocaching/utils/BaseUtils.java
@@ -137,10 +137,11 @@ public final class BaseUtils {
}
/**
- * Quick and naive check for possible html-content of a string.
+ * Quick and naive check for possible rich HTML content in a string.
*
- * @param str
- * @return True, if <code>str</code> could contain html
+ * @param str A string containing HTML code.
+ * @return <tt>true</tt> if <tt>str</tt> contains HTML code that needs to go through a HTML renderer before
+ * being displayed, <tt>false</tt> if it can be displayed as-is without any loss
*/
public static boolean containsHtml(final String str) {
return str.indexOf('<') != -1 || str.indexOf('&') != -1;
diff --git a/main/src/cgeo/geocaching/utils/ClipboardUtils.java b/main/src/cgeo/geocaching/utils/ClipboardUtils.java
index e6779ad..9343576 100644
--- a/main/src/cgeo/geocaching/utils/ClipboardUtils.java
+++ b/main/src/cgeo/geocaching/utils/ClipboardUtils.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.utils;
import cgeo.geocaching.cgeoapplication;
import android.content.Context;
-import android.text.ClipboardManager;
/**
* Clipboard Utilities. Functions to copy data to the Android clipboard.
@@ -20,7 +19,8 @@ public final class ClipboardUtils {
* The text to place in the clipboard.
*/
public static void copyToClipboard(final CharSequence text) {
- final ClipboardManager clipboard = (ClipboardManager) cgeoapplication.getInstance().getSystemService(Context.CLIPBOARD_SERVICE);
+ // fully qualified name used here to avoid buggy deprecation warning (of javac) on the import statement
+ final android.text.ClipboardManager clipboard = (android.text.ClipboardManager) cgeoapplication.getInstance().getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}
diff --git a/main/src/cgeo/geocaching/utils/GeoDirHandler.java b/main/src/cgeo/geocaching/utils/GeoDirHandler.java
index 21b2562..78455c4 100644
--- a/main/src/cgeo/geocaching/utils/GeoDirHandler.java
+++ b/main/src/cgeo/geocaching/utils/GeoDirHandler.java
@@ -9,10 +9,19 @@ import android.os.Message;
/**
* GeoData and Direction handler. Manipulating geodata and direction information
- * through a GeoDirHandler ensures that all listeners are registered from a
- * {@link android.os.Looper} thread.
+ * through a GeoDirHandler ensures that all listeners are registered from a {@link android.os.Looper} thread.
+ * <p>
+ * To use this class, override at least one of {@link #updateDirection(float)} or {@link #updateGeoData(IGeoData)}. You
+ * need to start the handler using one of
+ * <ul>
+ * <li>{@link #startDir()}</li>
+ * <li>{@link #startGeo()}</li>
+ * <li>{@link #startGeoAndDir()}</li>
+ * </ul>
+ * A good place might be the {@code onResume} method of the Activity. Stop the Handler accordingly in {@code onPause}.
+ * </p>
*/
-public class GeoDirHandler extends Handler implements IObserver<Object> {
+public abstract class GeoDirHandler extends Handler implements IObserver<Object> {
private static final int OBSERVABLE = 1 << 1;
private static final int START_GEO = 1 << 2;
@@ -57,7 +66,8 @@ public class GeoDirHandler extends Handler implements IObserver<Object> {
/**
* Update method called when new IGeoData is available.
*
- * @param data the new data
+ * @param data
+ * the new data
*/
protected void updateGeoData(final IGeoData data) {
// Override this in children
@@ -66,7 +76,8 @@ public class GeoDirHandler extends Handler implements IObserver<Object> {
/**
* Update method called when new direction data is available.
*
- * @param direction the new direction
+ * @param direction
+ * the new direction
*/
protected void updateDirection(final float direction) {
// Override this in children
@@ -118,4 +129,3 @@ public class GeoDirHandler extends Handler implements IObserver<Object> {
sendEmptyMessage(STOP_GEO | STOP_DIR);
}
}
-
diff --git a/main/src/cgeo/geocaching/utils/ImageHelper.java b/main/src/cgeo/geocaching/utils/ImageHelper.java
index 98cad64..ec77018 100644
--- a/main/src/cgeo/geocaching/utils/ImageHelper.java
+++ b/main/src/cgeo/geocaching/utils/ImageHelper.java
@@ -8,6 +8,9 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+
public class ImageHelper {
// Do not let this class be instantiated, this is a utility class.
@@ -22,11 +25,21 @@ public class ImageHelper {
* @return BitmapDrawable The scaled image
*/
public static BitmapDrawable scaleBitmapToFitDisplay(final Bitmap image) {
- final cgeoapplication app = cgeoapplication.getInstance();
Point displaySize = Compatibility.getDisplaySize();
final int maxWidth = displaySize.x - 25;
final int maxHeight = displaySize.y - 25;
+ return scaleBitmapTo(image, maxWidth, maxHeight);
+ }
+ /**
+ * Scales a bitmap to the given bounds if it is larger, otherwise returns the original bitmap.
+ *
+ * @param image
+ * The bitmap to scale
+ * @return BitmapDrawable The scaled image
+ */
+ public static BitmapDrawable scaleBitmapTo(final Bitmap image, final int maxWidth, final int maxHeight) {
+ final cgeoapplication app = cgeoapplication.getInstance();
Bitmap result = image;
int width = image.getWidth();
int height = image.getHeight();
@@ -43,4 +56,27 @@ public class ImageHelper {
return resultDrawable;
}
+ /**
+ * Store a bitmap to file.
+ *
+ * @param bitmap
+ * The bitmap to store
+ * @param format
+ * The image format
+ * @param quality
+ * The image quality
+ * @param pathOfOutputImage
+ * Path to store to
+ */
+ public static void storeBitmap(final Bitmap bitmap, final Bitmap.CompressFormat format, final int quality, final String pathOfOutputImage) {
+ try {
+ FileOutputStream out = new FileOutputStream(pathOfOutputImage);
+ BufferedOutputStream bos = new BufferedOutputStream(out);
+ bitmap.compress(format, quality, bos);
+ bos.flush();
+ bos.close();
+ } catch (Exception e) {
+ Log.e("Image", e);
+ }
+ }
}
diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java
index 6d57b75..f912ddd 100644
--- a/main/src/cgeo/geocaching/utils/Log.java
+++ b/main/src/cgeo/geocaching/utils/Log.java
@@ -2,6 +2,7 @@ package cgeo.geocaching.utils;
import android.os.Environment;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@@ -100,12 +101,14 @@ final public class Log {
first = false;
file.delete();
}
+ Writer writer = null;
try {
- final Writer writer = new FileWriter(file, true);
+ writer = new BufferedWriter(new FileWriter(file, true));
writer.write(msg);
- writer.close();
} catch (final IOException e) {
Log.e("logToFile: cannot write to " + file, e);
+ } finally {
+ IOUtils.closeQuietly(writer);
}
}
}
diff --git a/main/src/cgeo/geocaching/utils/PeriodicHandler.java b/main/src/cgeo/geocaching/utils/PeriodicHandler.java
index 2759580..288bbb0 100644
--- a/main/src/cgeo/geocaching/utils/PeriodicHandler.java
+++ b/main/src/cgeo/geocaching/utils/PeriodicHandler.java
@@ -3,16 +3,26 @@ package cgeo.geocaching.utils;
import android.os.Handler;
import android.os.Message;
+import java.lang.ref.WeakReference;
+
/**
* A PeriodicHandler class helps with the implementation of a periodic
* action embedded in a thread with a looper such as the UI thread.
- * The act() method will be called periodically. The clock may drift
- * as the implementation does not target real-time actions.
+ * The onPeriodic() method of the listener will be called periodically.
+ * The clock may drift as the implementation does not target real-time
+ * actions.
*
* The handler will be interrupted if the device goes to sleep.
*
+ * The handler only keeps a weak reference to the listener. If the listener
+ * is garbage-collected without having stopped the timer, the handler will
+ * stop itself.
*/
-abstract public class PeriodicHandler extends Handler {
+final public class PeriodicHandler extends Handler {
+
+ public static interface PeriodicHandlerListener {
+ public void onPeriodic();
+ }
final static private int START = 0;
final static private int STOP = 1;
@@ -20,21 +30,19 @@ abstract public class PeriodicHandler extends Handler {
final private long period;
+ final private WeakReference<PeriodicHandlerListener> listenerRef;
+
/**
* Create a new PeriodicHandler object.
*
* @param period
* The period in milliseconds.
*/
- protected PeriodicHandler(final long period) {
+ public PeriodicHandler(final long period, final PeriodicHandlerListener listener) {
this.period = period;
+ listenerRef = new WeakReference<PeriodicHandlerListener>(listener);
}
- /**
- * Subclasses of PeriodicHandler must implement this method.
- */
- abstract public void act();
-
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
@@ -46,8 +54,11 @@ abstract public class PeriodicHandler extends Handler {
removeMessages(ACT);
break;
case ACT:
- sendEmptyMessageDelayed(ACT, period);
- act();
+ final PeriodicHandlerListener listener = listenerRef.get();
+ if (listener != null) {
+ sendEmptyMessageDelayed(ACT, period);
+ listener.onPeriodic();
+ }
break;
default:
throw new UnsupportedOperationException();
diff --git a/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java b/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java
deleted file mode 100644
index af4c03e..0000000
--- a/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java
+++ /dev/null
@@ -1,375 +0,0 @@
-package gnu.android.app.appmanualclient;
-
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.util.Log;
-
-import java.util.List;
-
-/**
- * The "App Manual Reader" client is a class to be used in applications which
- * want to offer their users manuals through the gnu.android.appmanualreader
- * application. Such applications do not need to include the whole
- * "App Manual Reader" app but instead just have to include only this little
- * package. This package then provides the mechanism to open suitable installed
- * manuals. It does not include any manuals itself.
- * <p>
- *
- * (c) 2011 Geocrasher (geocrasher@gmx.eu)
- * <p>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- * <p>
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- * <p>
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/.
- *
- * @author Geocrasher
- */
-public class AppManualReaderClient {
-
- /**
- * The URI scheme used to identify application manual URIs when flinging
- * Intents around within an Android device, in the hope that there are
- * activities registered which will handle such application manual URIs.
- * Usually, there won't be just a single activity registered but instead
- * many, depending on how many manuals are installed on an Android device.
- */
- public static final String URI_SCHEME_APPMANUAL = "appmanual";
-
- /**
- * Standardized topic for opening a manual at its beginning.
- *
- * @see #openManual(String, String, Context)
- * @see #openManual(String, String, Context, String)
- */
- public static final String TOPIC_HOME = "andtw-home";
- /**
- * Standardized topic for opening the index of a manual.
- *
- * @see #openManual(String, String, Context)
- * @see #openManual(String, String, Context, String)
- */
- public static final String TOPIC_INDEX = "andtw-index";
- /**
- * Standardized topic for opening a manual's "about" topic.
- *
- * @see #openManual(String, String, Context)
- * @see #openManual(String, String, Context, String)
- */
- public static final String TOPIC_ABOUT_MANUAL = "andtw-about";
-
- /**
- * Convenience function to open a manual at a specific topic. See
- * {@link #openManual(String, String, Context, String)} for a detailed
- * description.
- *
- * @param manualIdentifier
- * the identifier of the manual to open. This identifier must
- * uniquely identify the manual as such, independent of the
- * particular locale the manual is intended for.
- * @param topic
- * the topic to open. Please do not use spaces for topic names.
- * With respect to the TiddlyWiki infrastructure used for manuals
- * the topic needs to the tag of a (single) tiddler. This way
- * manuals can be localized (especially their topic titles)
- * without breaking an app's knowledge about topics. Some
- * standardized topics are predefined, such as {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and
- * {@link #TOPIC_ABOUT_MANUAL}.
- * @param context
- * the context (usually an Activity) from which the manual is to
- * be opened. In particular, this context is required to derive
- * the proper current locale configuration in order to open
- * appropriate localized manuals, if installed.
- *
- * @exception ActivityNotFoundException
- * there is no suitable manual installed and all combinations
- * of locale scope failed to activate any manual.
- *
- * @see #openManual(String, String, Context, String, boolean)
- */
- public static void openManual(String manualIdentifier, String topic,
- Context context) throws ActivityNotFoundException {
- openManual(manualIdentifier, topic, context, null, false);
- }
-
- /**
- * Convenience function to open a manual at a specific topic. See
- * {@link #openManual(String, String, Context, String)} for a detailed
- * description.
- *
- * @param manualIdentifier
- * the identifier of the manual to open. This identifier must
- * uniquely identify the manual as such, independent of the
- * particular locale the manual is intended for.
- * @param topic
- * the topic to open. Please do not use spaces for topic names.
- * With respect to the TiddlyWiki infrastructure used for manuals
- * the topic needs to the tag of a (single) tiddler. This way
- * manuals can be localized (especially their topic titles)
- * without breaking an app's knowledge about topics. Some
- * standardized topics are predefined, such as {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and
- * {@link #TOPIC_ABOUT_MANUAL}.
- * @param context
- * the context (usually an Activity) from which the manual is to
- * be opened. In particular, this context is required to derive
- * the proper current locale configuration in order to open
- * appropriate localized manuals, if installed.
- * @param fallbackUri
- * either <code>null</code> or a fallback URI to be used in case
- * the user has not installed any suitable manual.
- *
- * @exception ActivityNotFoundException
- * there is no suitable manual installed and all combinations
- * of locale scope failed to activate any manual.
- *
- * @see #openManual(String, String, Context, String, boolean)
- */
- public static void openManual(String manualIdentifier, String topic,
- Context context, String fallbackUri)
- throws ActivityNotFoundException {
- openManual(manualIdentifier, topic, context, fallbackUri, false);
- }
-
- /**
- * Opens a manual at a specific topic. At least it tries to open a manual.
- * As manuals are (usually) installed separately and we use late binding in
- * form of implicit intents, a lot of things can go wrong.
- *
- * We use late binding and the intent architecture in particular as follows:
- * first, we use our own URI scheme called "appmanual". Second, we use the
- * host field as a unique manual identifier (such as "c-geo" for the app
- * manuals for a map which must not be named by the powers that wanna be).
- * Third, a localized manual is differentiated as a path with a single
- * element in form of (in this precedence) "/lang_country_variant",
- * "/lang__variant", "/lang_country", "/lang", or "/". Fourth, the topic to
- * open is encoded as the a fragment "#topic=mytopic".
- *
- * In order to support localization, manuals can register themselves with
- * different URIs.
- *
- * @param manualIdentifier
- * the identifier of the manual to open. This identifier must
- * uniquely identify the manual as such, independent of the
- * particular locale the manual is intended for.
- * @param topic
- * the topic to open. Please do not use spaces for topic names.
- * With respect to the TiddlyWiki infrastructure used for manuals
- * the topic needs to the tag of a (single) tiddler. This way
- * manuals can be localized (especially their topic titles)
- * without breaking an app's knowledge about topics. Some
- * standardized topics are predefined, such as
- * {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and
- * {@link #TOPIC_ABOUT_MANUAL}.
- * @param context
- * the context (usually an Activity) from which the manual is to
- * be opened. In particular, this context is required to derive
- * the proper current locale configuration in order to open
- * appropriate localized manuals, if installed.
- * @param fallbackUri
- * either <code>null</code> or a fallback URI to be used in case
- * the user has not installed any suitable manual.
- * @param contextAffinity
- * if <code>true</code>, then we try to open the manual within
- * the context, if possible. That is, if the package of the
- * calling context also offers suitable activity registrations,
- * then we will prefer them over any other registrations. If you
- * don't know what this means, then you probably don't need this
- * very special capability and should specify <code>false</code>
- * for this parameter.
- *
- * @exception ActivityNotFoundException
- * there is no suitable manual installed and all combinations
- * of locale scope failed to activate any manual and no
- * {@literal fallbackUri} was given.
- */
- public static void openManual(String manualIdentifier, String topic,
- Context context, String fallbackUri, boolean contextAffinity)
- throws ActivityNotFoundException {
- //
- // The path of an "appmanual:" URI consists simply of the locale
- // information. This allows manual packages to register themselves
- // for both very specific locales as well as very broad ones.
- //
- String localePath = "/"
- + context.getResources().getConfiguration().locale.toString();
- //
- // We later need this intent in order to try to launch an appropriate
- // manual (respectively its manual viewer). And yes, we need to set
- // the intent's category explicitly, even as we will later use
- // startActivity(): if we don't do this, the proper activity won't be
- // started albeit the filter almost matches. That dirty behavior (it is
- // documented wrong) had cost me half a day until I noticed some
- // informational log entry generated from the ActivityManager. Grrrr!
- //
- Intent intent = new Intent(Intent.ACTION_VIEW);
- int defaultIntentFlags = intent.getFlags();
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- //
- // Try to open the manual in the following order (subject to
- // availability):
- // 1. manualIdentifier_lang_country_variant (can also be
- // manualIdentifier_lang__variant in some cases)
- // 2. manualIdentifier_lang_country
- // 3. manualIdentifier_lang
- // 4. manualIdentifier
- // Of course, manuals are free to register more than one Intent,
- // in particular, the should register also the plain manualIdentifier
- // as a suitable fallback strategy. Even when installing multiple
- // manuals this doesn't matter, as the user then can choose which
- // one to use on a single or permanent basis.
- //
- 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);
- intent.setFlags(defaultIntentFlags);
- if ( contextAffinity ) {
- //
- // What is happening here? Well, here we try something that we
- // would like to call "package affinity activity resolving".
- // Given an implicit(!) intent we try to figure out whether the
- // package of the context which is trying to open the manual is
- // able to resolve the intent. If this is the case, then we
- // simply turn the implicit intent into an explicit(!) intent.
- // We do this by setting the concrete module, that is: package
- // name (eventually the one of the calling context) and class
- // name within the package.
- //
- List<ResolveInfo> capableActivities = context
- .getPackageManager()
- .queryIntentActivityOptions(null, null, intent,
- PackageManager.MATCH_DEFAULT_ONLY);
- int capables = capableActivities.size();
- if ( capables > 1 ) {
- for ( int idx = 0; idx < capables; ++idx ) {
- ActivityInfo activityInfo = capableActivities.get(idx).activityInfo;
- if ( activityInfo.packageName.contentEquals(context
- .getPackageName()) ) {
- intent.setClassName(activityInfo.packageName,
- activityInfo.name);
- //
- // First match is okay, so we quit searching and
- // continue with the usual attempt to start the
- // activity. This should not fail, as we already
- // found a match; yet the code is very forgiving in
- // this respect and would just try another round
- // with "downsized" locale requirements.
- //
- break;
- }
- }
- }
- // FIXME
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
- } else {
- //
- // No context affinity required, thus we need to set some flags:
- //
- // ...NEW_TASK: we want to start the manual reader activity as a
- // separate
- // task so that it can be kept open, yet in the background when
- // returning to the application from which the manual was
- // opened.
- //
- // ...SINGLE_TOP:
- //
- // ...RESET_TASK_IF_NEEDED: clear the manual reader activities
- // down to the root activity. We've set the required
- // ...CLEAR_WHEN_TASK_RESET above when opening the meta-manual
- // with the context affinity.
- //
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_SINGLE_TOP
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- }
- try {
- String logTag = "appmanualclient";
- if ( Log.isLoggable(logTag, Log.INFO) ) {
- Log.i(logTag,
- "Trying to activate manual: uri=" + uri.toString());
- }
- context.startActivity(intent);
- //
- // We could successfully activate the manual activity, so no
- // further trials are required.
- //
- return;
- } catch ( ActivityNotFoundException noActivity ) {
- //
- // Ensure that we switch back to implicit intent resolving for
- // the next round.
- //
- intent.setComponent(null);
- //
- // As long as we still have some locale information, reduce it
- // and try again a broader locale.
- //
- if ( localePath.length() > 1 ) {
- int underscore = localePath.lastIndexOf('_');
- if ( underscore > 0 ) {
- localePath = localePath.substring(0, underscore);
- //
- // Handle the case where we have a locale variant, yet
- // no locale country, thus two underscores in immediate
- // series. Get rid of both.
- //
- if ( localePath.endsWith("_") ) {
- localePath = localePath
- .substring(0, underscore - 1);
- }
- } else {
- //
- // Ready for the last round: try without any locale
- // modifiers.
- //
- localePath = "/";
- }
- } else {
- //
- // We've tried all combinations, so we've run out of them
- // and bail out.
- //
- break;
- }
- }
- //
- // Okay, go for the next round, we've updated (or rather trimmed)
- // the localeIdent, so let us try this.
- //
- }
- //
- // If we reach this code point then no suitable activity could be found
- // and activated. In case the caller specified a fallback URI we will
- // try to open that. As this will activate a suitable browser and this
- // is an asynchronous activity we won't get back any negative results,
- // such as 404's. Here we will only see such problems that prevented the
- // start of a suitable browsing activity.
- //
- if ( fallbackUri != null ) {
- intent = new Intent(Intent.ACTION_VIEW, Uri.parse(fallbackUri));
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- context.startActivity(intent);
- }
- //
- // We could not activate any manual and there was no fallback URI to
- // open, so we finally bail out unsuccessful with an exception.
- //
- throw new ActivityNotFoundException();
- }
-}
diff --git a/main/templates/ocde_okapi.xml b/main/templates/ocde_okapi.xml
new file mode 100644
index 0000000..9ca39b3
--- /dev/null
+++ b/main/templates/ocde_okapi.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources>
+ <string name="oc_de_okapi_consumer_key" translatable="false">@ocde.okapi.consumer.key@</string>
+ <string name="oc_de_okapi_consumer_secret" translatable="false">@ocde.okapi.consumer.secret@</string>
+</resources>
diff --git a/main/templates/private.properties b/main/templates/private.properties
index f29cb7c..731ff50 100644
--- a/main/templates/private.properties
+++ b/main/templates/private.properties
@@ -1,7 +1,7 @@
# The API-key is necessary in order that Google Maps is working.
# You can get one at
# http://code.google.com/intl/de/android/add-ons/google-apis/maps-api-signup.html
-# For developing paste your key to both lines and you will not have any problems
+# For developing paste your key to both lines and you will not have any problems.
maps.api.key=
maps.api.key.market=
@@ -16,3 +16,10 @@ maps.api.key.market=
#key.alias=
#key.store.password=
#key.alias.password=
+
+# These keys allow c:geo to be registered at opencaching.de and
+# to search and log caches in your name.
+# You can request your own key at http://www.opencaching.de/okapi/signup.html
+
+ocde.okapi.consumer.key=
+ocde.okapi.consumer.secret=
diff --git a/main/src/android/support/v4/app/FragmentListActivity.java b/main/thirdparty/android/support/v4/app/FragmentListActivity.java
index e3ed42c..e3ed42c 100644
--- a/main/src/android/support/v4/app/FragmentListActivity.java
+++ b/main/thirdparty/android/support/v4/app/FragmentListActivity.java
diff --git a/main/src/cgeo/org/kxml2/io/KXmlSerializer.java b/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java
index 027ff53..027ff53 100644
--- a/main/src/cgeo/org/kxml2/io/KXmlSerializer.java
+++ b/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java
diff --git a/main/thirdparty/com/google/zxing/integration/android/IntentIntegrator.java b/main/thirdparty/com/google/zxing/integration/android/IntentIntegrator.java
new file mode 100644
index 0000000..902de4f
--- /dev/null
+++ b/main/thirdparty/com/google/zxing/integration/android/IntentIntegrator.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright 2009 ZXing authors
+ *
+ * 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 com.google.zxing.integration.android;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple
+ * way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the
+ * project's source code.</p>
+ *
+ * <h2>Initiating a barcode scan</h2>
+ *
+ * <p>To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait
+ * for the result in your app.</p>
+ *
+ * <p>It does require that the Barcode Scanner (or work-alike) application is installed. The
+ * {@link #initiateScan()} method will prompt the user to download the application, if needed.</p>
+ *
+ * <p>There are a few steps to using this integration. First, your {@link Activity} must implement
+ * the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
+ *
+ * <pre>{@code
+ * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ * IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
+ * if (scanResult != null) {
+ * // handle scan result
+ * }
+ * // else continue with any other code you need in the method
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>This is where you will handle a scan result.</p>
+ *
+ * <p>Second, just call this in response to a user action somewhere to begin the scan process:</p>
+ *
+ * <pre>{@code
+ * IntentIntegrator integrator = new IntentIntegrator(yourActivity);
+ * integrator.initiateScan();
+ * }</pre>
+ *
+ * <p>Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the
+ * user was prompted to download the application. This lets the calling app potentially manage the dialog.
+ * In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()}
+ * method.</p>
+ *
+ * <p>You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use
+ * {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and
+ * yes/no button labels can be changed.</p>
+ *
+ * <p>Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used
+ * to invoke the scanner. This can be used to set additional options not directly exposed by this
+ * simplified API.</p>
+ *
+ * <p>By default, this will only allow applications that are known to respond to this intent correctly
+ * do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}.
+ * For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.</p>
+ *
+ * <h2>Sharing text via barcode</h2>
+ *
+ * <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.</p>
+ *
+ * <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
+ *
+ * <h2>Enabling experimental barcode formats</h2>
+ *
+ * <p>Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as
+ * PDF417. Use {@link #initiateScan(java.util.Collection)} with
+ * a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such
+ * formats.</p>
+ *
+ * @author Sean Owen
+ * @author Fred Lin
+ * @author Isaac Potoczny-Jones
+ * @author Brad Drehmer
+ * @author gcstang
+ */
+public class IntentIntegrator {
+
+ public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits
+ private static final String TAG = IntentIntegrator.class.getSimpleName();
+
+ public static final String DEFAULT_TITLE = "Install Barcode Scanner?";
+ public static final String DEFAULT_MESSAGE =
+ "This application requires Barcode Scanner. Would you like to install it?";
+ public static final String DEFAULT_YES = "Yes";
+ public static final String DEFAULT_NO = "No";
+
+ private static final String BS_PACKAGE = "com.google.zxing.client.android";
+ private static final String BSPLUS_PACKAGE = "com.srowen.bs.android";
+
+ // supported barcode formats
+ public static final Collection<String> PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14");
+ public static final Collection<String> ONE_D_CODE_TYPES =
+ list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128",
+ "ITF", "RSS_14", "RSS_EXPANDED");
+ public static final Collection<String> QR_CODE_TYPES = Collections.singleton("QR_CODE");
+ public static final Collection<String> DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX");
+
+ public static final Collection<String> ALL_CODE_TYPES = null;
+
+ public static final List<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE);
+ public static final List<String> TARGET_ALL_KNOWN = list(
+ BS_PACKAGE, // Barcode Scanner
+ BSPLUS_PACKAGE, // Barcode Scanner+
+ BSPLUS_PACKAGE + ".simple" // Barcode Scanner+ Simple
+ // What else supports this intent?
+ );
+
+ private final Activity activity;
+ private String title;
+ private String message;
+ private String buttonYes;
+ private String buttonNo;
+ private List<String> targetApplications;
+ private final Map<String,Object> moreExtras;
+
+ public IntentIntegrator(Activity activity) {
+ this.activity = activity;
+ title = DEFAULT_TITLE;
+ message = DEFAULT_MESSAGE;
+ buttonYes = DEFAULT_YES;
+ buttonNo = DEFAULT_NO;
+ targetApplications = TARGET_ALL_KNOWN;
+ moreExtras = new HashMap<String,Object>(3);
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setTitleByID(int titleID) {
+ title = activity.getString(titleID);
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public void setMessageByID(int messageID) {
+ message = activity.getString(messageID);
+ }
+
+ public String getButtonYes() {
+ return buttonYes;
+ }
+
+ public void setButtonYes(String buttonYes) {
+ this.buttonYes = buttonYes;
+ }
+
+ public void setButtonYesByID(int buttonYesID) {
+ buttonYes = activity.getString(buttonYesID);
+ }
+
+ public String getButtonNo() {
+ return buttonNo;
+ }
+
+ public void setButtonNo(String buttonNo) {
+ this.buttonNo = buttonNo;
+ }
+
+ public void setButtonNoByID(int buttonNoID) {
+ buttonNo = activity.getString(buttonNoID);
+ }
+
+ public Collection<String> getTargetApplications() {
+ return targetApplications;
+ }
+
+ public final void setTargetApplications(List<String> targetApplications) {
+ if (targetApplications.isEmpty()) {
+ throw new IllegalArgumentException("No target applications");
+ }
+ this.targetApplications = targetApplications;
+ }
+
+ public void setSingleTargetApplication(String targetApplication) {
+ this.targetApplications = Collections.singletonList(targetApplication);
+ }
+
+ public Map<String,?> getMoreExtras() {
+ return moreExtras;
+ }
+
+ public final void addExtra(String key, Object value) {
+ moreExtras.put(key, value);
+ }
+
+ /**
+ * Initiates a scan for all known barcode types.
+ */
+ public final AlertDialog initiateScan() {
+ return initiateScan(ALL_CODE_TYPES);
+ }
+
+ /**
+ * Initiates a scan only for a certain set of barcode types, given as strings corresponding
+ * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
+ * like {@link #PRODUCT_CODE_TYPES} for example.
+ *
+ * @return the {@link AlertDialog} that was shown to the user prompting them to download the app
+ * if a prompt was needed, or null otherwise
+ */
+ public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
+ Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
+ intentScan.addCategory(Intent.CATEGORY_DEFAULT);
+
+ // check which types of codes to scan for
+ if (desiredBarcodeFormats != null) {
+ // set the desired barcode types
+ StringBuilder joinedByComma = new StringBuilder();
+ for (String format : desiredBarcodeFormats) {
+ if (joinedByComma.length() > 0) {
+ joinedByComma.append(',');
+ }
+ joinedByComma.append(format);
+ }
+ intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString());
+ }
+
+ String targetAppPackage = findTargetAppPackage(intentScan);
+ if (targetAppPackage == null) {
+ return showDownloadDialog();
+ }
+ intentScan.setPackage(targetAppPackage);
+ intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ attachMoreExtras(intentScan);
+ startActivityForResult(intentScan, REQUEST_CODE);
+ return null;
+ }
+
+ /**
+ * Start an activity.<br>
+ * This method is defined to allow different methods of activity starting for
+ * newer versions of Android and for compatibility library.
+ *
+ * @param intent Intent to start.
+ * @param code Request code for the activity
+ * @see android.app.Activity#startActivityForResult(Intent, int)
+ * @see android.app.Fragment#startActivityForResult(Intent, int)
+ */
+ protected void startActivityForResult(Intent intent, int code) {
+ activity.startActivityForResult(intent, code);
+ }
+
+ private String findTargetAppPackage(Intent intent) {
+ PackageManager pm = activity.getPackageManager();
+ List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ if (availableApps != null) {
+ for (ResolveInfo availableApp : availableApps) {
+ String packageName = availableApp.activityInfo.packageName;
+ if (targetApplications.contains(packageName)) {
+ return packageName;
+ }
+ }
+ }
+ return null;
+ }
+
+ private AlertDialog showDownloadDialog() {
+ AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
+ downloadDialog.setTitle(title);
+ downloadDialog.setMessage(message);
+ downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ String packageName = targetApplications.get(0);
+ Uri uri = Uri.parse("market://details?id=" + packageName);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ try {
+ activity.startActivity(intent);
+ } catch (ActivityNotFoundException anfe) {
+ // Hmm, market is not installed
+ Log.w(TAG, "Google Play is not installed; cannot install " + packageName);
+ }
+ }
+ });
+ downloadDialog.setNegativeButton(buttonNo, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {}
+ });
+ return downloadDialog.show();
+ }
+
+
+ /**
+ * <p>Call this from your {@link Activity}'s
+ * {@link Activity#onActivityResult(int, int, Intent)} method.</p>
+ *
+ * @return null if the event handled here was not related to this class, or
+ * else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
+ * the fields will be null.
+ */
+ public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
+ if (requestCode == REQUEST_CODE) {
+ if (resultCode == Activity.RESULT_OK) {
+ String contents = intent.getStringExtra("SCAN_RESULT");
+ String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
+ byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES");
+ int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE);
+ Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation;
+ String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL");
+ return new IntentResult(contents,
+ formatName,
+ rawBytes,
+ orientation,
+ errorCorrectionLevel);
+ }
+ return new IntentResult();
+ }
+ return null;
+ }
+
+
+ /**
+ * Defaults to type "TEXT_TYPE".
+ * @see #shareText(CharSequence, CharSequence)
+ */
+ public final AlertDialog shareText(CharSequence text) {
+ return shareText(text, "TEXT_TYPE");
+ }
+
+ /**
+ * Shares the given text by encoding it as a barcode, such that another user can
+ * scan the text off the screen of the device.
+ *
+ * @param text the text string to encode as a barcode
+ * @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants.
+ * @return the {@link AlertDialog} that was shown to the user prompting them to download the app
+ * if a prompt was needed, or null otherwise
+ */
+ public final AlertDialog shareText(CharSequence text, CharSequence type) {
+ Intent intent = new Intent();
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.setAction(BS_PACKAGE + ".ENCODE");
+ intent.putExtra("ENCODE_TYPE", type);
+ intent.putExtra("ENCODE_DATA", text);
+ String targetAppPackage = findTargetAppPackage(intent);
+ if (targetAppPackage == null) {
+ return showDownloadDialog();
+ }
+ intent.setPackage(targetAppPackage);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ attachMoreExtras(intent);
+ activity.startActivity(intent);
+ return null;
+ }
+
+ private static List<String> list(String... values) {
+ return Collections.unmodifiableList(Arrays.asList(values));
+ }
+
+ private void attachMoreExtras(Intent intent) {
+ for (Map.Entry<String,Object> entry : moreExtras.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ // Kind of hacky
+ if (value instanceof Integer) {
+ intent.putExtra(key, (Integer) value);
+ } else if (value instanceof Long) {
+ intent.putExtra(key, (Long) value);
+ } else if (value instanceof Boolean) {
+ intent.putExtra(key, (Boolean) value);
+ } else if (value instanceof Double) {
+ intent.putExtra(key, (Double) value);
+ } else if (value instanceof Float) {
+ intent.putExtra(key, (Float) value);
+ } else if (value instanceof Bundle) {
+ intent.putExtra(key, (Bundle) value);
+ } else {
+ intent.putExtra(key, value.toString());
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/main/thirdparty/com/google/zxing/integration/android/IntentResult.java b/main/thirdparty/com/google/zxing/integration/android/IntentResult.java
new file mode 100644
index 0000000..f7ccfe7
--- /dev/null
+++ b/main/thirdparty/com/google/zxing/integration/android/IntentResult.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009 ZXing authors
+ *
+ * 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 com.google.zxing.integration.android;
+
+/**
+ * <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
+ *
+ * @author Sean Owen
+ */
+public final class IntentResult {
+
+ private final String contents;
+ private final String formatName;
+ private final byte[] rawBytes;
+ private final Integer orientation;
+ private final String errorCorrectionLevel;
+
+ IntentResult() {
+ this(null, null, null, null, null);
+ }
+
+ IntentResult(String contents,
+ String formatName,
+ byte[] rawBytes,
+ Integer orientation,
+ String errorCorrectionLevel) {
+ this.contents = contents;
+ this.formatName = formatName;
+ this.rawBytes = rawBytes;
+ this.orientation = orientation;
+ this.errorCorrectionLevel = errorCorrectionLevel;
+ }
+
+ /**
+ * @return raw content of barcode
+ */
+ public String getContents() {
+ return contents;
+ }
+
+ /**
+ * @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names.
+ */
+ public String getFormatName() {
+ return formatName;
+ }
+
+ /**
+ * @return raw bytes of the barcode content, if applicable, or null otherwise
+ */
+ public byte[] getRawBytes() {
+ return rawBytes;
+ }
+
+ /**
+ * @return rotation of the image, in degrees, which resulted in a successful scan. May be null.
+ */
+ public Integer getOrientation() {
+ return orientation;
+ }
+
+ /**
+ * @return name of the error correction level used in the barcode, if applicable
+ */
+ public String getErrorCorrectionLevel() {
+ return errorCorrectionLevel;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder dialogText = new StringBuilder(100);
+ dialogText.append("Format: ").append(formatName).append('\n');
+ dialogText.append("Contents: ").append(contents).append('\n');
+ int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
+ dialogText.append("Raw bytes: (").append(rawBytesLength).append(" bytes)\n");
+ dialogText.append("Orientation: ").append(orientation).append('\n');
+ dialogText.append("EC level: ").append(errorCorrectionLevel).append('\n');
+ return dialogText.toString();
+ }
+
+} \ No newline at end of file
diff --git a/main/src/com/viewpagerindicator/PageIndicator.java b/main/thirdparty/com/viewpagerindicator/PageIndicator.java
index 26414d8..26414d8 100644
--- a/main/src/com/viewpagerindicator/PageIndicator.java
+++ b/main/thirdparty/com/viewpagerindicator/PageIndicator.java
diff --git a/main/src/com/viewpagerindicator/TitlePageIndicator.java b/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java
index 94ac962..94ac962 100644
--- a/main/src/com/viewpagerindicator/TitlePageIndicator.java
+++ b/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java
diff --git a/main/src/com/viewpagerindicator/TitleProvider.java b/main/thirdparty/com/viewpagerindicator/TitleProvider.java
index 2a04b65..2a04b65 100644
--- a/main/src/com/viewpagerindicator/TitleProvider.java
+++ b/main/thirdparty/com/viewpagerindicator/TitleProvider.java
diff --git a/main/src/org/openintents/intents/FileManagerIntents.java b/main/thirdparty/org/openintents/intents/FileManagerIntents.java
index 8ff10c8..8ff10c8 100644
--- a/main/src/org/openintents/intents/FileManagerIntents.java
+++ b/main/thirdparty/org/openintents/intents/FileManagerIntents.java