diff options
Diffstat (limited to 'main')
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 Binary files differnew file mode 100644 index 0000000..1bd6fe6 --- /dev/null +++ b/main/libs/butterknife-1.3.2.jar 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 Binary files differnew file mode 100644 index 0000000..7ee5bc4 --- /dev/null +++ b/main/project/attributes_okapi/genattr.jar 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 Binary files differdeleted file mode 100644 index c4a592f..0000000 --- a/main/project/rawimages/c_geo_icon_basic_512.png +++ /dev/null diff --git a/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png b/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png Binary files differdeleted file mode 100644 index 1fab340..0000000 --- a/main/project/rawimages/c_geo_icon_basic_freigestellt_512.png +++ /dev/null diff --git a/main/res/drawable-hdpi/actionbar_manual.png b/main/res/drawable-hdpi/actionbar_manual.png Binary files differdeleted file mode 100644 index 0b0c93c..0000000 --- a/main/res/drawable-hdpi/actionbar_manual.png +++ /dev/null diff --git a/main/res/drawable-hdpi/ic_menu_start_conversation.png b/main/res/drawable-hdpi/ic_menu_start_conversation.png Binary files differnew file mode 100644 index 0000000..395a5ec --- /dev/null +++ b/main/res/drawable-hdpi/ic_menu_start_conversation.png diff --git a/main/res/drawable-ldpi/actionbar_manual.png b/main/res/drawable-ldpi/actionbar_manual.png Binary files differdeleted file mode 100644 index 14af11d..0000000 --- a/main/res/drawable-ldpi/actionbar_manual.png +++ /dev/null diff --git a/main/res/drawable-ldpi/ic_menu_start_conversation.png b/main/res/drawable-ldpi/ic_menu_start_conversation.png Binary files differnew file mode 100644 index 0000000..1e39928 --- /dev/null +++ b/main/res/drawable-ldpi/ic_menu_start_conversation.png diff --git a/main/res/drawable-mdpi/actionbar_manual.png b/main/res/drawable-mdpi/actionbar_manual.png Binary files differdeleted file mode 100644 index a71acb3..0000000 --- a/main/res/drawable-mdpi/actionbar_manual.png +++ /dev/null diff --git a/main/res/drawable-mdpi/attribute_easy_climbing.png b/main/res/drawable-mdpi/attribute_easy_climbing.png Binary files differnew file mode 100644 index 0000000..ecf10b8 --- /dev/null +++ b/main/res/drawable-mdpi/attribute_easy_climbing.png diff --git a/main/res/drawable-mdpi/attribute_geotour.png b/main/res/drawable-mdpi/attribute_geotour.png Binary files differnew file mode 100644 index 0000000..f1f0c24 --- /dev/null +++ b/main/res/drawable-mdpi/attribute_geotour.png diff --git a/main/res/drawable-mdpi/helper_manual.png b/main/res/drawable-mdpi/helper_manual.png Binary files differdeleted file mode 100644 index c3c43db..0000000 --- a/main/res/drawable-mdpi/helper_manual.png +++ /dev/null diff --git a/main/res/drawable-mdpi/helper_pocketquery.png b/main/res/drawable-mdpi/helper_pocketquery.png Binary files differnew file mode 100644 index 0000000..0a24d2f --- /dev/null +++ b/main/res/drawable-mdpi/helper_pocketquery.png diff --git a/main/res/drawable-mdpi/ic_menu_start_conversation.png b/main/res/drawable-mdpi/ic_menu_start_conversation.png Binary files differnew file mode 100644 index 0000000..24b6540 --- /dev/null +++ b/main/res/drawable-mdpi/ic_menu_start_conversation.png 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 & 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コードが表示されるので、この下の入力欄にコピー&ペーストして「完了」ボタンを押してください。</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 |
