mirror of https://github.com/tasks/tasks
Merge commit '94a57ce7512954d092ea49a09f3f15ccc7486556' as 'api'
commit
9b26d9020e
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="output" path="ecbuild"/>
|
||||
</classpath>
|
@ -0,0 +1,8 @@
|
||||
*~
|
||||
.metadata
|
||||
*.class
|
||||
org.eclipse.ltk.core.refactoring.prefs
|
||||
gen
|
||||
local.properties
|
||||
ecbuild
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>astridApi</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -0,0 +1,332 @@
|
||||
#Wed Jul 07 18:43:41 PDT 2010
|
||||
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.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=ignore
|
||||
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=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
|
||||
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
|
||||
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
|
||||
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
|
||||
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=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
|
||||
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.redundantSuperinterface=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
|
||||
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.uncheckedTypeOperation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
|
||||
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.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=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
|
||||
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
|
||||
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=false
|
||||
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=true
|
||||
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=80
|
||||
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.format_guardian_clause_on_one_line=false
|
||||
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=false
|
||||
org.eclipse.jdt.core.formatter.indentation.size=4
|
||||
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_member=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_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=true
|
||||
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
|
||||
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=80
|
||||
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_tabs_only_for_leading_indentations=false
|
||||
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
|
@ -0,0 +1,109 @@
|
||||
#Tue Jun 29 14:53:46 PDT 2010
|
||||
cleanup.add_default_serial_version_id=true
|
||||
cleanup.add_generated_serial_version_id=false
|
||||
cleanup.add_missing_annotations=true
|
||||
cleanup.add_missing_deprecated_annotations=true
|
||||
cleanup.add_missing_methods=false
|
||||
cleanup.add_missing_nls_tags=false
|
||||
cleanup.add_missing_override_annotations=true
|
||||
cleanup.add_serial_version_id=true
|
||||
cleanup.always_use_blocks=true
|
||||
cleanup.always_use_parentheses_in_expressions=false
|
||||
cleanup.always_use_this_for_non_static_field_access=false
|
||||
cleanup.always_use_this_for_non_static_method_access=false
|
||||
cleanup.convert_to_enhanced_for_loop=false
|
||||
cleanup.correct_indentation=false
|
||||
cleanup.format_source_code=false
|
||||
cleanup.format_source_code_changes_only=false
|
||||
cleanup.make_local_variable_final=true
|
||||
cleanup.make_parameters_final=false
|
||||
cleanup.make_private_fields_final=true
|
||||
cleanup.make_type_abstract_if_missing_method=false
|
||||
cleanup.make_variable_declarations_final=false
|
||||
cleanup.never_use_blocks=false
|
||||
cleanup.never_use_parentheses_in_expressions=true
|
||||
cleanup.organize_imports=true
|
||||
cleanup.qualify_static_field_accesses_with_declaring_class=false
|
||||
cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
|
||||
cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
|
||||
cleanup.qualify_static_member_accesses_with_declaring_class=true
|
||||
cleanup.qualify_static_method_accesses_with_declaring_class=false
|
||||
cleanup.remove_private_constructors=true
|
||||
cleanup.remove_trailing_whitespaces=true
|
||||
cleanup.remove_trailing_whitespaces_all=true
|
||||
cleanup.remove_trailing_whitespaces_ignore_empty=false
|
||||
cleanup.remove_unnecessary_casts=true
|
||||
cleanup.remove_unnecessary_nls_tags=true
|
||||
cleanup.remove_unused_imports=true
|
||||
cleanup.remove_unused_local_variables=false
|
||||
cleanup.remove_unused_private_fields=true
|
||||
cleanup.remove_unused_private_members=false
|
||||
cleanup.remove_unused_private_methods=true
|
||||
cleanup.remove_unused_private_types=true
|
||||
cleanup.sort_members=false
|
||||
cleanup.sort_members_all=false
|
||||
cleanup.use_blocks=false
|
||||
cleanup.use_blocks_only_for_return_and_throw=false
|
||||
cleanup.use_parentheses_in_expressions=false
|
||||
cleanup.use_this_for_non_static_field_access=false
|
||||
cleanup.use_this_for_non_static_field_access_only_if_necessary=true
|
||||
cleanup.use_this_for_non_static_method_access=false
|
||||
cleanup.use_this_for_non_static_method_access_only_if_necessary=true
|
||||
cleanup_profile=_Astrid
|
||||
cleanup_settings_version=2
|
||||
eclipse.preferences.version=1
|
||||
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
|
||||
formatter_profile=_Astrid
|
||||
formatter_settings_version=11
|
||||
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
|
||||
sp_cleanup.add_default_serial_version_id=true
|
||||
sp_cleanup.add_generated_serial_version_id=false
|
||||
sp_cleanup.add_missing_annotations=true
|
||||
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_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=false
|
||||
sp_cleanup.format_source_code_changes_only=false
|
||||
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=true
|
||||
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=true
|
||||
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=false
|
||||
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
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.todoroo.astrid.api"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="3" />
|
||||
|
||||
</manifest>
|
@ -0,0 +1,24 @@
|
||||
Copyright (c) 2010, Todoroo, Inc
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,35 @@
|
||||
Astrid API Library - libraries for writing add-ons to [Astrid](http://www.weloveastrid.com/) -
|
||||
================================
|
||||
|
||||
This code is licensed under the New BSD License (see LICENSE)
|
||||
|
||||
Note that this is a beta release of the API - things may (and probably will) change from now until the official release. Documentation is also being written.
|
||||
|
||||
If you are planning on using this project, make sure to watch it for changes. Your feedback is also appreciated.
|
||||
|
||||
Getting Started With Development
|
||||
---------------
|
||||
|
||||
1. Install the following:
|
||||
• *[git](http://git.or.cz/)*
|
||||
• *[Eclipse](http://eclipse.org)* (preferred: Eclipse IDE for Java Developers)
|
||||
• *[Android SDK](http://developer.android.com/sdk/index.html)* - version 0.9.7 of Eclipse ADT is required
|
||||
|
||||
2. Use **git** to clone this repository (see Github's instructions if you need help).
|
||||
|
||||
2b. mkdir libs (in case your Android SDK is [not up to date](http://comments.gmane.org/gmane.comp.handhelds.android.devel/101722))
|
||||
|
||||
3. Open up **eclipse** and import the *astridApi* project.
|
||||
|
||||
4. If you are creating a new add-on for Astrid, create a new project in **eclipse**
|
||||
• in the Android tab of the project, indicate astridApi as a library reference
|
||||
|
||||
5. Check out the [wiki](http://wiki.github.com/todoroo/astridApi) and [javadoc](http://todoroo.github.com/astridApi)
|
||||
|
||||
Contact
|
||||
-------
|
||||
For support requests, use the Astrid issue tracker. For development questions, contact [timsu](http://github.com/timsu) via e-mail.
|
||||
|
||||
Astrid also has an IRC channel, irc.freenode.net #astrid
|
||||
|
||||
|
@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="." default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked in in Version
|
||||
Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The build.properties file can be created by you and is never touched
|
||||
by the 'android' tool. This is the place to change some of the default property values
|
||||
used by the Ant rules.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
application.package
|
||||
the name of your application package as defined in the manifest. Used by the
|
||||
'uninstall' rule.
|
||||
source.dir
|
||||
the name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
the name of the output directory. Default is 'bin'.
|
||||
|
||||
Properties related to the SDK location or the project target should be updated
|
||||
using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your application and
|
||||
should be checked in in Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="build.properties" />
|
||||
|
||||
<!-- The default.properties file is created and updated by the 'android' tool, as well
|
||||
as ADT.
|
||||
This file is an integral part of the build system for your application and
|
||||
should be checked in in Version Control Systems. -->
|
||||
<property file="default.properties" />
|
||||
|
||||
<!-- Custom Android task to deal with the project target, and import the proper rules.
|
||||
This requires ant 1.6.0 or above. -->
|
||||
<path id="android.antlibs">
|
||||
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />
|
||||
</path>
|
||||
|
||||
<taskdef name="setup"
|
||||
classname="com.android.ant.SetupTask"
|
||||
classpathref="android.antlibs" />
|
||||
|
||||
<!-- Execute the Android Setup task that will setup some properties specific to the target,
|
||||
and import the build rules files.
|
||||
|
||||
The rules file is imported from
|
||||
<SDK>/platforms/<target_platform>/templates/android_rules.xml
|
||||
|
||||
To customize some build steps for your project:
|
||||
- copy the content of the main node <project> from android_rules.xml
|
||||
- paste it in this build.xml below the <setup /> task.
|
||||
- disable the import by changing the setup task below to <setup import="false" />
|
||||
|
||||
This will ensure that the properties are setup correctly but that your customized
|
||||
build steps are used.
|
||||
-->
|
||||
<setup />
|
||||
|
||||
<target name="javadoc">
|
||||
<javadoc access="public" author="true" classpath="." destdir="doc"
|
||||
doctitle="Astrid API Project" nodeprecated="false"
|
||||
nodeprecatedlist="false" noindex="false" nonavbar="false"
|
||||
notree="false" source="1.6" splitindex="true"
|
||||
use="true" version="true">
|
||||
<sourcefiles>
|
||||
<fileset dir="." includes="src/**/*" />
|
||||
</sourcefiles>
|
||||
<classpath>
|
||||
<fileset dir="${sdk.dir}/platforms/${target}" includes="android.jar" />
|
||||
</classpath>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
</project>
|
@ -0,0 +1,12 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "build.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
android.library=true
|
||||
# Project target.
|
||||
target=android-3
|
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2006 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- Layout for a visually child-like Preference in a PreferenceActivity. -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/status"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingRight="?android:attr/scrollbarSize">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dip"
|
||||
android:layout_marginRight="6dip"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_marginBottom="6dip"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView android:id="@+android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal" />
|
||||
|
||||
<TextView android:id="@+android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_alignLeft="@android:id/title"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Preference should place its actual preference widget here. -->
|
||||
<LinearLayout android:id="@+android:id/widget_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 Any</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d Anys</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 Mes</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d Mesos</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Setmana</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Setmanes</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 dia</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Dies</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 Hora</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d Hores</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 Minut</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d Minuts</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 Segon</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d Segons</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 Hr</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d Hrs</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 Min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d Min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 Seg</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d Seg</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 tasca</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d tasques</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Confirmar?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Pregunta:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Informació</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Sí</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">No</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Tancar</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Fet</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">¡Ui, sembla que hi ha hagut un problema! Això es el que ha passat:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">¡Ui, sembla que hi ha hagut un problema!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Si us plau, espera...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Sincronitzant les seves tasques...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Sincronitzant...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Sincronització</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Error de conexió! Verifiqui la conexió d\'internet.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Estat</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">No conectat!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Sincronització en curs...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Última sincronització: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Fallida el: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Última sincronització correcte: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Mai sincronitzat!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Opcions</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Sincronitzar en segon pla</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Desactivada la sincronització en segon pla</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Actualment configurat en: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Configuració Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">La sincronització en segon pla només funciona amb el Wifi activat.</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Sempre es produirà la sincronització en segon pla</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Accions</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Sincronitzar Ara!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Ingressar & Sincronitzar!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Surt</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Esborra tota la informació de sincronització</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Tancar sessió / esborra la informació de sincronització?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>desactivat</item>
|
||||
<item>cada quince minuts</item>
|
||||
<item>cada trenta minuts</item>
|
||||
<item>cada hora</item>
|
||||
<item>cada tres hores</item>
|
||||
<item>cada sis hores</item>
|
||||
<item>cada dotze hores</item>
|
||||
<item>diàriament</item>
|
||||
<item>cada tres dies</item>
|
||||
<item>setmanalment</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 rok</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d Roky</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 měsíc</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d Měsíce</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 týden</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Týdny</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 den</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Dnů</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 hodina</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d hodin</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 minuta</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d minut</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 vteřina</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d vteřin</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 hod.</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d hod.</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 min.</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d min.</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 s</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d s</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 úkol</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d úkolů</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Potvrdit?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Otázka:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Informace</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Ano</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">Ne</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Zavřít</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Hotovo</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Prosím čekejte...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Probíhá synchronizace Vašich úkolů...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Sychronizuji...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Synchronizace</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Connection Error! Check your Internet connection.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Stav</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Not Logged In!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Probíhá synchronizace...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Poslední synchronizace: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Selhalo: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Poslední úspěšná synchronizace: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Nikdo nesynchronizováno!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Možnosti</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Synchronizace na pozadí</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Synchronizace na pozadí je zakázána</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Současně nastaveno na: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Nastavení jen pro Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Synchronizovat na pozadí se bude pouze při zapnuté Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Synchronizovat na pozadí se bude vždy</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Činnosti</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Synchronizuj teď!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Přihlásit se & Synchronizovat!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Odhlásit se</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Odhlásit se / vymazat synchronizační data?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>zakázat</item>
|
||||
<item>každých patnáct minut</item>
|
||||
<item>každých třicet minut</item>
|
||||
<item>každou hodinu</item>
|
||||
<item>každé tři hodiny</item>
|
||||
<item>každých šest hodin</item>
|
||||
<item>každých dvanáct hodin</item>
|
||||
<item>každý den</item>
|
||||
<item>každé tři dny</item>
|
||||
<item>každý týden</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">Ein Jahr</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d Jahre</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">Ein Monat</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d Monate</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">Eine Woche</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Wochen</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Tag</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Tage</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 Stunde</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d Stunden</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 Minute</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d Minuten</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 Sekunde</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d Sekunden</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 Std</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d Std</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 Min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d Min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 Sek</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d Sek</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 Aufgabe</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d Aufgaben</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Bestätigen</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Frage:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Information</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Fehler!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Ja</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">Nein</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Schließen</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Erledigt</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Ups, sieht aus, als ob ein Fehler passiert ist! Hier, was passiert ist:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Ups, sieht aus, als ob ein Fehler passiert ist!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Bitte warten...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synchronisiere deine Aufgaben</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Synchronisiere…</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Abgleich</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Verbindungsfehler! Überprüfen Sie Ihre Internetverbindung.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Status</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Nicht angemeldet!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Synchronisierung läuft...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Letzte Synchronisierung: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Fehlgeschlagen am: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Letzte erfolgreiche Synchronisierung: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Noch nie synchronisiert!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Einstellungen</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Hintergrund-Synchronisierung</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Hintergrund-Synchronisierung ist deaktiviert</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Gesetzt auf: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">WLAN Einstellungen</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Hintergrund-Synchronisierung nur bei WLAN-Verbindung</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Hintergrund-Synchronisierung findet immer statt</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Aktionen</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Jetzt abgleichen!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Einloggen & Synchroniseren!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Abmelden</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Alle Synchronisationsdaten löschen</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Ausloggen / synchronisierte Daten löschen?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>deaktivieren</item>
|
||||
<item>alle 15 Minuten</item>
|
||||
<item>alle 30 Minuten</item>
|
||||
<item>stündlich</item>
|
||||
<item>alle 3 Stunden</item>
|
||||
<item>alle 6 Stunden</item>
|
||||
<item>alle 12 Stunden</item>
|
||||
<item>täglich</item>
|
||||
<item>jeden dritten Tag</item>
|
||||
<item>wöchentlich</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 año</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d años</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 Mes</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d meses</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 semana</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d semanas</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 día</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d días</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 hora</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d horas</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 minuto</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d minutos</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 segundo</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d segundos</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 hora</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d horas</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 minuto</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d minutos</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 segundo</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d segundos</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 tarea</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d tareas</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">¿Confirmar?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Pregunta:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Información</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">¡Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Sí</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">No</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Cerrar</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Listo</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">¡Uy, al parecer hay algún problema! Esto es lo que pasó:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">¡Uy, al parecer hay algún problema!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Espere por favor...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Sincronizando sus tareas...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Sincronizando...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Sincronización</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Error de conexión! Verifique su conexión a internet.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Estado</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">No conectado!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Sincronización en curso...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Última sincronización: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Falló el: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Última sincronización exitosa: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">¡Jamás se sincronizó!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Opciones</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Sincronizar en segundo plano</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Sincronización en segundo plano desactivada</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Actualmente configurado para: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Sólo Configuración Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">La sincronización en segundo plano sólo funciona con el Wifi activado</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">La sincronización en segundo plano funciona siempre</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Acciones</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">¡Sincronizar ahora!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Iniciar sesión y sincronizar!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Cerrar sesión</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Borra todos los datos de sincronización</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Cierre de sesión / cancelar la sincronización de datos?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>desactivar</item>
|
||||
<item>cada quince minutos</item>
|
||||
<item>cada treinta minutos</item>
|
||||
<item>cada hora</item>
|
||||
<item>cada tres horas</item>
|
||||
<item>cada seis horas</item>
|
||||
<item>cada doce horas</item>
|
||||
<item>cada día</item>
|
||||
<item>cada tres días</item>
|
||||
<item>cada semana</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 année</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d années</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 mois</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d mois</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 semaine</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d semaines</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 jour</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d jours</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 heure</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d heures</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 minute</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d minutes</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 seconde</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d secondes</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 h</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d h</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 s</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d s</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 tâche</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d tâches</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Confirmer ?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Question :</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Information</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Erreur !</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Oui</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">Non</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Fermer</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Terminé</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Veuillez patienter...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synchronisation de vos tâches...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Synchronisation...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Synchronisation</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Connection Error! Check your Internet connection.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Statut</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Not Logged In!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Synchronisation en cours...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Dernière synchro. : %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Échec sur : %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Dernière synchro. réussie : %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Jamais synchronisé !</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Options</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Synchro. en arrière-plan</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Synchronisation en arrière-plan désactivée</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Actuellement configuré sur : %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Paramètre Wifi seul</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">La synchronisation en arrière-plan ne s\'effectue uniquement sous Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">La synchronisation en arrière-plan s\'effectuera toujours</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Actions</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Synchroniser maintenant !</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Se connecter et synchroniser !</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Se déconnecter</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Se déconnecter/purger les données de synchronisation ?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>désactiver</item>
|
||||
<item>toutes les quinze minutes</item>
|
||||
<item>toutes les trente minutes</item>
|
||||
<item>toutes les heures</item>
|
||||
<item>toutes les trois heures</item>
|
||||
<item>toutes les six heures</item>
|
||||
<item>toutes les douze heures</item>
|
||||
<item>tous les jours</item>
|
||||
<item>tous les trois jours</item>
|
||||
<item>toutes les semaines</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 Year</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d Years</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 Month</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d Months</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Week</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Weeks</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Hari</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Hari</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 Jam</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d Jam</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 Menit</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d Menit</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 Detik</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d Detik</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 Jam</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d Jam</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 Mnt</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d Mnt</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 Dtk</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d Dtk</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 task</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d tasks</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Confirm?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Question:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Informasi</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Yes</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">No</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Close</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Selesai</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Please wait...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synchronizing your tasks...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Synchronizing...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Sinkronisasi</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Connection Error! Check your Internet connection.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Status</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Not Logged In!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Sync Ongoing...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Last Sync: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Failed On: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Last Successful Sync: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Never Synchronized!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Pilihan</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Background Sync</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Background synchronization is disabled</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Currently set to: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Wifi Only Setting</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Background synchronization only happens when on Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Background synchronization will always occur</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Aksi</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Sinkronkan Sekarang!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Log In & Synchronize!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Log Out</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Log out / clear synchronization data?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>tidak difungsikan</item>
|
||||
<item>every fifteen minutes</item>
|
||||
<item>every thirty minutes</item>
|
||||
<item>every hour</item>
|
||||
<item>every three hours</item>
|
||||
<item>every six hours</item>
|
||||
<item>every twelve hours</item>
|
||||
<item>every day</item>
|
||||
<item>every three days</item>
|
||||
<item>every week</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 Anno</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d Anni</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 Mese</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d Mesi</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Settimana</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Settimane</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 giorno</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Giorni</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 ora</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d ore</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 minuto</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d minuti</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 secondo</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d secondi</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 ora</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d ore</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 sec</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d sec</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 Attività</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d attività</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Conferma?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Domanda:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Informazioni</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Sì</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">No</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Chiudi</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Completata</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Attendere per favore...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Sincronizzando le tue attività...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Sincronizzando...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Sincronizzazione</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Connection Error! Check your Internet connection.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Stato</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Not Logged In!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Sincronizzazione in corso ...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Ultima Sincronizzazione: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Fallita Su: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Ultima sincronizzazione eseguita con successo in data: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Mai sincronizzato!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Opzioni</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Sincronizzazione eseguita in background</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">La sincronizzazione in background è disattivata</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Attualmente impostata su: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Unica Impostazione Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">la sincronizzazione in background avviene solo quando la rete Wifi è abilitata</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">La sincronizzazione in background avviene sempre</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Azioni</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Sincronizza Ora!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Esegui l\'accesso & Sincronizza!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Esci</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Esci / cancella i file di sincronizzazione?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>disabilita</item>
|
||||
<item>ogni quindici minuti</item>
|
||||
<item>ogni trenta minuti</item>
|
||||
<item>ogni ora</item>
|
||||
<item>ogni tre ore</item>
|
||||
<item>ogni sei ore</item>
|
||||
<item>ogni dodici ore</item>
|
||||
<item>ogni giorno</item>
|
||||
<item>ogni tre giorni</item>
|
||||
<item>Ogni settimana</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1年</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d 年</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1か月</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d か月</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1週間</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d 週間</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 日</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d 日</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 時間</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d 時間</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 分</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d 分</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 秒</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d 秒</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 時間</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d 時間</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 分</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d 分</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 秒</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d 秒</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">タスク 1 件</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">タスク %d 件</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">確認</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">確認</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">インフォメーション</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">エラー</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">はい</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">いいえ</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">閉じる</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">完了</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">お待ちください</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">タスクの同期中...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">同期中...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">同期</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Connection Error! Check your Internet connection.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">状況</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">ログインしていません</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">同期中</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">前回の同期: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">失敗: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">最後の同期: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">同期していません</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">オプション</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">バックグラウンド同期</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">バックグラウンド同期は無効になっています</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">現在の設定: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Wi-Fi のみ</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Wi-Fi が有効なときだけバックグラウンドで同期する</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Background synchronization will always occur</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">アクション</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">すぐに同期!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">ログインと同期</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">ログアウト</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">すべての同期データを消去します</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">ログアウトと同期データを消去しますか?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>無効</item>
|
||||
<item>15分毎</item>
|
||||
<item>30分毎</item>
|
||||
<item>1時間毎</item>
|
||||
<item>3時間毎</item>
|
||||
<item>6時間毎</item>
|
||||
<item>12時間毎</item>
|
||||
<item>毎日</item>
|
||||
<item>3日に一度</item>
|
||||
<item>毎週</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1년</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d 년</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1개월</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d 개월</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1주</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d 주</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1일</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d 일</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1시간</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d 시간</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 분</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d 분</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 초</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d 초</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 시간</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d 시간</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 분</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d 분</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 초</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d 초</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 작업</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d 작업</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">확인?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">질문:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">정보</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">오류!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">네</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">아니오</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">닫기</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">마침</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">오류가 발생한 것 같습니다! 원인은 다음과 같습니다:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">오류가 발생한 것 같습니다!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">잠시만 기다려주세요...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">작업 동기화 중입니다...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">동기화하는 중...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">동기화</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">연결 오류! 인터넷 연결을 확인하세요.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">상태</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">로그인 되지 않았습니다!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">동기화 진행중...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">마지막 동기화: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">실패: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">마지막 동기화 성공시간: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">한번도 동기화 되지 않았습니다!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">옵션</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">백그라운드 동기화</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">백그라운드 동기화가 설정되지 않았습니다.</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">현재 설정: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">WiFi 일때만 설정</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">백그라운드 동기화는 WiFi 지역에서만 작동합니다.</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">백그라운드 동기화는 항상 작동합니다.</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">작업</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">동기화 시작!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">로그인 & 동기화!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">로그아웃</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">모든 동기화 데이터 삭제</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">로그아웃 / 모든 동기화 데이터 삭제?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>사용안함</item>
|
||||
<item>매 15분 마다</item>
|
||||
<item>매 30분마다</item>
|
||||
<item>매 시간</item>
|
||||
<item>매 3시간마다</item>
|
||||
<item>매 6시간마다</item>
|
||||
<item>매 12시간마다</item>
|
||||
<item>매일</item>
|
||||
<item>매 3일마다</item>
|
||||
<item>매주</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 år</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d år</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 måned</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d måneder</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 uke</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d uker</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 dag</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d dager</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 time</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d timer</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 minutt</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d minutter</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 sekund</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d sekunder</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 t</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d t</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 s</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d s</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 oppgave</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d oppgaver</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Bekreft?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Spørsmål:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Informasjon</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Feil!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Ja</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">Nei</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Lukk</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Utført</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oi sann! Det ser ut for at en feil oppstod. Her er hva som skjedde:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oi sann! Det ser ut for at en feil oppstod</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Vennligst vent...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synkroniserer oppgavene dine...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Synkroniserer...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Synkronisering</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Tilkoblingsfeil! Kontroller at du er koblet til Internett</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Status</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Not Logged In!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Synkronisering pågår...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Siste synkronisering: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Feilet: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Siste vellykkede synkronisering: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Aldri synkronisert!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Alternativer</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Bakgrunnssynkronisering</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Bakgrunnssynkronisering er deaktivert</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Foreløpig satt til %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Bare Wifi Innstilling</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Synkronisering i bakgrunnen skal kun utføres med WiFi-tilkobling</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Synkronisering i bakgrunnen skal alltid utføres</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Handlinger</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Synkroniser nå!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Logg Inn & Synkroniser!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Logg av</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Logge ut / slette synkroniserings data?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>deaktiver</item>
|
||||
<item>hvert kvarter</item>
|
||||
<item>hver halvtime</item>
|
||||
<item>hver time</item>
|
||||
<item>hver tredje time</item>
|
||||
<item>hver sjette time</item>
|
||||
<item>hver tolvte time</item>
|
||||
<item>daglig</item>
|
||||
<item>hver tredje dag</item>
|
||||
<item>hver uke</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 jaar</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d jaren</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 maand</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d maanden</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 week</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d weken</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 dag</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Dagen</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 Uur</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d Uren</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 Minuut</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d Minuten</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 Seconde</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d Seconden</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 U</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d Uur</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 Min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d Min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 Sec</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d Sec</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 task</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d tasks</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Confirm?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Vraag:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Informatie</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Ja</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">Nee</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Sluiten</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Voltooid</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Even geduld alstublieft...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synchronizing your tasks...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Bezig met synchroniseren...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Synchronisatie</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Connection Error! Check your Internet connection.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Status</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Not Logged In!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Sync Ongoing...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Last Sync: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Failed On: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Last Successful Sync: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Never Synchronized!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Opties</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Background Sync</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Background synchronization is disabled</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Currently set to: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Wifi Only Setting</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Background synchronization only happens when on Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Background synchronization will always occur</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Acties</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Synchroniseer nu!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Log In & Synchronize!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Afmelden</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Log out / clear synchronization data?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>uit</item>
|
||||
<item>elke 15 minuten</item>
|
||||
<item>elke 30 minuten</item>
|
||||
<item>elk uur</item>
|
||||
<item>elke 3 uur</item>
|
||||
<item>elke 6 uur</item>
|
||||
<item>elke 12 uur</item>
|
||||
<item>elke dag</item>
|
||||
<item>elke 3 dagen</item>
|
||||
<item>elke week</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 rok</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d lat</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 miesiąc</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d miesięcy</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 tydzień</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d tygodni</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 dzień</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d dni</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 godzina</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d godzin</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 minuta</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d minut</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 sekunda</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d sekund</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 godz.</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d godz.</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 min.</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d min.</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 sek.</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d sek.</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 zadanie</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d zadań</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Potwierdzić?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Pytanie:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Informacja</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Błąd!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Tak</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">Nie</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Zamknij</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Gotowe</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Ups! Wygląda na to, że wystąpił jakiś błąd! Oto, co się stało:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Ups! Wygląda na to, że wystąpił jakiś błąd!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Proszę czekać...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synchronizowanie Twoich zadań...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Synchronizacja...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Synchronizacja</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Błąd połączenia! Sprawdź swoje połączenie z Internetem!</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Stan</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Nie zalogowano!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Synchronizacja trwa...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Ostatnia synchronizacja: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Nieudana: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Ostatnia udana synchronizacja: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Nigdy nie synchronizowano!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Ustawienia</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Synchronizacja w tle</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Synchronizacja w tle wyłączona</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Aktualnie ustawione na: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Tylko połączenie Wi-Fi</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Synchronizacja w tle przebiega tylko poprzez Wi-Fi</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Synchronizowanie w tle zawsze, niezależnie od rodzaju połączenia</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Działania</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Synchronizuj teraz!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Zaloguj & Synchronizuj!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Wyloguj</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Czyści wszystkie dane synchronizacji</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Wyloguj / wyczyść dane synchronizacji?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>Wyłączone</item>
|
||||
<item>co 15 minut</item>
|
||||
<item>co 30 minut</item>
|
||||
<item>co godzinę</item>
|
||||
<item>co 3 godziny</item>
|
||||
<item>co 6 godzin</item>
|
||||
<item>co 12 godzin</item>
|
||||
<item>raz dziennie</item>
|
||||
<item>co 3 dni</item>
|
||||
<item>co tydzień</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 Ano</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d Anos</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 Mês</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d Meses</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Semana</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Semanas</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Dia</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Dias</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 Hora</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d Horas</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 Minuto</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d Minutos</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 Segundo</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d Segundos</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 h</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d h</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 s</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d s</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 tarefa</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d tarefas</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Confirma?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Pergunta:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Informação</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Sim</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">Não</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Fechar</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Concluído</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Por favor aguarde...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synchronizing your tasks...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">A Sincronizar...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Sincronização</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Connection Error! Check your Internet connection.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Estado</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Not Logged In!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Sync Ongoing...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Last Sync: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Failed On: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Last Successful Sync: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Never Synchronized!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Opções</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Background Sync</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Background synchronization is disabled</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Currently set to: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Wifi Only Setting</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Background synchronization only happens when on Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Background synchronization will always occur</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Acções</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Sincronizar Agora!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Log In & Synchronize!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Terminar sessão</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Log out / clear synchronization data?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>desactivar</item>
|
||||
<item>every fifteen minutes</item>
|
||||
<item>every thirty minutes</item>
|
||||
<item>every hour</item>
|
||||
<item>every three hours</item>
|
||||
<item>every six hours</item>
|
||||
<item>every twelve hours</item>
|
||||
<item>every day</item>
|
||||
<item>every three days</item>
|
||||
<item>every week</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 år</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d år</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 månad</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d månader</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 vecka</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d veckor</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 dag</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d dagar</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 timme</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d timmar</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 minut</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d minuter</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 sekund</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d sekunder</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 tim</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d tim</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 sek</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d sek</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 uppgift</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d uppgifter</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Bekräfta?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Fråga:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Information</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Fel!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Ja</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">Nej</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Stäng</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Klar</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oj, det uppstod ett fel! Detta hände:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oj, det uppstod ett fel!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Var god vänta...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synkroniserar dina uppgifter...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Synkroniserar...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Synkronisering</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Tillkopplingsfel! Kontrollera din tillkoppling till internet.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Status</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Ej inloggad!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Synkronisering pågår...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Synkroniserades senast: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Misslyckades: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Synkronisering lyckades senast: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Aldrig synkroniserad!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Alternativ</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Bakgrundssynkronisering</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Bakgrundssynkronisering är inaktiverad</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Aktuell inställning: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Endast Wi-Fi Inställning</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Bakgrundssynkronisering sker endast när du är ansluten till Wi-Fi</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Bakgrundssynkronisering sker alltid</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Åtgärder</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Synkronisera nu!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Logga in & synkronisera!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Logga ut</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Rensar alla synkroniseringsdata</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Logga ut / rensa synkroniseringsdata?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>inaktivera</item>
|
||||
<item>varje kvartstimme</item>
|
||||
<item>varje halvtimme</item>
|
||||
<item>varje timme</item>
|
||||
<item>var tredje timme</item>
|
||||
<item>var sjätte timme</item>
|
||||
<item>var tolfte timme</item>
|
||||
<item>varje dag</item>
|
||||
<item>var tredje dag</item>
|
||||
<item>varje vecka</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1年</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d年</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1个月</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d个月</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1周</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d周</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1天</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d天</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1小时</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d小时</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1分钟</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d分钟</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1秒</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d秒</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1小时</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d小时</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1分钟</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d分钟</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1秒</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d秒</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1任务</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d任务</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">确认?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">问题:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">信息</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">错误!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">是</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">否</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">关闭</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">完成</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">哇,看来出错了!情况如下:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">哇,看来出错了!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">请稍候...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">正在同步任务...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">正在同步...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">同步</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">连接错误!查看您的网络连接。</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">状态</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">未登录!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">正在同步...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">上一次同步:%s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">同步失败:%s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">上一次成功同步:%s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">从未同步!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">选项</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">后台同步</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">后台同步已禁用</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">当前设置为:%s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">仅使用 Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">仅当 Wifi 打开时使用后台同步</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">总是使用后台同步</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">行动</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">现在同步!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">登录&同步</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">注销</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">清除所有同步数据</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">注销并清除同步数据?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>禁用</item>
|
||||
<item>每十五分钟</item>
|
||||
<item>每半小时</item>
|
||||
<item>每小时</item>
|
||||
<item>每三小时</item>
|
||||
<item>每六小时</item>
|
||||
<item>每十二小时</item>
|
||||
<item>每天</item>
|
||||
<item>每三天</item>
|
||||
<item>每周</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 年</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d 年</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 個月</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d 月</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 週</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d 週</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 天</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d 天</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 小時</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d 小時</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 分鐘</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d 分鐘</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 秒</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d 秒</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 小時</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d 小時</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 分鐘</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d 分鐘</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 秒</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d 秒</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 個工作</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d 個工作</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">確認?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">問題:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">資訊</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">確定</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">取消</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">關閉</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">完成</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">請稍候...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">同步工作中...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">正在同步中...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">同步</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">連結錯誤! 檢查您的網際網路連線.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">狀態</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">未登入!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">同步中...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">上次同步: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">失敗: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">上次成功同步: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">未同步過!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">選項</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">背景同步</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">背景同步關閉</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">目前同步設定: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Wifi 才可使用之設定</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">使用Wifi才啟動背景同步</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">總是使用背景同步</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">動作</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">現在同步!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">登入並同步!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">登出</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">清除所有同步資料</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">登出 / 清除同步資料?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>停用</item>
|
||||
<item>每15分</item>
|
||||
<item>每30分</item>
|
||||
<item>每小時</item>
|
||||
<item>每3小時</item>
|
||||
<item>每6小時</item>
|
||||
<item>每12小時</item>
|
||||
<item>每天</item>
|
||||
<item>每3天</item>
|
||||
<item>每週</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
</resources>
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<color name="importance_1">#ffff5555</color>
|
||||
<color name="importance_2">#fffea400</color>
|
||||
<color name="importance_3">#ff33a5e8</color>
|
||||
<color name="importance_4">#ff808080</color>
|
||||
<color name="importance_5">#ff505050</color>
|
||||
<color name="importance_6">#ff202020</color>
|
||||
|
||||
</resources>
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file contains preference keys and preference list values.
|
||||
These should not be translated
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
|
||||
<!-- ============================================================ SYNC == -->
|
||||
|
||||
<string-array name="sync_SPr_interval_values">
|
||||
<!-- sync_SPr_interval_values: interval in seconds for sync entries (do not edit) -->
|
||||
<item>0</item>
|
||||
<item>900</item>
|
||||
<item>1800</item>
|
||||
<item>3600</item>
|
||||
<item>10800</item>
|
||||
<item>21600</item>
|
||||
<item>43200</item>
|
||||
<item>86400</item>
|
||||
<item>259200</item>
|
||||
<item>604800</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Preference Key (do not translate) -->
|
||||
<string name="sync_SPr_status_key">sync_status</string>
|
||||
<!-- Preference Key (do not translate) -->
|
||||
<string name="sync_SPr_bgwifi_key">sync_bgwifi</string>
|
||||
<!-- Preference Key (do not translate) -->
|
||||
<string name="sync_SPr_sync_key">sync_sync</string>
|
||||
<!-- Preference Key (do not translate) -->
|
||||
<string name="sync_SPr_forget_key">sync_forget</string>
|
||||
|
||||
</resources>
|
@ -0,0 +1,194 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ==================================================== Generic Units == -->
|
||||
|
||||
<plurals name="DUt_years">
|
||||
<!-- plurals: years -->
|
||||
<item quantity="one">1 Year</item>
|
||||
<!-- plurals: years -->
|
||||
<item quantity="other">%d Years</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_months">
|
||||
<!-- plurals: months -->
|
||||
<item quantity="one">1 Month</item>
|
||||
<!-- plurals: months -->
|
||||
<item quantity="other">%d Months</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weeks">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Week</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Weeks</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_days">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Day</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Days</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_weekdays">
|
||||
<!-- plurals: days -->
|
||||
<item quantity="one">1 Weekday</item>
|
||||
<!-- plurals: days -->
|
||||
<item quantity="other">%d Weekdays</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hours">
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="one">1 Hour</item>
|
||||
<!-- plurals: hours -->
|
||||
<item quantity="other">%d Hours</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutes">
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="one">1 Minute</item>
|
||||
<!-- plurals: minutes -->
|
||||
<item quantity="other">%d Minutes</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_seconds">
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="one">1 Second</item>
|
||||
<!-- plurals: seconds -->
|
||||
<item quantity="other">%d Seconds</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_hoursShort">
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="one">1 Hr</item>
|
||||
<!-- plurals: hours (abbreviated) -->
|
||||
<item quantity="other">%d Hrs</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_minutesShort">
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="one">1 Min</item>
|
||||
<!-- plurals: minutes (abbreviated) -->
|
||||
<item quantity="other">%d Min</item>
|
||||
</plurals>
|
||||
<plurals name="DUt_secondsShort">
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="one">1 Sec</item>
|
||||
<!-- plurals: seconds (abbreviated) -->
|
||||
<item quantity="other">%d Sec</item>
|
||||
</plurals>
|
||||
<plurals name="Ntasks">
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="one">1 task</item>
|
||||
<!-- plurals: tasks -->
|
||||
<item quantity="other">%d tasks</item>
|
||||
</plurals>
|
||||
|
||||
<!-- ================================================== Generic Dialogs == -->
|
||||
|
||||
<!-- confirmation dialog title -->
|
||||
<string name="DLG_confirm_title">Confirm?</string>
|
||||
|
||||
<!-- question dialog title -->
|
||||
<string name="DLG_question_title">Question:</string>
|
||||
|
||||
<!-- information dialog title -->
|
||||
<string name="DLG_information_title">Information</string>
|
||||
|
||||
<!-- error dialog title -->
|
||||
<string name="DLG_error_title">Error!</string>
|
||||
|
||||
<!-- general dialog yes-->
|
||||
<string name="DLG_yes">Yes</string>
|
||||
|
||||
<!-- general dialog no-->
|
||||
<string name="DLG_no">No</string>
|
||||
|
||||
<!-- general dialog close-->
|
||||
<string name="DLG_close">Close</string>
|
||||
|
||||
<!-- general dialog done -->
|
||||
<string name="DLG_done">Done</string>
|
||||
|
||||
<!-- error dialog (%s => error message)-->
|
||||
<string name="DLG_error">Oops, looks like an error occurred! Here\'s what happened:\n\n%s</string>
|
||||
|
||||
<!-- error dialog (no message indicated)-->
|
||||
<string name="DLG_error_generic">Oops, looks like an error occurred!</string>
|
||||
|
||||
<!-- Progress dialog shown when doing something slow -->
|
||||
<string name="DLG_wait">Please wait...</string>
|
||||
|
||||
<!-- ====================================================== SyncProvider == -->
|
||||
|
||||
<!-- Sync Notification: message when sync service active -->
|
||||
<string name="SyP_progress">Synchronizing your tasks...</string>
|
||||
|
||||
<!-- Sync Notification: toast when sync activated from activity -->
|
||||
<string name="SyP_progress_toast">Synchronizing...</string>
|
||||
|
||||
<!-- Sync Label: used in menu to denote synchronization -->
|
||||
<string name="SyP_label">Synchronization</string>
|
||||
|
||||
<!-- Error msg when io exception -->
|
||||
<string name="SyP_ioerror">Connection Error! Check your Internet connection.</string>
|
||||
|
||||
<!-- ================================================== SyncPreferences == -->
|
||||
|
||||
<!-- Status Group Label -->
|
||||
<string name="sync_SPr_group_status">Status</string>
|
||||
|
||||
<!-- Sync Status: log in -->
|
||||
<string name="sync_status_loggedout">Not Logged In!</string>
|
||||
<!-- Status: ongoing -->
|
||||
<string name="sync_status_ongoing">Sync Ongoing...</string>
|
||||
<!-- Sync Status: success status (%s -> last sync date). Keep it short!-->
|
||||
<string name="sync_status_success">Last Sync: %s</string>
|
||||
<!-- Sync Status: error status (%s -> last attempted sync date) -->
|
||||
<string name="sync_status_failed">Failed On: %s</string>
|
||||
<!-- Sync Status: error subtitle (%s -> last successful sync date) -->
|
||||
<string name="sync_status_failed_subtitle">Last Successful Sync: %s</string>
|
||||
<!-- Sync Status: never sync'd -->
|
||||
<string name="sync_status_never">Never Synchronized!</string>
|
||||
|
||||
<!-- Options Group Label -->
|
||||
<string name="sync_SPr_group_options">Options</string>
|
||||
|
||||
<!-- Preference: Synchronization Interval Title -->
|
||||
<string name="sync_SPr_interval_title">Background Sync</string>
|
||||
<!-- Preference: Synchronization Interval Description (when disabled) -->
|
||||
<string name="sync_SPr_interval_desc_disabled">Background synchronization is disabled</string>
|
||||
<!-- Preference: Synchronization Interval Description (%s => setting) -->
|
||||
<string name="sync_SPr_interval_desc">Currently set to: %s</string>
|
||||
|
||||
<!-- Preference: Background Wifi Title -->
|
||||
<string name="sync_SPr_bgwifi_title">Wifi Only Setting</string>
|
||||
<!-- Preference: Background Wifi Description (enabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_enabled">Background synchronization only happens when on Wifi</string>
|
||||
<!-- Preference: Background Wifi Description (disabled) -->
|
||||
<string name="sync_SPr_bgwifi_desc_disabled">Background synchronization will always occur</string>
|
||||
|
||||
<!-- Actions Group Label -->
|
||||
<string name="sync_SPr_group_actions">Actions</string>
|
||||
|
||||
<!-- Synchronize Now Button -->
|
||||
<string name="sync_SPr_sync">Synchronize Now!</string>
|
||||
<!-- Synchronize Now Button if not logged in-->
|
||||
<string name="sync_SPr_sync_log_in">Log In & Synchronize!</string>
|
||||
|
||||
<!-- Sync: Clear Data Title -->
|
||||
<string name="sync_SPr_forget">Log Out</string>
|
||||
<!-- Sync: Clear Data Description -->
|
||||
<string name="sync_SPr_forget_description">Clears all synchronization data</string>
|
||||
|
||||
<!-- confirmation dialog for sync log out -->
|
||||
<string name="sync_forget_confirm">Log out / clear synchronization data?</string>
|
||||
|
||||
<string-array name="sync_SPr_interval_entries">
|
||||
<!-- sync_SPr_interval_entries: Synchronization Intervals -->
|
||||
<item>disable</item>
|
||||
<item>every fifteen minutes</item>
|
||||
<item>every thirty minutes</item>
|
||||
<item>every hour</item>
|
||||
<item>every three hours</item>
|
||||
<item>every six hours</item>
|
||||
<item>every twelve hours</item>
|
||||
<item>every day</item>
|
||||
<item>every three days</item>
|
||||
<item>every week</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Todoroo Inc
|
||||
* All Rights Reserved
|
||||
* http://www.todoroo.com
|
||||
*/
|
||||
package com.todoroo.andlib.data;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||
import android.util.Log;
|
||||
|
||||
import com.todoroo.andlib.data.Property.PropertyVisitor;
|
||||
import com.todoroo.andlib.service.Autowired;
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||
import com.todoroo.andlib.service.ExceptionService;
|
||||
import com.todoroo.andlib.utility.AndroidUtilities;
|
||||
|
||||
/**
|
||||
* AbstractDatabase is a database abstraction which wraps a SQLite database.
|
||||
* <p>
|
||||
* Users of this class are in charge of the database's lifecycle - ensuring that
|
||||
* the database is open when needed and closed when usage is finished. Within an
|
||||
* activity, this is typically accomplished through the onResume and onPause
|
||||
* methods, though if the database is not needed for the activity's entire
|
||||
* lifecycle, it can be closed earlier.
|
||||
* <p>
|
||||
* Direct querying is not recommended for type safety reasons. Instead, use one
|
||||
* of the service classes to issue the request and return a {@link TodorooCursor}.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
abstract public class AbstractDatabase {
|
||||
|
||||
// --- abstract methods
|
||||
|
||||
/**
|
||||
* @return database name
|
||||
*/
|
||||
protected abstract String getName();
|
||||
|
||||
/**
|
||||
* @return all tables in this database
|
||||
*/
|
||||
protected abstract Table[] getTables();
|
||||
|
||||
/**
|
||||
* @return database version
|
||||
*/
|
||||
protected abstract int getVersion();
|
||||
|
||||
/**
|
||||
* Called after database and tables are created. Use this method to
|
||||
* create indices and perform other database maintenance
|
||||
*/
|
||||
protected abstract void onCreateTables();
|
||||
|
||||
/**
|
||||
* Upgrades an open database from one version to the next
|
||||
* @param oldVersion
|
||||
* @param newVersion
|
||||
* @return true if upgrade was handled, false otherwise
|
||||
*/
|
||||
protected abstract boolean onUpgrade(int oldVersion, int newVersion);
|
||||
|
||||
// --- protected variables
|
||||
|
||||
/**
|
||||
* SQLiteOpenHelper that takes care of database operations
|
||||
*/
|
||||
protected SQLiteOpenHelper helper = null;
|
||||
|
||||
/**
|
||||
* Internal pointer to open database. Hides the fact that there is a
|
||||
* database and a wrapper by making a single monolithic interface
|
||||
*/
|
||||
protected SQLiteDatabase database = null;
|
||||
|
||||
// --- internal implementation
|
||||
|
||||
@Autowired
|
||||
private ExceptionService exceptionService;
|
||||
|
||||
public AbstractDatabase() {
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the table containing these models
|
||||
* @param modelType
|
||||
* @return
|
||||
*/
|
||||
public final Table getTable(Class<? extends AbstractModel> modelType) {
|
||||
for(Table table : getTables()) {
|
||||
if(table.modelClass.equals(modelType))
|
||||
return table;
|
||||
}
|
||||
throw new UnsupportedOperationException("Unknown model class " + modelType); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
protected synchronized final void initializeHelper() {
|
||||
if(helper == null) {
|
||||
if(ContextManager.getContext() == null)
|
||||
throw new NullPointerException("Null context creating database helper");
|
||||
helper = new DatabaseHelper(ContextManager.getContext(),
|
||||
getName(), null, getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the database for writing. Must be closed afterwards. If user is
|
||||
* out of disk space, database may be opened for reading instead
|
||||
*/
|
||||
public synchronized final void openForWriting() {
|
||||
initializeHelper();
|
||||
|
||||
if(database != null && !database.isReadOnly() && database.isOpen())
|
||||
return;
|
||||
|
||||
try {
|
||||
database = helper.getWritableDatabase();
|
||||
} catch (NullPointerException e) {
|
||||
// don't know why this happens
|
||||
throw new IllegalStateException(e);
|
||||
} catch (final RuntimeException original) {
|
||||
Log.e("database-" + getName(), "Error opening db",
|
||||
original);
|
||||
try {
|
||||
// provide read-only database
|
||||
openForReading();
|
||||
} catch (Exception readException) {
|
||||
exceptionService.reportError("database-open-" + getName(), original);
|
||||
|
||||
// throw original write exception
|
||||
throw original;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the database for reading. Must be closed afterwards
|
||||
*/
|
||||
public synchronized final void openForReading() {
|
||||
initializeHelper();
|
||||
if(database != null && database.isOpen())
|
||||
return;
|
||||
database = helper.getReadableDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the database if it has been opened previously
|
||||
*/
|
||||
public synchronized final void close() {
|
||||
if(database != null) {
|
||||
database.close();
|
||||
}
|
||||
database = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all data in database. Warning: this does what it says. Any open
|
||||
* database resources will be abruptly closed.
|
||||
*/
|
||||
public synchronized final void clear() {
|
||||
close();
|
||||
ContextManager.getContext().deleteDatabase(getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return sql database. opens database if not yet open
|
||||
*/
|
||||
public synchronized final SQLiteDatabase getDatabase() {
|
||||
if(database == null) {
|
||||
AndroidUtilities.sleepDeep(300L);
|
||||
openForWriting();
|
||||
}
|
||||
return database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return human-readable database name for debugging
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DB:" + getName();
|
||||
}
|
||||
|
||||
// --- database wrapper
|
||||
|
||||
/*
|
||||
* @see android.database.sqlite.SQLiteDatabase#rawQuery(String sql, String[] selectionArgs)
|
||||
*/
|
||||
public synchronized Cursor rawQuery(String sql, String[] selectionArgs) {
|
||||
return getDatabase().rawQuery(sql, selectionArgs);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see android.database.sqlite.SQLiteDatabase#insert(String table, String nullColumnHack, ContentValues values)
|
||||
*/
|
||||
public synchronized long insert(String table, String nullColumnHack, ContentValues values) {
|
||||
return getDatabase().insert(table, nullColumnHack, values);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see android.database.sqlite.SQLiteDatabase#delete(String table, String whereClause, String[] whereArgs)
|
||||
*/
|
||||
public synchronized int delete(String table, String whereClause, String[] whereArgs) {
|
||||
return getDatabase().delete(table, whereClause, whereArgs);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see android.database.sqlite.SQLiteDatabase#update(String table, ContentValues values, String whereClause, String[] whereArgs)
|
||||
*/
|
||||
public synchronized int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
|
||||
return getDatabase().update(table, values, whereClause, whereArgs);
|
||||
}
|
||||
|
||||
// --- helper classes
|
||||
|
||||
/**
|
||||
* Default implementation of Astrid database helper
|
||||
*/
|
||||
private class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
public DatabaseHelper(Context context, String name,
|
||||
CursorFactory factory, int version) {
|
||||
super(context, name, factory, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to create the database tables
|
||||
*/
|
||||
@Override
|
||||
public synchronized void onCreate(SQLiteDatabase db) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
SqlConstructorVisitor sqlVisitor = new SqlConstructorVisitor();
|
||||
|
||||
// create tables
|
||||
for(Table table : getTables()) {
|
||||
sql.append("CREATE TABLE IF NOT EXISTS ").append(table.name).append('(').
|
||||
append(AbstractModel.ID_PROPERTY).append(" INTEGER PRIMARY KEY AUTOINCREMENT");
|
||||
for(Property<?> property : table.getProperties()) {
|
||||
if(AbstractModel.ID_PROPERTY.name.equals(property.name))
|
||||
continue;
|
||||
sql.append(',').append(property.accept(sqlVisitor, null));
|
||||
}
|
||||
sql.append(')');
|
||||
db.execSQL(sql.toString());
|
||||
sql.setLength(0);
|
||||
}
|
||||
|
||||
// post-table-creation
|
||||
database = db;
|
||||
onCreateTables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to upgrade the database to a new version
|
||||
*/
|
||||
@Override
|
||||
public synchronized void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w("database-" + getName(), String.format("Upgrading database from version %d to %d.",
|
||||
oldVersion, newVersion));
|
||||
|
||||
database = db;
|
||||
try {
|
||||
if(!AbstractDatabase.this.onUpgrade(oldVersion, newVersion)) {
|
||||
// We don't know how to handle this case because someone forgot to
|
||||
// implement the upgrade. We can't drop tables, we can only
|
||||
// throw a nasty exception at this time
|
||||
|
||||
throw new IllegalStateException("Missing database migration " +
|
||||
"from " + oldVersion + " to " + newVersion);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionService.reportError(String.format("database-upgrade-%s-%d-%d",
|
||||
getName(), oldVersion, newVersion), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visitor that returns SQL constructor for this property
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class SqlConstructorVisitor implements PropertyVisitor<String, Void> {
|
||||
|
||||
public String visitDouble(Property<Double> property, Void data) {
|
||||
return String.format("%s REAL", property.name);
|
||||
}
|
||||
|
||||
public String visitInteger(Property<Integer> property, Void data) {
|
||||
return String.format("%s INTEGER", property.name);
|
||||
}
|
||||
|
||||
public String visitLong(Property<Long> property, Void data) {
|
||||
return String.format("%s INTEGER", property.name);
|
||||
}
|
||||
|
||||
public String visitString(Property<String> property, Void data) {
|
||||
return String.format("%s TEXT", property.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Todoroo Inc
|
||||
* All Rights Reserved
|
||||
* http://www.todoroo.com
|
||||
*/
|
||||
package com.todoroo.andlib.data;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.todoroo.andlib.data.Property.DoubleProperty;
|
||||
import com.todoroo.andlib.data.Property.IntegerProperty;
|
||||
import com.todoroo.andlib.data.Property.LongProperty;
|
||||
import com.todoroo.andlib.data.Property.PropertyVisitor;
|
||||
|
||||
/**
|
||||
* <code>AbstractModel</code> represents a row in a database.
|
||||
* <p>
|
||||
* A single database can be represented by multiple <code>AbstractModel</code>s
|
||||
* corresponding to different queries that return a different set of columns.
|
||||
* Each model exposes a set of properties that it contains.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractModel implements Parcelable {
|
||||
|
||||
// --- static variables
|
||||
|
||||
private static final ContentValuesSavingVisitor saver = new ContentValuesSavingVisitor();
|
||||
|
||||
// --- constants
|
||||
|
||||
/** id property common to all models */
|
||||
protected static final String ID_PROPERTY_NAME = "_id"; //$NON-NLS-1$
|
||||
|
||||
/** id field common to all models */
|
||||
public static final IntegerProperty ID_PROPERTY = new IntegerProperty(null, ID_PROPERTY_NAME);
|
||||
|
||||
/** sentinel for objects without an id */
|
||||
public static final long NO_ID = 0;
|
||||
|
||||
// --- abstract methods
|
||||
|
||||
/** Get the default values for this object */
|
||||
abstract public ContentValues getDefaultValues();
|
||||
|
||||
// --- data store variables and management
|
||||
|
||||
/* Data Source Ordering:
|
||||
*
|
||||
* In order to return the best data, we want to check first what the user
|
||||
* has explicitly set (setValues), then the values we have read out of
|
||||
* the database (values), then defaults (getDefaultValues)
|
||||
*/
|
||||
|
||||
/** User set values */
|
||||
protected ContentValues setValues = null;
|
||||
|
||||
/** Values from database */
|
||||
protected ContentValues values = null;
|
||||
|
||||
/** Get database-read values for this object */
|
||||
public ContentValues getDatabaseValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
/** Get the user-set values for this object */
|
||||
public ContentValues getSetValues() {
|
||||
return setValues;
|
||||
}
|
||||
|
||||
/** Get a list of all field/value pairs merged across data sources */
|
||||
public ContentValues getMergedValues() {
|
||||
ContentValues mergedValues = new ContentValues();
|
||||
|
||||
ContentValues defaultValues = getDefaultValues();
|
||||
if(defaultValues != null)
|
||||
mergedValues.putAll(defaultValues);
|
||||
if(values != null)
|
||||
mergedValues.putAll(values);
|
||||
if(setValues != null)
|
||||
mergedValues.putAll(setValues);
|
||||
|
||||
return mergedValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all data on this model
|
||||
*/
|
||||
public void clear() {
|
||||
values = null;
|
||||
setValues = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers all set values into values. This occurs when a task is
|
||||
* saved - future saves will not need to write all the data as before.
|
||||
*/
|
||||
public void markSaved() {
|
||||
if(values == null)
|
||||
values = setValues;
|
||||
else if(setValues != null)
|
||||
values.putAll(setValues);
|
||||
setValues = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use merged values to compare two models to each other. Must be of
|
||||
* exactly the same class.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if(other == null || other.getClass() != getClass())
|
||||
return false;
|
||||
|
||||
return getMergedValues().equals(((AbstractModel)other).getMergedValues());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getMergedValues().hashCode() ^ getClass().hashCode();
|
||||
}
|
||||
|
||||
// --- data retrieval
|
||||
|
||||
/**
|
||||
* Reads all properties from the supplied cursor and store
|
||||
*/
|
||||
protected synchronized void readPropertiesFromCursor(TodorooCursor<? extends AbstractModel> cursor) {
|
||||
if (values == null)
|
||||
values = new ContentValues();
|
||||
|
||||
// clears user-set values
|
||||
setValues = null;
|
||||
|
||||
for (Property<?> property : cursor.getProperties()) {
|
||||
saver.save(property, values, cursor.get(property));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the given property. Make sure this model has this property!
|
||||
*/
|
||||
public synchronized <TYPE> TYPE getValue(Property<TYPE> property) {
|
||||
Object value;
|
||||
if(setValues != null && setValues.containsKey(property.name))
|
||||
value = setValues.get(property.name);
|
||||
|
||||
else if(values != null && values.containsKey(property.name))
|
||||
value = values.get(property.name);
|
||||
|
||||
else if(getDefaultValues().containsKey(property.name))
|
||||
value = getDefaultValues().get(property.name);
|
||||
|
||||
else
|
||||
throw new UnsupportedOperationException(
|
||||
"Model Error: Did not read property " + property.name); //$NON-NLS-1$
|
||||
|
||||
// resolve properties that were retrieved with a different type than accessed
|
||||
if(value instanceof String && property instanceof LongProperty)
|
||||
return (TYPE) Long.valueOf((String)value);
|
||||
else if(value instanceof String && property instanceof IntegerProperty)
|
||||
return (TYPE) Integer.valueOf((String)value);
|
||||
else if(value instanceof String && property instanceof DoubleProperty)
|
||||
return (TYPE) Double.valueOf((String)value);
|
||||
else if(value instanceof Integer && property instanceof LongProperty)
|
||||
return (TYPE) Long.valueOf(((Number)value).longValue());
|
||||
return (TYPE) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to get the identifier of the model, if it exists.
|
||||
*
|
||||
* @return {@value #NO_ID} if this model was not added to the database
|
||||
*/
|
||||
abstract public long getId();
|
||||
|
||||
protected long getIdHelper(LongProperty id) {
|
||||
if(setValues != null && setValues.containsKey(id.name))
|
||||
return setValues.getAsLong(id.name);
|
||||
else if(values != null && values.containsKey(id.name))
|
||||
return values.getAsLong(id.name);
|
||||
else
|
||||
return NO_ID;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
if (setValues == null)
|
||||
setValues = new ContentValues();
|
||||
|
||||
if(id == NO_ID)
|
||||
setValues.remove(ID_PROPERTY_NAME);
|
||||
else
|
||||
setValues.put(ID_PROPERTY_NAME, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this model has found Jesus (i.e. the database)
|
||||
*/
|
||||
public boolean isSaved() {
|
||||
return getId() != NO_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param property
|
||||
* @return true if setValues or values contains this property
|
||||
*/
|
||||
public boolean containsValue(Property<?> property) {
|
||||
if(setValues != null && setValues.containsKey(property.name))
|
||||
return true;
|
||||
if(values != null && values.containsKey(property.name))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param property
|
||||
* @return true if setValues or values contains this property, and the value
|
||||
* stored is not null
|
||||
*/
|
||||
public boolean containsNonNullValue(Property<?> property) {
|
||||
if(setValues != null && setValues.containsKey(property.name))
|
||||
return setValues.get(property.name) != null;
|
||||
if(values != null && values.containsKey(property.name))
|
||||
return values.get(property.name) != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- data storage
|
||||
|
||||
/**
|
||||
* Check whether the user has changed this property value and it should be
|
||||
* stored for saving in the database
|
||||
*/
|
||||
protected synchronized <TYPE> boolean shouldSaveValue(
|
||||
Property<TYPE> property, TYPE newValue) {
|
||||
|
||||
// we've already decided to save it, so overwrite old value
|
||||
if (setValues.containsKey(property.name))
|
||||
return true;
|
||||
|
||||
// values contains this key, we should check it out
|
||||
if(values != null && values.containsKey(property.name)) {
|
||||
TYPE value = getValue(property);
|
||||
if (value == null) {
|
||||
if (newValue == null)
|
||||
return false;
|
||||
} else if (value.equals(newValue))
|
||||
return false;
|
||||
}
|
||||
|
||||
// otherwise, good to save
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given property. Make sure this model has this property!
|
||||
*/
|
||||
public synchronized <TYPE> void setValue(Property<TYPE> property,
|
||||
TYPE value) {
|
||||
if (setValues == null)
|
||||
setValues = new ContentValues();
|
||||
if (!shouldSaveValue(property, value))
|
||||
return;
|
||||
|
||||
saver.save(property, setValues, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges content values with those coming from another source
|
||||
*/
|
||||
public synchronized <TYPE> void mergeWith(ContentValues other) {
|
||||
if (setValues == null)
|
||||
setValues = new ContentValues();
|
||||
setValues.putAll(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the key for the given property
|
||||
* @param property
|
||||
*/
|
||||
public synchronized void clearValue(Property<?> property) {
|
||||
if(setValues != null && setValues.containsKey(property.name))
|
||||
setValues.remove(property.name);
|
||||
else if(values != null && values.containsKey(property.name))
|
||||
values.remove(property.name);
|
||||
else if(getDefaultValues().containsKey(property.name))
|
||||
throw new IllegalArgumentException("Property has a default value"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// --- property management
|
||||
|
||||
/**
|
||||
* Looks inside the given class and finds all declared properties
|
||||
*/
|
||||
protected static Property<?>[] generateProperties(Class<? extends AbstractModel> cls) {
|
||||
ArrayList<Property<?>> properties = new ArrayList<Property<?>>();
|
||||
if(cls.getSuperclass() != AbstractModel.class)
|
||||
properties.addAll(Arrays.asList(generateProperties(
|
||||
(Class<? extends AbstractModel>) cls.getSuperclass())));
|
||||
|
||||
// a property is public, static & extends Property
|
||||
for(Field field : cls.getFields()) {
|
||||
if((field.getModifiers() & Modifier.STATIC) == 0)
|
||||
continue;
|
||||
if(!Property.class.isAssignableFrom(field.getType()))
|
||||
continue;
|
||||
try {
|
||||
properties.add((Property<?>) field.get(null));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return properties.toArray(new Property<?>[properties.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visitor that saves a value into a content values store
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class ContentValuesSavingVisitor implements PropertyVisitor<Void, Object> {
|
||||
|
||||
private ContentValues store;
|
||||
|
||||
public synchronized void save(Property<?> property, ContentValues newStore, Object value) {
|
||||
this.store = newStore;
|
||||
|
||||
// we don't allow null values, as they indicate unset properties
|
||||
// when the database was written
|
||||
|
||||
if(value != null)
|
||||
property.accept(this, value);
|
||||
}
|
||||
|
||||
public Void visitDouble(Property<Double> property, Object value) {
|
||||
store.put(property.name, (Double) value);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitInteger(Property<Integer> property, Object value) {
|
||||
store.put(property.name, (Integer) value);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitLong(Property<Long> property, Object value) {
|
||||
store.put(property.name, (Long) value);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitString(Property<String> property, Object value) {
|
||||
store.put(property.name, (String) value);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(setValues, 0);
|
||||
dest.writeParcelable(values, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* In addition to overriding this class, model classes should create
|
||||
* a static final variable named "CREATOR" in order to satisfy the
|
||||
* requirements of the Parcelable interface.
|
||||
*/
|
||||
abstract protected Parcelable.Creator<? extends AbstractModel> getCreator();
|
||||
|
||||
/**
|
||||
* Parcelable creator helper
|
||||
*/
|
||||
protected static final class ModelCreator<TYPE extends AbstractModel>
|
||||
implements Parcelable.Creator<TYPE> {
|
||||
|
||||
private final Class<TYPE> cls;
|
||||
|
||||
public ModelCreator(Class<TYPE> cls) {
|
||||
super();
|
||||
this.cls = cls;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TYPE createFromParcel(Parcel source) {
|
||||
TYPE model;
|
||||
try {
|
||||
model = cls.newInstance();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
model.setValues = source.readParcelable(ContentValues.class.getClassLoader());
|
||||
model.values = source.readParcelable(ContentValues.class.getClassLoader());
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TYPE[] newArray(int size) {
|
||||
return (TYPE[]) Array.newInstance(cls, size);
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
package com.todoroo.andlib.data;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.todoroo.andlib.service.Autowired;
|
||||
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
import com.todoroo.andlib.sql.Query;
|
||||
|
||||
|
||||
/**
|
||||
* DAO for reading and writing values from an Android ContentResolver
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
* @param <TYPE> model type
|
||||
*/
|
||||
public class ContentResolverDao<TYPE extends AbstractModel> {
|
||||
|
||||
/** class of model */
|
||||
private final Class<TYPE> modelClass;
|
||||
|
||||
/** base content uri */
|
||||
private final Uri baseUri;
|
||||
|
||||
/** content resolver */
|
||||
private final ContentResolver cr;
|
||||
|
||||
@Autowired
|
||||
protected Boolean debug;
|
||||
|
||||
public ContentResolverDao(Class<TYPE> modelClass, Context context, Uri baseUri) {
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
this.modelClass = modelClass;
|
||||
if(debug == null)
|
||||
debug = false;
|
||||
this.baseUri = baseUri;
|
||||
|
||||
cr = context.getContentResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URI for a single id
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
private Uri uriWithId(long id) {
|
||||
return Uri.withAppendedPath(baseUri, Long.toString(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete specific item from the given table
|
||||
* @param id
|
||||
* @return number of rows affected
|
||||
*/
|
||||
public int delete(long id) {
|
||||
return cr.delete(uriWithId(id), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete by criteria
|
||||
* @param where
|
||||
* @return number of rows affected
|
||||
*/
|
||||
public int deleteWhere(Criterion where) {
|
||||
return cr.delete(baseUri, where.toString(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query content provider
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public TodorooCursor<TYPE> query(Query query) {
|
||||
if(debug)
|
||||
Log.i("SQL-" + modelClass.getSimpleName(), query.toString()); //$NON-NLS-1$
|
||||
Cursor cursor = query.queryContentResolver(cr, baseUri);
|
||||
return new TodorooCursor<TYPE>(cursor, query.getFields());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new or save existing model
|
||||
* @param model
|
||||
* @return true if data was written to the db, false otherwise
|
||||
*/
|
||||
public boolean save(TYPE model) {
|
||||
if(model.isSaved()) {
|
||||
if(model.getSetValues() == null)
|
||||
return false;
|
||||
if(cr.update(uriWithId(model.getId()), model.getSetValues(), null, null) != 0)
|
||||
return true;
|
||||
}
|
||||
Uri uri = cr.insert(baseUri, model.getMergedValues());
|
||||
long id = Long.parseLong(uri.getLastPathSegment());
|
||||
model.setId(id);
|
||||
model.markSaved();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns object corresponding to the given identifier
|
||||
*
|
||||
* @param database
|
||||
* @param table
|
||||
* name of table
|
||||
* @param properties
|
||||
* properties to read
|
||||
* @param id
|
||||
* id of item
|
||||
* @return null if no item found
|
||||
*/
|
||||
public TYPE fetch(long id, Property<?>... properties) {
|
||||
TodorooCursor<TYPE> cursor = query(
|
||||
Query.select(properties).where(AbstractModel.ID_PROPERTY.eq(id)));
|
||||
try {
|
||||
if (cursor.getCount() == 0)
|
||||
return null;
|
||||
cursor.moveToFirst();
|
||||
Constructor<TYPE> constructor = modelClass.getConstructor(TodorooCursor.class);
|
||||
return constructor.newInstance(cursor);
|
||||
} catch (SecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
try {
|
||||
cursor.close();
|
||||
} catch (NullPointerException e) {
|
||||
// cursor was not open
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Todoroo Inc
|
||||
* All Rights Reserved
|
||||
* http://www.todoroo.com
|
||||
*/
|
||||
package com.todoroo.andlib.data;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.util.Log;
|
||||
|
||||
import com.todoroo.andlib.service.Autowired;
|
||||
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
import com.todoroo.andlib.sql.Query;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* DAO for reading data from an instance of {@link AbstractDatabase}. If you
|
||||
* are writing an add-on for Astrid, you probably want to be using a subclass
|
||||
* of {@link ContentResolverDao} instead.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class DatabaseDao<TYPE extends AbstractModel> {
|
||||
|
||||
private final Class<TYPE> modelClass;
|
||||
|
||||
private Table table;
|
||||
|
||||
private AbstractDatabase database;
|
||||
|
||||
@Autowired
|
||||
protected Boolean debug;
|
||||
|
||||
public DatabaseDao(Class<TYPE> modelClass) {
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
this.modelClass = modelClass;
|
||||
if(debug == null)
|
||||
debug = false;
|
||||
}
|
||||
|
||||
public DatabaseDao(Class<TYPE> modelClass, AbstractDatabase database) {
|
||||
this(modelClass);
|
||||
setDatabase(database);
|
||||
}
|
||||
|
||||
/** Gets table associated with this DAO */
|
||||
public Table getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets database accessed by this DAO. Used for dependency-injected
|
||||
* initialization by child classes and unit tests
|
||||
*
|
||||
* @param database
|
||||
*/
|
||||
public void setDatabase(AbstractDatabase database) {
|
||||
if(database == this.database)
|
||||
return;
|
||||
this.database = database;
|
||||
table = database.getTable(modelClass);
|
||||
}
|
||||
|
||||
// --- dao methods
|
||||
|
||||
/**
|
||||
* Construct a query with SQL DSL objects
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public TodorooCursor<TYPE> query(Query query) {
|
||||
query.from(table);
|
||||
if(debug)
|
||||
Log.i("SQL-" + modelClass.getSimpleName(), query.toString()); //$NON-NLS-1$
|
||||
Cursor cursor = database.rawQuery(query.toString(), null);
|
||||
return new TodorooCursor<TYPE>(cursor, query.getFields());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a query with raw SQL
|
||||
*
|
||||
* @param properties
|
||||
* @param selection
|
||||
* @param selectionArgs
|
||||
* @return
|
||||
*/
|
||||
public TodorooCursor<TYPE> rawQuery(String selection, String[] selectionArgs, Property<?>... properties) {
|
||||
String[] fields = new String[properties.length];
|
||||
for(int i = 0; i < properties.length; i++)
|
||||
fields[i] = properties[i].name;
|
||||
return new TodorooCursor<TYPE>(database.getDatabase().query(table.name,
|
||||
fields, selection, selectionArgs, null, null, null),
|
||||
properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns object corresponding to the given identifier
|
||||
*
|
||||
* @param database
|
||||
* @param table
|
||||
* name of table
|
||||
* @param properties
|
||||
* properties to read
|
||||
* @param id
|
||||
* id of item
|
||||
* @return null if no item found
|
||||
*/
|
||||
public TYPE fetch(long id, Property<?>... properties) {
|
||||
TodorooCursor<TYPE> cursor = fetchItem(id, properties);
|
||||
try {
|
||||
if (cursor.getCount() == 0)
|
||||
return null;
|
||||
Constructor<TYPE> constructor = modelClass.getConstructor(TodorooCursor.class);
|
||||
return constructor.newInstance(cursor);
|
||||
} catch (SecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given id
|
||||
*
|
||||
* @param database
|
||||
* @param id
|
||||
* @return true if delete was successful
|
||||
*/
|
||||
public boolean delete(long id) {
|
||||
return database.delete(table.name,
|
||||
AbstractModel.ID_PROPERTY.eq(id).toString(), null) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all matching a clause
|
||||
* @param where predicate for deletion
|
||||
* @return # of deleted items
|
||||
*/
|
||||
public int deleteWhere(Criterion where) {
|
||||
return database.delete(table.name,
|
||||
where.toString(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all matching a clause to have the values set on template object.
|
||||
* <p>
|
||||
* Example (updates "joe" => "bob" in metadata value1):
|
||||
* {code}
|
||||
* Metadata item = new Metadata();
|
||||
* item.setValue(Metadata.VALUE1, "bob");
|
||||
* update(item, Metadata.VALUE1.eq("joe"));
|
||||
* {code}
|
||||
* @param where sql criteria
|
||||
* @param template set fields on this object in order to set them in the db.
|
||||
* @return # of updated items
|
||||
*/
|
||||
public int update(Criterion where, TYPE template) {
|
||||
return database.update(table.name, template.getSetValues(),
|
||||
where.toString(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the given object to the database. Creates a new object if
|
||||
* model id property has not been set
|
||||
*
|
||||
* @return true on success.
|
||||
*/
|
||||
public boolean persist(TYPE item) {
|
||||
if (item.getId() == AbstractModel.NO_ID) {
|
||||
return createNew(item);
|
||||
} else {
|
||||
ContentValues values = item.getSetValues();
|
||||
|
||||
if (values.size() == 0) // nothing changed
|
||||
return true;
|
||||
|
||||
return saveExisting(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the given item.
|
||||
*
|
||||
* @param database
|
||||
* @param table
|
||||
* table name
|
||||
* @param item
|
||||
* item model
|
||||
* @return returns true on success.
|
||||
*/
|
||||
public boolean createNew(TYPE item) {
|
||||
long newRow = database.insert(table.name,
|
||||
AbstractModel.ID_PROPERTY.name, item.getMergedValues());
|
||||
boolean result = newRow >= 0;
|
||||
if(result) {
|
||||
item.markSaved();
|
||||
item.setId(newRow);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the given item. Will not create a new item!
|
||||
*
|
||||
* @param database
|
||||
* @param table
|
||||
* table name
|
||||
* @param item
|
||||
* item model
|
||||
* @return returns true on success.
|
||||
*/
|
||||
public boolean saveExisting(TYPE item) {
|
||||
ContentValues values = item.getSetValues();
|
||||
if(values == null || values.size() == 0) // nothing changed
|
||||
return true;
|
||||
boolean result = database.update(table.name, values,
|
||||
AbstractModel.ID_PROPERTY.eq(item.getId()).toString(), null) > 0;
|
||||
if(result)
|
||||
item.markSaved();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates multiple rows of the database based on model set values
|
||||
*
|
||||
* @param item
|
||||
* item model
|
||||
* @param criterion
|
||||
* @return returns true on success.
|
||||
*/
|
||||
public int updateMultiple(ContentValues values, Criterion criterion) {
|
||||
if(values.size() == 0) // nothing changed
|
||||
return 0;
|
||||
return database.update(table.name, values, criterion.toString(), null);
|
||||
}
|
||||
|
||||
// --- helper methods
|
||||
|
||||
|
||||
/**
|
||||
* Returns cursor to object corresponding to the given identifier
|
||||
*
|
||||
* @param database
|
||||
* @param table
|
||||
* name of table
|
||||
* @param properties
|
||||
* properties to read
|
||||
* @param id
|
||||
* id of item
|
||||
* @return
|
||||
*/
|
||||
protected TodorooCursor<TYPE> fetchItem(long id, Property<?>... properties) {
|
||||
TodorooCursor<TYPE> cursor = query(
|
||||
Query.select(properties).where(AbstractModel.ID_PROPERTY.eq(id)));
|
||||
cursor.moveToFirst();
|
||||
return new TodorooCursor<TYPE>(cursor, properties);
|
||||
}
|
||||
}
|
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Todoroo Inc
|
||||
* All Rights Reserved
|
||||
* http://www.todoroo.com
|
||||
*/
|
||||
package com.todoroo.andlib.data;
|
||||
|
||||
import com.todoroo.andlib.sql.Field;
|
||||
|
||||
/**
|
||||
* Property represents a typed column in a database.
|
||||
*
|
||||
* Within a given database row, the parameter may not exist, in which case the
|
||||
* value is null, it may be of an incorrect type, in which case an exception is
|
||||
* thrown, or the correct type, in which case the value is returned.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
* @param <TYPE>
|
||||
* a database supported type, such as String or Integer
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public abstract class Property<TYPE> extends Field implements Cloneable {
|
||||
|
||||
// --- implementation
|
||||
|
||||
/** The database table name this property */
|
||||
public final Table table;
|
||||
|
||||
/** The database column name for this property */
|
||||
public final String name;
|
||||
|
||||
/**
|
||||
* Create a property by table and column name. Uses the default property
|
||||
* expression which is derived from default table name
|
||||
*/
|
||||
protected Property(Table table, String columnName) {
|
||||
this(table, columnName, (table == null) ? (columnName) : (table.name + "." + columnName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a property by table and column name, manually specifying an
|
||||
* expression to use in SQL
|
||||
*/
|
||||
protected Property(Table table, String columnName, String expression) {
|
||||
super(expression);
|
||||
this.table = table;
|
||||
this.name = columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept a visitor
|
||||
*/
|
||||
abstract public <RETURN, PARAMETER> RETURN accept(
|
||||
PropertyVisitor<RETURN, PARAMETER> visitor, PARAMETER data);
|
||||
|
||||
/**
|
||||
* Return a clone of this property
|
||||
*/
|
||||
@Override
|
||||
public Property<TYPE> clone() {
|
||||
try {
|
||||
return (Property<TYPE>) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// --- helper classes and interfaces
|
||||
|
||||
/**
|
||||
* Visitor interface for property classes
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public interface PropertyVisitor<RETURN, PARAMETER> {
|
||||
public RETURN visitInteger(Property<Integer> property, PARAMETER data);
|
||||
|
||||
public RETURN visitLong(Property<Long> property, PARAMETER data);
|
||||
|
||||
public RETURN visitDouble(Property<Double> property, PARAMETER data);
|
||||
|
||||
public RETURN visitString(Property<String> property, PARAMETER data);
|
||||
}
|
||||
|
||||
// --- children
|
||||
|
||||
/**
|
||||
* Integer property type. See {@link Property}
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class IntegerProperty extends Property<Integer> {
|
||||
|
||||
public IntegerProperty(Table table, String name) {
|
||||
super(table, name);
|
||||
}
|
||||
|
||||
protected IntegerProperty(Table table, String name, String expression) {
|
||||
super(table, name, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <RETURN, PARAMETER> RETURN accept(
|
||||
PropertyVisitor<RETURN, PARAMETER> visitor, PARAMETER data) {
|
||||
return visitor.visitInteger(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String property type. See {@link Property}
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class StringProperty extends Property<String> {
|
||||
|
||||
public StringProperty(Table table, String name) {
|
||||
super(table, name);
|
||||
}
|
||||
|
||||
protected StringProperty(Table table, String name, String expression) {
|
||||
super(table, name, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <RETURN, PARAMETER> RETURN accept(
|
||||
PropertyVisitor<RETURN, PARAMETER> visitor, PARAMETER data) {
|
||||
return visitor.visitString(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Double property type. See {@link Property}
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class DoubleProperty extends Property<Double> {
|
||||
|
||||
public DoubleProperty(Table table, String name) {
|
||||
super(table, name);
|
||||
}
|
||||
|
||||
protected DoubleProperty(Table table, String name, String expression) {
|
||||
super(table, name, expression);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <RETURN, PARAMETER> RETURN accept(
|
||||
PropertyVisitor<RETURN, PARAMETER> visitor, PARAMETER data) {
|
||||
return visitor.visitDouble(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Long property type. See {@link Property}
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class LongProperty extends Property<Long> {
|
||||
|
||||
public LongProperty(Table table, String name) {
|
||||
super(table, name);
|
||||
}
|
||||
|
||||
protected LongProperty(Table table, String name, String expression) {
|
||||
super(table, name, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <RETURN, PARAMETER> RETURN accept(
|
||||
PropertyVisitor<RETURN, PARAMETER> visitor, PARAMETER data) {
|
||||
return visitor.visitLong(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
// --- pseudo-properties
|
||||
|
||||
/** Runs a SQL function and returns the result as a string */
|
||||
public static class StringFunctionProperty extends StringProperty {
|
||||
public StringFunctionProperty(String function, String columnName) {
|
||||
super(null, columnName, function);
|
||||
alias = columnName;
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs a SQL function and returns the result as a string */
|
||||
public static class IntegerFunctionProperty extends IntegerProperty {
|
||||
public IntegerFunctionProperty(String function, String columnName) {
|
||||
super(null, columnName, function);
|
||||
alias = columnName;
|
||||
}
|
||||
}
|
||||
|
||||
/** Counting in aggregated tables. Returns the result of COUNT(1) */
|
||||
public static final class CountProperty extends IntegerFunctionProperty {
|
||||
public CountProperty() {
|
||||
super("COUNT(1)", "count");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.todoroo.andlib.data;
|
||||
|
||||
import com.todoroo.andlib.sql.Field;
|
||||
import com.todoroo.andlib.sql.SqlTable;
|
||||
|
||||
/**
|
||||
* Table class. Most fields are final, so methods such as <code>as</code> will
|
||||
* clone the table when it returns.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public final class Table extends SqlTable {
|
||||
public final String name;
|
||||
public final Class<? extends AbstractModel> modelClass;
|
||||
|
||||
public Table(String name, Class<? extends AbstractModel> modelClass) {
|
||||
this(name, modelClass, null);
|
||||
}
|
||||
|
||||
public Table(String name, Class<? extends AbstractModel> modelClass, String alias) {
|
||||
super(name);
|
||||
this.name = name;
|
||||
this.alias = alias;
|
||||
this.modelClass = modelClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a list of properties from model class by reflection
|
||||
* @return property array
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public Property<?>[] getProperties() {
|
||||
try {
|
||||
return (Property<?>[])modelClass.getField("PROPERTIES").get(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (SecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// --- for sql-dsl
|
||||
|
||||
/**
|
||||
* Create a new join table based on this table, but with an alias
|
||||
*/
|
||||
@Override
|
||||
public Table as(String newAlias) {
|
||||
return new Table(name, modelClass, newAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a field object based on the given property
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public Field field(Property<?> property) {
|
||||
if(alias != null)
|
||||
return Field.field(alias + "." + property.name);
|
||||
return Field.field(name + "." + property.name);
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.andlib.data;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorWrapper;
|
||||
|
||||
import com.todoroo.andlib.data.Property.PropertyVisitor;
|
||||
|
||||
/**
|
||||
* AstridCursor wraps a cursor and allows users to query for individual
|
||||
* {@link Property} types or read an entire {@link AbstractModel} from
|
||||
* a database row.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
* @param <TYPE> a model type that is returned by this cursor
|
||||
*/
|
||||
public class TodorooCursor<TYPE extends AbstractModel> extends CursorWrapper {
|
||||
|
||||
/** Properties read by this cursor */
|
||||
private final Property<?>[] properties;
|
||||
|
||||
/** Weakly cache field name to column id references for this cursor.
|
||||
* Because it's a weak hash map, entire keys can be discarded by GC */
|
||||
private final WeakHashMap<String, Integer> columnIndexCache;
|
||||
|
||||
/** Property reading visitor */
|
||||
private static final CursorReadingVisitor reader = new CursorReadingVisitor();
|
||||
|
||||
/**
|
||||
* Create an <code>AstridCursor</code> from the supplied {@link Cursor}
|
||||
* object.
|
||||
*
|
||||
* @param cursor
|
||||
* @param properties properties read from this cursor
|
||||
*/
|
||||
public TodorooCursor(Cursor cursor, Property<?>[] properties) {
|
||||
super(cursor);
|
||||
|
||||
this.properties = properties;
|
||||
columnIndexCache = new WeakHashMap<String, Integer>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for the given property on the underlying {@link Cursor}
|
||||
*
|
||||
* @param <PROPERTY_TYPE> type to return
|
||||
* @param property to retrieve
|
||||
* @return
|
||||
*/
|
||||
public <PROPERTY_TYPE> PROPERTY_TYPE get(Property<PROPERTY_TYPE> property) {
|
||||
return (PROPERTY_TYPE)property.accept(reader, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets entire property list
|
||||
* @return
|
||||
*/
|
||||
public Property<?>[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use cache to get the column index for the given field name
|
||||
*/
|
||||
public synchronized int getColumnIndexFromCache(String field) {
|
||||
Integer index = columnIndexCache.get(field);
|
||||
if(index == null) {
|
||||
index = getColumnIndexOrThrow(field);
|
||||
columnIndexCache.put(field, index);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visitor that reads the given property from a cursor
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class CursorReadingVisitor implements PropertyVisitor<Object, TodorooCursor<?>> {
|
||||
|
||||
public Object visitDouble(Property<Double> property,
|
||||
TodorooCursor<?> cursor) {
|
||||
return cursor.getDouble(cursor.getColumnIndexFromCache(property.name));
|
||||
}
|
||||
|
||||
public Object visitInteger(Property<Integer> property,
|
||||
TodorooCursor<?> cursor) {
|
||||
return cursor.getInt(cursor.getColumnIndexFromCache(property.name));
|
||||
}
|
||||
|
||||
public Object visitLong(Property<Long> property, TodorooCursor<?> cursor) {
|
||||
return cursor.getLong(cursor.getColumnIndexFromCache(property.name));
|
||||
}
|
||||
|
||||
public Object visitString(Property<String> property,
|
||||
TodorooCursor<?> cursor) {
|
||||
return cursor.getString(cursor.getColumnIndexFromCache(property.name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Todoroo Library classes for the data layer: accessing data from a database or
|
||||
* {@link ContentResolver}
|
||||
*/
|
||||
package com.todoroo.andlib.data;
|
@ -0,0 +1,100 @@
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.todoroo.andlib.service.ExceptionService.ErrorReporter;
|
||||
|
||||
/**
|
||||
* A Dependency Injector knows how to inject certain dependencies based
|
||||
* on the field that is passed in. You will need to write your own initialization
|
||||
* code to insert this dependency injector into the DI chain.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
abstract public class AbstractDependencyInjector {
|
||||
|
||||
/**
|
||||
* Initialize list of injection variables. Special care must used when
|
||||
* instantiating classes that themselves depend on dependency injection
|
||||
* (i.e. {@link ErrorReporter}.
|
||||
*/
|
||||
protected void addInjectables() {
|
||||
// your injectables here
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
protected AbstractDependencyInjector() {
|
||||
addInjectables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependencies this class knows how to handle
|
||||
*/
|
||||
protected final HashMap<String, Object> injectables = new HashMap<String, Object>();
|
||||
|
||||
/**
|
||||
* Cache of classes that were instantiated by the injector
|
||||
*/
|
||||
protected final HashMap<Class<?>, WeakReference<Object>> createdObjects =
|
||||
new HashMap<Class<?>, WeakReference<Object>>();
|
||||
|
||||
/**
|
||||
* Gets the injected object for this field. If implementing class does not
|
||||
* know how to handle this dependency, it should return null
|
||||
*
|
||||
* @param object
|
||||
* object to perform dependency injection on
|
||||
* @param field
|
||||
* field tagged with {link Autowired} annotation
|
||||
* @return object to assign to this field, or null
|
||||
*/
|
||||
public Object getInjection(Object object, Field field) {
|
||||
if(injectables.containsKey(field.getName())) {
|
||||
Object injection = injectables.get(field.getName());
|
||||
|
||||
// if it's a class, instantiate the class
|
||||
if(injection instanceof Class<?>) {
|
||||
if(createdObjects.containsKey(injection) &&
|
||||
createdObjects.get(injection).get() != null) {
|
||||
injection = createdObjects.get(injection).get();
|
||||
} else {
|
||||
Class<?> cls = (Class<?>)injection;
|
||||
try {
|
||||
injection = cls.newInstance();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
createdObjects.put(cls,
|
||||
new WeakReference<Object>(injection));
|
||||
}
|
||||
}
|
||||
|
||||
return injection;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush dependency injection cache. Useful for unit tests.
|
||||
*/
|
||||
protected void flushCreated() {
|
||||
createdObjects.clear();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Autowired is an annotation that tells the dependency injector to
|
||||
* set up the class as appropriate.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Autowired {
|
||||
//
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
/**
|
||||
* Singleton class to manage current application context
|
||||
* b
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public final class ContextManager {
|
||||
|
||||
/**
|
||||
* Global application context
|
||||
*/
|
||||
private static Context context = null;
|
||||
|
||||
/**
|
||||
* Sets the global context
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static void setContext(Context context) {
|
||||
if(context == null || context.getApplicationContext() == null)
|
||||
return;
|
||||
if(ContextManager.context != null && !(context instanceof Activity))
|
||||
return;
|
||||
ContextManager.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the global context
|
||||
*/
|
||||
public static Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to read a string from the resources
|
||||
*
|
||||
* @param resId resource
|
||||
* @param parameters % arguments
|
||||
* @return resource string
|
||||
*/
|
||||
public static String getString(int resId, Object... formatArgs) {
|
||||
return context.getString(resId, formatArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to read resources
|
||||
*
|
||||
* @return resources object
|
||||
*/
|
||||
public static Resources getResources() {
|
||||
return context.getResources();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.LinkedList;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simple Dependency Injection Service for Android.
|
||||
* <p>
|
||||
* Add dependency injectors to the injector chain, then invoke this method
|
||||
* against classes you wish to perform dependency injection for.
|
||||
* <p>
|
||||
* All errors encountered are handled as warnings, so if dependency injection
|
||||
* seems to be failing, check the logs for more information.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class DependencyInjectionService {
|
||||
|
||||
/**
|
||||
* Dependency injectors. Use getters and setters to modify this list
|
||||
*/
|
||||
private final LinkedList<AbstractDependencyInjector> injectors = new LinkedList<AbstractDependencyInjector>();
|
||||
|
||||
/**
|
||||
* Perform dependency injection in the caller object
|
||||
*
|
||||
* @param caller
|
||||
* object to perform DI on
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public void inject(Object caller) {
|
||||
// Traverse through class and all parent classes, looking for
|
||||
// fields declared with the @Autowired annotation and using
|
||||
// dependency injection to set them as appropriate
|
||||
|
||||
Class<?> cls = caller.getClass();
|
||||
while(cls != null) {
|
||||
String packageName = cls.getPackage().getName();
|
||||
if(!isQualifiedPackage(packageName))
|
||||
break;
|
||||
|
||||
for(Field field : cls.getDeclaredFields()) {
|
||||
if(field.getAnnotation(Autowired.class) != null) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
handleField(caller, field);
|
||||
} catch (IllegalStateException e) {
|
||||
throw new RuntimeException(String.format("Unable to set field '%s' of type '%s'",
|
||||
field.getName(), field.getType()), e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(String.format("Unable to set field '%s' of type '%s'",
|
||||
field.getName(), field.getType()), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(String.format("Unable to set field '%s' of type '%s'",
|
||||
field.getName(), field.getType()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cls = cls.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
private boolean isQualifiedPackage(String packageName) {
|
||||
if(packageName.startsWith("com.todoroo"))
|
||||
return true;
|
||||
if(packageName.startsWith("com.timsu"))
|
||||
return true;
|
||||
if(packageName.startsWith("org.weloveastrid"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the appropriate dependency object based on the type
|
||||
* that this autowired field accepts
|
||||
*
|
||||
* @param caller
|
||||
* calling object
|
||||
* @param field
|
||||
* field to inject
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
private synchronized void handleField(Object caller, Field field)
|
||||
throws IllegalStateException, IllegalArgumentException,
|
||||
IllegalAccessException {
|
||||
|
||||
if(field.getType().isPrimitive())
|
||||
throw new IllegalStateException(String.format(
|
||||
"Tried to dependency-inject primative field '%s' of type '%s'",
|
||||
field.getName(), field.getType()));
|
||||
|
||||
// field has already been processed, ignore
|
||||
if (field.get(caller) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (AbstractDependencyInjector injector : injectors) {
|
||||
Object injection = injector.getInjection(caller, field);
|
||||
if (injection != null) {
|
||||
field.set(caller, injection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException(
|
||||
String.format("No dependency injector found for autowired " +
|
||||
"field '%s' in class '%s'. Injectors: %s",
|
||||
field.getName(), caller.getClass().getName(),
|
||||
injectors));
|
||||
}
|
||||
|
||||
// --- default dependency injector
|
||||
|
||||
private class DefaultDependencyInjector extends AbstractDependencyInjector {
|
||||
@SuppressWarnings("nls")
|
||||
@Override
|
||||
protected void addInjectables() {
|
||||
injectables.put("debug", false);
|
||||
injectables.put("exceptionService", ExceptionService.class);
|
||||
}
|
||||
}
|
||||
|
||||
// --- static methods
|
||||
|
||||
private static DependencyInjectionService instance = null;
|
||||
|
||||
DependencyInjectionService() {
|
||||
// prevent instantiation
|
||||
injectors.add(new DefaultDependencyInjector());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the singleton instance of the dependency injection service.
|
||||
* @return
|
||||
*/
|
||||
public synchronized static DependencyInjectionService getInstance() {
|
||||
if(instance == null)
|
||||
instance = new DependencyInjectionService();
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the supplied injector
|
||||
* @return
|
||||
*/
|
||||
public synchronized void removeInjector(AbstractDependencyInjector injector) {
|
||||
injectors.remove(injector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Dependency Injector to the front of the list
|
||||
* @param injectors
|
||||
*/
|
||||
public synchronized void addInjector(AbstractDependencyInjector injector) {
|
||||
removeInjector(injector);
|
||||
|
||||
this.injectors.addFirst(injector);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.todoroo.astrid.api.R;
|
||||
|
||||
/**
|
||||
* Exception handling utility class - reports and logs errors
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class ExceptionService {
|
||||
|
||||
@Autowired
|
||||
public ErrorReporter[] errorReporters;
|
||||
|
||||
public ExceptionService() {
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
if(errorReporters == null) {
|
||||
errorReporters = new ErrorReporter[] {
|
||||
new AndroidLogReporter()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report the error via registered error handlers
|
||||
*
|
||||
* @param name Internal error name. Not displayed to user
|
||||
* @param error Exception encountered. Message will be displayed to user
|
||||
*/
|
||||
public void reportError(String name, Throwable error) {
|
||||
if(errorReporters == null)
|
||||
return;
|
||||
|
||||
for(ErrorReporter reporter : errorReporters) {
|
||||
try {
|
||||
reporter.handleError(name, error);
|
||||
} catch (Exception e) {
|
||||
Log.e("astrid-exception-service", "Exception handling error", e); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display error dialog if context is activity and report error
|
||||
*
|
||||
* @param context Application Context
|
||||
* @param name Internal error name. Not displayed to user
|
||||
* @param error Exception encountered. Message will be displayed to user
|
||||
*/
|
||||
public void displayAndReportError(final Context context, String name, Throwable error) {
|
||||
if(context instanceof Activity) {
|
||||
final String messageToDisplay;
|
||||
|
||||
// pretty up the message when displaying to user
|
||||
if(error == null)
|
||||
messageToDisplay = context.getString(R.string.DLG_error_generic);
|
||||
else
|
||||
messageToDisplay = context.getString(R.string.DLG_error, error);
|
||||
|
||||
((Activity)context).runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.DLG_error_title)
|
||||
.setMessage(messageToDisplay)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
} catch (Exception e) {
|
||||
// suppress errors during dialog creation
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reportError(name, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Error reporter interface
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public interface ErrorReporter {
|
||||
public void handleError(String name, Throwable error);
|
||||
}
|
||||
|
||||
/**
|
||||
* AndroidLogReporter reports errors to LogCat
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class AndroidLogReporter implements ErrorReporter {
|
||||
|
||||
/**
|
||||
* Report the error to the logs
|
||||
*
|
||||
* @param name
|
||||
* @param error
|
||||
*/
|
||||
public void handleError(String name, Throwable error) {
|
||||
String tag = null;
|
||||
if(ContextManager.getContext() != null) {
|
||||
PackageManager pm = ContextManager.getContext().getPackageManager();
|
||||
try {
|
||||
String appName = pm.getApplicationInfo(ContextManager.getContext().
|
||||
getPackageName(), 0).loadLabel(pm).toString();
|
||||
tag = appName + "-" + name; //$NON-NLS-1$
|
||||
} catch (NameNotFoundException e) {
|
||||
// give up
|
||||
}
|
||||
}
|
||||
|
||||
if(tag == null)
|
||||
tag = "unknown-" + name; //$NON-NLS-1$
|
||||
|
||||
if(error == null)
|
||||
Log.e(tag, "Exception: " + name); //$NON-NLS-1$
|
||||
else
|
||||
Log.e(tag, error.toString(), error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uncaught exception handler uses the exception utilities class to
|
||||
* report errors
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class TodorooUncaughtExceptionHandler implements UncaughtExceptionHandler {
|
||||
private final UncaughtExceptionHandler defaultUEH;
|
||||
|
||||
@Autowired
|
||||
protected ExceptionService exceptionService;
|
||||
|
||||
public TodorooUncaughtExceptionHandler() {
|
||||
defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
}
|
||||
|
||||
public void uncaughtException(Thread thread, Throwable ex) {
|
||||
if(exceptionService != null)
|
||||
exceptionService.reportError("uncaught", ex); //$NON-NLS-1$
|
||||
defaultUEH.uncaughtException(thread, ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class HttpErrorException extends IOException {
|
||||
|
||||
private static final long serialVersionUID = 5373340422464657279L;
|
||||
|
||||
public HttpErrorException(int code, String message) {
|
||||
super(String.format("%d %s", code, message)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* RestClient allows Android to consume web requests.
|
||||
* <p>
|
||||
* Portions by Praeda:
|
||||
* http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple
|
||||
* -restful-client-at-android/
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class HttpRestClient implements RestClient {
|
||||
|
||||
private static final int HTTP_UNAVAILABLE_END = 599;
|
||||
private static final int HTTP_UNAVAILABLE_START = 500;
|
||||
private static final int HTTP_OK = 200;
|
||||
|
||||
private static final int TIMEOUT_MILLIS = 30000;
|
||||
|
||||
private static WeakReference<HttpClient> httpClient = null;
|
||||
|
||||
protected boolean debug = false;
|
||||
|
||||
public HttpRestClient() {
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
}
|
||||
|
||||
private static String convertStreamToString(InputStream is) {
|
||||
/*
|
||||
* To convert the InputStream to String we use the
|
||||
* BufferedReader.readLine() method. We iterate until the BufferedReader
|
||||
* return null which means there's no more data to read. Each line will
|
||||
* appended to a StringBuilder and returned as String.
|
||||
*/
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is), 16384);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
String line = null;
|
||||
try {
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line + "\n"); //$NON-NLS-1$
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private synchronized static HttpClient getClient() {
|
||||
if (httpClient == null || httpClient.get() == null) {
|
||||
HttpParams params = new BasicHttpParams();
|
||||
HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_MILLIS);
|
||||
HttpConnectionParams.setSoTimeout(params, TIMEOUT_MILLIS);
|
||||
HttpClient client = new DefaultHttpClient(params);
|
||||
httpClient = new WeakReference<HttpClient>(client);
|
||||
return client;
|
||||
} else {
|
||||
return httpClient.get();
|
||||
}
|
||||
}
|
||||
|
||||
private String processHttpResponse(HttpResponse response) throws IOException {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if(statusCode >= HTTP_UNAVAILABLE_START && statusCode <= HTTP_UNAVAILABLE_END) {
|
||||
throw new HttpUnavailableException();
|
||||
} else if(statusCode != HTTP_OK) {
|
||||
throw new HttpErrorException(response.getStatusLine().getStatusCode(),
|
||||
response.getStatusLine().getReasonPhrase());
|
||||
}
|
||||
|
||||
HttpEntity entity = response.getEntity();
|
||||
|
||||
if (entity != null) {
|
||||
InputStream contentStream = entity.getContent();
|
||||
try {
|
||||
return convertStreamToString(contentStream);
|
||||
} finally {
|
||||
contentStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue an HTTP GET for the given URL, return the response
|
||||
*
|
||||
* @param url url with url-encoded params
|
||||
* @return response, or null if there was no response
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized String get(String url) throws IOException {
|
||||
if(debug)
|
||||
Log.d("http-rest-client-get", url); //$NON-NLS-1$
|
||||
|
||||
try {
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
HttpResponse response = getClient().execute(httpGet);
|
||||
|
||||
return processHttpResponse(response);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
IOException ioException = new IOException(e.getMessage());
|
||||
ioException.initCause(e);
|
||||
throw ioException;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue an HTTP POST for the given URL, return the response
|
||||
*
|
||||
* @param url
|
||||
* @param data
|
||||
* url-encoded data
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized String post(String url, String data) throws IOException {
|
||||
if(debug)
|
||||
Log.d("http-rest-client-post", url + " | " + data); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
try {
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
httpPost.setEntity(new StringEntity(data));
|
||||
HttpResponse response = getClient().execute(httpPost);
|
||||
|
||||
return processHttpResponse(response);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
IOException ioException = new IOException(e.getMessage());
|
||||
ioException.initCause(e);
|
||||
throw ioException;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Exception displayed when a 500 error is received on an HTTP invocation
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class HttpUnavailableException extends IOException {
|
||||
|
||||
private static final long serialVersionUID = 5373340422464657279L;
|
||||
|
||||
public HttpUnavailableException() {
|
||||
super();
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Sorry, our servers are experiencing some issues. Please try again later!"; //$NON-NLS-1$ // FIXME
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Notification Manager stub
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public interface NotificationManager {
|
||||
|
||||
public void cancel(int id);
|
||||
|
||||
public void cancelAll();
|
||||
|
||||
public void notify(int id, Notification notification);
|
||||
|
||||
/**
|
||||
* Instantiation of notification manager that passes through to
|
||||
* Android's notification manager
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public static class AndroidNotificationManager implements NotificationManager {
|
||||
private final android.app.NotificationManager nm;
|
||||
public AndroidNotificationManager(Context context) {
|
||||
nm = (android.app.NotificationManager)
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
public void cancel(int id) {
|
||||
nm.cancel(id);
|
||||
}
|
||||
|
||||
public void cancelAll() {
|
||||
nm.cancelAll();
|
||||
}
|
||||
|
||||
public void notify(int id, Notification notification) {
|
||||
nm.notify(id, notification);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.todoroo.andlib.service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* RestClient stub invokes the HTML requests as desired
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public interface RestClient {
|
||||
public String get(String url) throws IOException;
|
||||
public String post(String url, String data) throws IOException;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Todoroo Library classes for the service layer: dependency injection,
|
||||
* exceptions, HTTP requests, etc.
|
||||
*/
|
||||
package com.todoroo.andlib.service;
|
@ -0,0 +1,89 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.AND;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.EXISTS;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.LEFT_PARENTHESIS;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.NOT;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.OR;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.RIGHT_PARENTHESIS;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
|
||||
public abstract class Criterion {
|
||||
protected final Operator operator;
|
||||
|
||||
Criterion(Operator operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
public static Criterion all = new Criterion(Operator.exists) {
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(1);
|
||||
}
|
||||
};
|
||||
|
||||
public static Criterion none = new Criterion(Operator.exists) {
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(0);
|
||||
}
|
||||
};
|
||||
|
||||
public static Criterion and(final Criterion criterion, final Criterion... criterions) {
|
||||
return new Criterion(Operator.and) {
|
||||
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(criterion);
|
||||
for (Criterion c : criterions) {
|
||||
sb.append(SPACE).append(AND).append(SPACE).append(c);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Criterion or(final Criterion criterion, final Criterion... criterions) {
|
||||
return new Criterion(Operator.or) {
|
||||
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(criterion);
|
||||
for (Criterion c : criterions) {
|
||||
sb.append(SPACE).append(OR).append(SPACE).append(c.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Criterion exists(final Query query) {
|
||||
return new Criterion(Operator.exists) {
|
||||
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(EXISTS).append(SPACE).append(LEFT_PARENTHESIS).append(query).append(RIGHT_PARENTHESIS);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Criterion not(final Criterion criterion) {
|
||||
return new Criterion(Operator.not) {
|
||||
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(NOT).append(SPACE);
|
||||
criterion.populate(sb);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract void populate(StringBuilder sb);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder(LEFT_PARENTHESIS);
|
||||
populate(builder);
|
||||
builder.append(RIGHT_PARENTHESIS);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.AS;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
|
||||
public abstract class DBObject<T extends DBObject<?>> implements Cloneable {
|
||||
protected String alias;
|
||||
protected final String expression;
|
||||
|
||||
protected DBObject(String expression){
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public T as(String newAlias) {
|
||||
try {
|
||||
T clone = (T) clone();
|
||||
clone.alias = newAlias;
|
||||
return clone;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasAlias() {
|
||||
return alias != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
DBObject<?> dbObject = (DBObject<?>) o;
|
||||
|
||||
if (alias != null ? !alias.equals(dbObject.alias) : dbObject.alias != null) return false;
|
||||
if (expression != null ? !expression.equals(dbObject.expression) : dbObject.expression != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = alias != null ? alias.hashCode() : 0;
|
||||
result = 31 * result + (expression != null ? expression.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
if (hasAlias()) {
|
||||
return alias;
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
public final String toStringInSelect() {
|
||||
StringBuilder sb = new StringBuilder(expression);
|
||||
if (hasAlias()) {
|
||||
sb.append(SPACE).append(AS).append(SPACE).append(alias);
|
||||
} else {
|
||||
int pos = expression.indexOf('.');
|
||||
if(pos > 0)
|
||||
sb.append(SPACE).append(AS).append(SPACE).append(expression.substring(pos + 1));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
public class EqCriterion extends UnaryCriterion {
|
||||
EqCriterion(Field field, Object value) {
|
||||
super(field, Operator.eq, value);
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.AND;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.BETWEEN;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.COMMA;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.LEFT_PARENTHESIS;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.RIGHT_PARENTHESIS;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
|
||||
public class Field extends DBObject<Field> {
|
||||
|
||||
protected Field(String expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
public static Field field(String expression) {
|
||||
return new Field(expression);
|
||||
}
|
||||
|
||||
public Criterion eq(Object value) {
|
||||
if(value == null)
|
||||
return UnaryCriterion.isNull(this);
|
||||
return UnaryCriterion.eq(this, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the criterion that the field must be equal to the given string, ignoring case.
|
||||
*
|
||||
* Thanks to a sqlite bug, this will only work for ASCII values.
|
||||
*
|
||||
* @param value string which field must equal
|
||||
* @return the criterion
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public Criterion eqCaseInsensitive(String value) {
|
||||
String escaped = value.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_");
|
||||
return UnaryCriterion.like(this, escaped, "\\");
|
||||
}
|
||||
|
||||
public Criterion neq(Object value) {
|
||||
if(value == null)
|
||||
return UnaryCriterion.isNotNull(this);
|
||||
return UnaryCriterion.neq(this, value);
|
||||
}
|
||||
|
||||
public Criterion gt(Object value) {
|
||||
return UnaryCriterion.gt(this, value);
|
||||
}
|
||||
|
||||
public Criterion lt(final Object value) {
|
||||
return UnaryCriterion.lt(this, value);
|
||||
}
|
||||
|
||||
public Criterion lte(final Object value) {
|
||||
return UnaryCriterion.lte(this, value);
|
||||
}
|
||||
|
||||
public Criterion isNull() {
|
||||
return UnaryCriterion.isNull(this);
|
||||
}
|
||||
|
||||
public Criterion isNotNull() {
|
||||
return UnaryCriterion.isNotNull(this);
|
||||
}
|
||||
|
||||
public Criterion between(final Object lower, final Object upper) {
|
||||
final Field field = this;
|
||||
return new Criterion(null) {
|
||||
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(field).append(SPACE).append(BETWEEN).append(SPACE).append(lower).append(SPACE).append(AND)
|
||||
.append(SPACE).append(upper);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Criterion like(final String value) {
|
||||
return UnaryCriterion.like(this, value);
|
||||
}
|
||||
|
||||
public Criterion like(String value, String escape) {
|
||||
return UnaryCriterion.like(this, value, escape);
|
||||
}
|
||||
|
||||
public <T> Criterion in(final T... value) {
|
||||
final Field field = this;
|
||||
return new Criterion(Operator.in) {
|
||||
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(field).append(SPACE).append(Operator.in).append(SPACE).append(LEFT_PARENTHESIS).append(SPACE);
|
||||
for (T t : value) {
|
||||
sb.append(t.toString()).append(COMMA);
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1).append(RIGHT_PARENTHESIS);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Criterion in(final Query query) {
|
||||
final Field field = this;
|
||||
return new Criterion(Operator.in) {
|
||||
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
sb.append(field).append(SPACE).append(Operator.in).append(SPACE).append(LEFT_PARENTHESIS).append(query)
|
||||
.append(RIGHT_PARENTHESIS);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public final class Functions {
|
||||
|
||||
public static String caseStatement(Criterion when, Object ifTrue, Object ifFalse) {
|
||||
return new StringBuilder("(CASE WHEN ").
|
||||
append(when.toString()).append(" THEN ").append(value(ifTrue)).
|
||||
append(" ELSE ").append(value(ifFalse)).append(" END)").toString();
|
||||
}
|
||||
|
||||
private static String value(Object value) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
public static Field upper(Field title) {
|
||||
return new Field("UPPER(" + title.toString() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SQL now (in milliseconds)
|
||||
*/
|
||||
public static Field now() {
|
||||
return new Field("(strftime('%s','now')*1000)");
|
||||
}
|
||||
|
||||
public static Field cast(Field field, String newType) {
|
||||
return new Field("CAST(" + field.toString() + " AS " +
|
||||
newType + ")");
|
||||
}
|
||||
|
||||
public static Field max(Field field) {
|
||||
return new Field("MAX(" + field.toString() + ")");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GroupBy {
|
||||
private List<Field> fields = new ArrayList<Field>();
|
||||
|
||||
public static GroupBy groupBy(Field field) {
|
||||
GroupBy groupBy = new GroupBy();
|
||||
groupBy.fields.add(field);
|
||||
return groupBy;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.JOIN;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.ON;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
|
||||
public class Join {
|
||||
private final SqlTable joinTable;
|
||||
private final JoinType joinType;
|
||||
private final Criterion[] criterions;
|
||||
|
||||
private Join(SqlTable table, JoinType joinType, Criterion... criterions) {
|
||||
joinTable = table;
|
||||
this.joinType = joinType;
|
||||
this.criterions = criterions;
|
||||
}
|
||||
|
||||
public static Join inner(SqlTable expression, Criterion... criterions) {
|
||||
return new Join(expression, JoinType.INNER, criterions);
|
||||
}
|
||||
|
||||
public static Join left(SqlTable table, Criterion... criterions) {
|
||||
return new Join(table, JoinType.LEFT, criterions);
|
||||
}
|
||||
|
||||
public static Join right(SqlTable table, Criterion... criterions) {
|
||||
return new Join(table, JoinType.RIGHT, criterions);
|
||||
}
|
||||
|
||||
public static Join out(SqlTable table, Criterion... criterions) {
|
||||
return new Join(table, JoinType.OUT, criterions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(joinType).append(SPACE).append(JOIN).append(SPACE).append(joinTable).append(SPACE).append(ON);
|
||||
for (Criterion criterion : criterions) {
|
||||
sb.append(SPACE).append(criterion);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
public enum JoinType {
|
||||
INNER, LEFT, RIGHT, OUT
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public final class Operator {
|
||||
|
||||
private final String operator;
|
||||
public static final Operator eq = new Operator("=");
|
||||
public static final Operator neq = new Operator("<>");
|
||||
public static final Operator isNull = new Operator("IS NULL");
|
||||
public static final Operator isNotNull = new Operator("IS NOT NULL");
|
||||
public static final Operator gt = new Operator(">");
|
||||
public static final Operator lt = new Operator("<");
|
||||
public static final Operator gte = new Operator(">=");
|
||||
public static final Operator lte = new Operator("<=");
|
||||
public static final Operator and = new Operator("AND");
|
||||
public static final Operator or = new Operator("OR");
|
||||
public static final Operator not = new Operator("NOT");
|
||||
public static final Operator exists = new Operator("EXISTS");
|
||||
public static final Operator like = new Operator("LIKE");
|
||||
public static final Operator in = new Operator("IN");
|
||||
|
||||
private static final Map<Operator, Operator> contraryRegistry = new HashMap<Operator, Operator>();
|
||||
|
||||
static {
|
||||
contraryRegistry.put(eq, neq);
|
||||
contraryRegistry.put(neq, eq);
|
||||
contraryRegistry.put(isNull, isNotNull);
|
||||
contraryRegistry.put(isNotNull, isNull);
|
||||
contraryRegistry.put(gt, lte);
|
||||
contraryRegistry.put(lte, gt);
|
||||
contraryRegistry.put(lt, gte);
|
||||
contraryRegistry.put(gte, lt);
|
||||
}
|
||||
|
||||
private Operator(String operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
public Operator getContrary() {
|
||||
if(!contraryRegistry.containsKey(this)){
|
||||
Operator opposite = new Operator(not.toString() + SPACE + this.toString());
|
||||
contraryRegistry.put(this, opposite);
|
||||
contraryRegistry.put(opposite, this);
|
||||
}
|
||||
return contraryRegistry.get(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.operator.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
|
||||
public class Order {
|
||||
private final Object expression;
|
||||
private final OrderType orderType;
|
||||
|
||||
private Order(Object expression) {
|
||||
this(expression, OrderType.ASC);
|
||||
}
|
||||
|
||||
private Order(Object expression, OrderType orderType) {
|
||||
this.expression = expression;
|
||||
this.orderType = orderType;
|
||||
}
|
||||
|
||||
public static Order asc(Object expression) {
|
||||
return new Order(expression);
|
||||
}
|
||||
|
||||
public static Order desc(Object expression) {
|
||||
return new Order(expression, OrderType.DESC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return expression + SPACE + orderType;
|
||||
}
|
||||
|
||||
public Order reverse() {
|
||||
if(orderType == OrderType.ASC)
|
||||
return new Order(expression, OrderType.DESC);
|
||||
else
|
||||
return new Order(expression, OrderType.ASC);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
public enum OrderType {
|
||||
DESC, ASC
|
||||
}
|
@ -0,0 +1,296 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.ALL;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.COMMA;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.DISTINCT;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.FROM;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.GROUP_BY;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.LEFT_PARENTHESIS;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.LIMIT;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.ORDER_BY;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.RIGHT_PARENTHESIS;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SELECT;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.WHERE;
|
||||
import static com.todoroo.andlib.sql.SqlTable.table;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.todoroo.andlib.data.Property;
|
||||
import com.todoroo.astrid.api.AstridApiConstants;
|
||||
|
||||
public final class Query {
|
||||
|
||||
private SqlTable table;
|
||||
private String queryTemplate = null;
|
||||
private final ArrayList<Criterion> criterions = new ArrayList<Criterion>();
|
||||
private final ArrayList<Field> fields = new ArrayList<Field>();
|
||||
private final ArrayList<Join> joins = new ArrayList<Join>();
|
||||
private final ArrayList<Field> groupBies = new ArrayList<Field>();
|
||||
private final ArrayList<Order> orders = new ArrayList<Order>();
|
||||
private final ArrayList<Criterion> havings = new ArrayList<Criterion>();
|
||||
private int limits = -1;
|
||||
private boolean distinct = false;
|
||||
|
||||
private Query(Field... fields) {
|
||||
this.fields.addAll(asList(fields));
|
||||
}
|
||||
|
||||
public static Query select(Field... fields) {
|
||||
return new Query(fields);
|
||||
}
|
||||
|
||||
public static Query selectDistinct(Field... fields) {
|
||||
Query query = new Query(fields);
|
||||
query.distinct = true;
|
||||
return query;
|
||||
}
|
||||
|
||||
public Query from(SqlTable fromTable) {
|
||||
this.table = fromTable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query join(Join... join) {
|
||||
joins.addAll(asList(join));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query where(Criterion criterion) {
|
||||
criterions.add(criterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query groupBy(Field... groupBy) {
|
||||
groupBies.addAll(asList(groupBy));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query orderBy(Order... order) {
|
||||
orders.addAll(asList(order));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query limit(int limit) {
|
||||
limits = limit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query appendSelectFields(Property<?>... selectFields) {
|
||||
this.fields.addAll(asList(selectFields));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o || !(o == null || getClass() != o.getClass()) && this.toString().equals(o.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
visitSelectClause(sql);
|
||||
visitFromClause(sql);
|
||||
|
||||
visitJoinClause(sql);
|
||||
if(queryTemplate == null) {
|
||||
visitWhereClause(sql);
|
||||
visitGroupByClause(sql);
|
||||
visitOrderByClause(sql);
|
||||
visitLimitClause(sql);
|
||||
} else {
|
||||
if(groupBies.size() > 0 || orders.size() > 0 ||
|
||||
havings.size() > 0)
|
||||
throw new IllegalStateException("Can't have extras AND query template"); //$NON-NLS-1$
|
||||
sql.append(queryTemplate);
|
||||
}
|
||||
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
private void visitOrderByClause(StringBuilder sql) {
|
||||
if (orders.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sql.append(ORDER_BY);
|
||||
for (Order order : orders) {
|
||||
sql.append(SPACE).append(order).append(COMMA);
|
||||
}
|
||||
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
private void visitGroupByClause(StringBuilder sql) {
|
||||
if (groupBies.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sql.append(GROUP_BY);
|
||||
for (Field groupBy : groupBies) {
|
||||
sql.append(SPACE).append(groupBy).append(COMMA);
|
||||
}
|
||||
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||
if (havings.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sql.append("HAVING");
|
||||
for (Criterion havingCriterion : havings) {
|
||||
sql.append(SPACE).append(havingCriterion).append(COMMA);
|
||||
}
|
||||
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||
}
|
||||
|
||||
private void visitWhereClause(StringBuilder sql) {
|
||||
if (criterions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sql.append(WHERE);
|
||||
for (Criterion criterion : criterions) {
|
||||
sql.append(SPACE).append(criterion).append(SPACE);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitJoinClause(StringBuilder sql) {
|
||||
for (Join join : joins) {
|
||||
sql.append(join).append(SPACE);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitFromClause(StringBuilder sql) {
|
||||
if (table == null) {
|
||||
return;
|
||||
}
|
||||
sql.append(FROM).append(SPACE).append(table).append(SPACE);
|
||||
}
|
||||
|
||||
private void visitSelectClause(StringBuilder sql) {
|
||||
sql.append(SELECT).append(SPACE);
|
||||
if(distinct)
|
||||
sql.append(DISTINCT).append(SPACE);
|
||||
if (fields.isEmpty()) {
|
||||
sql.append(ALL).append(SPACE);
|
||||
return;
|
||||
}
|
||||
for (Field field : fields) {
|
||||
sql.append(field.toStringInSelect()).append(COMMA);
|
||||
}
|
||||
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||
}
|
||||
|
||||
private void visitLimitClause(StringBuilder sql) {
|
||||
if(limits > -1)
|
||||
sql.append(LIMIT).append(SPACE).append(limits).append(SPACE);
|
||||
}
|
||||
|
||||
public SqlTable as(String alias) {
|
||||
return table(LEFT_PARENTHESIS + this.toString() + RIGHT_PARENTHESIS).as(alias);
|
||||
}
|
||||
|
||||
public Query having(Criterion criterion) {
|
||||
this.havings.add(criterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of fields returned by this query
|
||||
* @return
|
||||
*/
|
||||
public Property<?>[] getFields() {
|
||||
return fields.toArray(new Property<?>[fields.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the SQL query template (comes after the "from")
|
||||
* @param template
|
||||
* @return query
|
||||
*/
|
||||
public Query withQueryTemplate(String template) {
|
||||
queryTemplate = template;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse out properties and run query
|
||||
* @param cr
|
||||
* @param baseUri
|
||||
* @return
|
||||
*/
|
||||
public Cursor queryContentResolver(ContentResolver cr, Uri baseUri) {
|
||||
Uri uri = baseUri;
|
||||
|
||||
if(joins.size() != 0)
|
||||
throw new UnsupportedOperationException("can't perform join in content resolver query"); //$NON-NLS-1$
|
||||
|
||||
String[] projection = new String[fields.size()];
|
||||
for(int i = 0; i < projection.length; i++)
|
||||
projection[i] = fields.get(i).toString();
|
||||
|
||||
StringBuilder groupByClause = new StringBuilder();
|
||||
StringBuilder selectionClause = new StringBuilder();
|
||||
StringBuilder orderClause = new StringBuilder();
|
||||
if(queryTemplate != null) {
|
||||
QueryTemplateHelper.queryForContentResolver(queryTemplate,
|
||||
selectionClause, orderClause, groupByClause);
|
||||
} else {
|
||||
if(groupBies.size() > 0) {
|
||||
for (Field groupBy : groupBies)
|
||||
groupByClause.append(SPACE).append(groupBy).append(COMMA);
|
||||
if(groupByClause.length() > 0)
|
||||
groupByClause.deleteCharAt(groupByClause.length() - 1);
|
||||
}
|
||||
|
||||
for (Criterion criterion : criterions)
|
||||
selectionClause.append(criterion).append(SPACE);
|
||||
|
||||
for (Order order : orders)
|
||||
orderClause.append(SPACE).append(order).append(COMMA);
|
||||
if(orderClause.length() > 0)
|
||||
orderClause.deleteCharAt(orderClause.length() - 1);
|
||||
}
|
||||
|
||||
if(groupByClause.length() > 0)
|
||||
uri = Uri.withAppendedPath(baseUri, AstridApiConstants.GROUP_BY_URI +
|
||||
groupByClause.toString().trim());
|
||||
return cr.query(uri, projection, selectionClause.toString(), null,
|
||||
orderClause.toString());
|
||||
}
|
||||
|
||||
/** query template helper */
|
||||
public static class QueryTemplateHelper {
|
||||
|
||||
/** build a content resolver query */
|
||||
@SuppressWarnings("nls")
|
||||
public static void queryForContentResolver(String queryTemplate,
|
||||
StringBuilder selectionClause, StringBuilder orderClause,
|
||||
StringBuilder groupByClause) {
|
||||
|
||||
Pattern where = Pattern.compile("WHERE (.*?)(LIMIT|HAVING|GROUP|ORDER|\\Z)");
|
||||
Matcher whereMatcher = where.matcher(queryTemplate);
|
||||
if(whereMatcher.find())
|
||||
selectionClause.append(whereMatcher.group(1).trim());
|
||||
|
||||
Pattern group = Pattern.compile("GROUP BY (.*?)(LIMIT|HAVING|ORDER|\\Z)");
|
||||
Matcher groupMatcher = group.matcher(queryTemplate);
|
||||
if(groupMatcher.find())
|
||||
groupByClause.append(groupMatcher.group(1).trim());
|
||||
|
||||
Pattern order = Pattern.compile("ORDER BY (.*?)(LIMIT|HAVING|\\Z)");
|
||||
Matcher orderMatcher = order.matcher(queryTemplate);
|
||||
if(orderMatcher.find())
|
||||
orderClause.append(orderMatcher.group(1).trim());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.COMMA;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.GROUP_BY;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.LIMIT;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.ORDER_BY;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
import static com.todoroo.andlib.sql.SqlConstants.WHERE;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Query Template returns a bunch of criteria that allows a query to be
|
||||
* constructed
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public final class QueryTemplate {
|
||||
|
||||
private final ArrayList<Criterion> criterions = new ArrayList<Criterion>();
|
||||
private final ArrayList<Join> joins = new ArrayList<Join>();
|
||||
private final ArrayList<Field> groupBies = new ArrayList<Field>();
|
||||
private final ArrayList<Order> orders = new ArrayList<Order>();
|
||||
private final ArrayList<Criterion> havings = new ArrayList<Criterion>();
|
||||
private Integer limit = null;
|
||||
|
||||
public QueryTemplate join(Join... join) {
|
||||
joins.addAll(asList(join));
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryTemplate where(Criterion criterion) {
|
||||
criterions.add(criterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryTemplate groupBy(Field... groupBy) {
|
||||
groupBies.addAll(asList(groupBy));
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryTemplate orderBy(Order... order) {
|
||||
orders.addAll(asList(order));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
visitJoinClause(sql);
|
||||
visitWhereClause(sql);
|
||||
visitGroupByClause(sql);
|
||||
visitOrderByClause(sql);
|
||||
if(limit != null)
|
||||
sql.append(LIMIT).append(SPACE).append(limit);
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
private void visitOrderByClause(StringBuilder sql) {
|
||||
if (orders.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sql.append(ORDER_BY);
|
||||
for (Order order : orders) {
|
||||
sql.append(SPACE).append(order).append(COMMA);
|
||||
}
|
||||
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
private void visitGroupByClause(StringBuilder sql) {
|
||||
if (groupBies.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sql.append(GROUP_BY);
|
||||
for (Field groupBy : groupBies) {
|
||||
sql.append(SPACE).append(groupBy).append(COMMA);
|
||||
}
|
||||
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||
if (havings.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sql.append("HAVING");
|
||||
for (Criterion havingCriterion : havings) {
|
||||
sql.append(SPACE).append(havingCriterion).append(COMMA);
|
||||
}
|
||||
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||
}
|
||||
|
||||
private void visitWhereClause(StringBuilder sql) {
|
||||
if (criterions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sql.append(WHERE);
|
||||
for (Criterion criterion : criterions) {
|
||||
sql.append(SPACE).append(criterion).append(SPACE);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitJoinClause(StringBuilder sql) {
|
||||
for (Join join : joins) {
|
||||
sql.append(join).append(SPACE);
|
||||
}
|
||||
}
|
||||
|
||||
public QueryTemplate having(Criterion criterion) {
|
||||
this.havings.add(criterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryTemplate limit(int limitValue) {
|
||||
this.limit = limitValue;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public final class SqlConstants {
|
||||
static final String SELECT = "SELECT";
|
||||
static final String DISTINCT = "DISTINCT";
|
||||
static final String SPACE = " ";
|
||||
static final String AS = "AS";
|
||||
static final String COMMA = ",";
|
||||
static final String FROM = "FROM";
|
||||
static final String ON = "ON";
|
||||
static final String JOIN = "JOIN";
|
||||
static final String ALL = "*";
|
||||
static final String LEFT_PARENTHESIS = "(";
|
||||
static final String RIGHT_PARENTHESIS = ")";
|
||||
static final String AND = "AND";
|
||||
static final String BETWEEN = "BETWEEN";
|
||||
static final String LIKE = "LIKE";
|
||||
static final String OR = "OR";
|
||||
static final String ORDER_BY = "ORDER BY";
|
||||
static final String GROUP_BY = "GROUP BY";
|
||||
static final String WHERE = "WHERE";
|
||||
public static final String EXISTS = "EXISTS";
|
||||
public static final String NOT = "NOT";
|
||||
public static final String LIMIT = "LIMIT";
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
public class SqlTable extends DBObject<SqlTable> {
|
||||
|
||||
protected SqlTable(String expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
public static SqlTable table(String table) {
|
||||
return new SqlTable(table);
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
protected String fieldExpression(String fieldName) {
|
||||
if (hasAlias()) {
|
||||
return alias + "." + fieldName;
|
||||
}
|
||||
return expression+"."+fieldName;
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package com.todoroo.andlib.sql;
|
||||
|
||||
import static com.todoroo.andlib.sql.SqlConstants.SPACE;
|
||||
|
||||
public class UnaryCriterion extends Criterion {
|
||||
protected final Field expression;
|
||||
protected final Object value;
|
||||
|
||||
UnaryCriterion(Field expression, Operator operator, Object value) {
|
||||
super(operator);
|
||||
this.expression = expression;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void populate(StringBuilder sb) {
|
||||
beforePopulateOperator(sb);
|
||||
populateOperator(sb);
|
||||
afterPopulateOperator(sb);
|
||||
}
|
||||
|
||||
public static Criterion eq(Field expression, Object value) {
|
||||
return new UnaryCriterion(expression, Operator.eq, value);
|
||||
}
|
||||
|
||||
protected void beforePopulateOperator(StringBuilder sb) {
|
||||
sb.append(expression);
|
||||
}
|
||||
|
||||
protected void populateOperator(StringBuilder sb) {
|
||||
sb.append(operator);
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
protected void afterPopulateOperator(StringBuilder sb) {
|
||||
if(value == null)
|
||||
return;
|
||||
else if(value instanceof String)
|
||||
sb.append("'").append(sanitize((String) value)).append("'");
|
||||
else
|
||||
sb.append(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize the given input for SQL
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static String sanitize(String input) {
|
||||
return input.replace("'", "''");
|
||||
}
|
||||
|
||||
public static Criterion neq(Field field, Object value) {
|
||||
return new UnaryCriterion(field, Operator.neq, value);
|
||||
}
|
||||
|
||||
public static Criterion gt(Field field, Object value) {
|
||||
return new UnaryCriterion(field, Operator.gt, value);
|
||||
}
|
||||
|
||||
public static Criterion lt(Field field, Object value) {
|
||||
return new UnaryCriterion(field, Operator.lt, value);
|
||||
}
|
||||
|
||||
public static Criterion lte(Field field, Object value) {
|
||||
return new UnaryCriterion(field, Operator.lte, value);
|
||||
}
|
||||
|
||||
public static Criterion isNull(Field field) {
|
||||
return new UnaryCriterion(field, Operator.isNull, null) {
|
||||
@Override
|
||||
protected void populateOperator(StringBuilder sb) {
|
||||
sb.append(SPACE).append(operator);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Criterion isNotNull(Field field) {
|
||||
return new UnaryCriterion(field, Operator.isNotNull, null) {
|
||||
@Override
|
||||
protected void populateOperator(StringBuilder sb) {
|
||||
sb.append(SPACE).append(operator);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Criterion like(Field field, String value) {
|
||||
return new UnaryCriterion(field, Operator.like, value) {
|
||||
@Override
|
||||
protected void populateOperator(StringBuilder sb) {
|
||||
sb.append(SPACE).append(operator).append(SPACE);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Criterion like(Field field, String value, final String escape) {
|
||||
return new UnaryCriterion(field, Operator.like, value) {
|
||||
@Override
|
||||
protected void populateOperator(StringBuilder sb) {
|
||||
sb.append(SPACE).append(operator).append(SPACE);
|
||||
}
|
||||
@SuppressWarnings("nls")
|
||||
@Override
|
||||
protected void afterPopulateOperator(StringBuilder sb) {
|
||||
super.afterPopulateOperator(sb);
|
||||
sb.append(SPACE).append("ESCAPE").append(" '").append(sanitize(escape)).append("'");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Fork of <a href="http://code.google.com/p/sql-dsl/">sql-dsl</a>
|
||||
*/
|
||||
package com.todoroo.andlib.sql;
|
@ -0,0 +1,547 @@
|
||||
package com.todoroo.andlib.utility;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkInfo.State;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.todoroo.andlib.data.Property;
|
||||
import com.todoroo.andlib.service.ExceptionService;
|
||||
|
||||
/**
|
||||
* Android Utility Classes
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class AndroidUtilities {
|
||||
|
||||
public static final String SEPARATOR_ESCAPE = "!PIPE!"; //$NON-NLS-1$
|
||||
public static final String SERIALIZATION_SEPARATOR = "|"; //$NON-NLS-1$
|
||||
|
||||
// --- utility methods
|
||||
|
||||
/** Suppress virtual keyboard until user's first tap */
|
||||
public static void suppressVirtualKeyboard(final TextView editor) {
|
||||
final int inputType = editor.getInputType();
|
||||
editor.setInputType(InputType.TYPE_NULL);
|
||||
editor.setOnTouchListener(new OnTouchListener() {
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
editor.setInputType(inputType);
|
||||
editor.setOnTouchListener(null);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if we're connected to the internet
|
||||
*/
|
||||
public static boolean isConnected(Context context) {
|
||||
ConnectivityManager manager = (ConnectivityManager)
|
||||
context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo info = manager.getActiveNetworkInfo();
|
||||
if (info == null)
|
||||
return false;
|
||||
if (info.getState() != State.CONNECTED)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Fetch the image specified by the given url */
|
||||
public static Bitmap fetchImage(URL url) throws IOException {
|
||||
InputStream is = null;
|
||||
try {
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.connect();
|
||||
is = conn.getInputStream();
|
||||
BufferedInputStream bis = new BufferedInputStream(is, 16384);
|
||||
try {
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(bis);
|
||||
return bitmap;
|
||||
} finally {
|
||||
bis.close();
|
||||
}
|
||||
} finally {
|
||||
if(is != null)
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the given intent, handling security exceptions if they arise
|
||||
*
|
||||
* @param context
|
||||
* @param intent
|
||||
* @param request request code. if negative, no request.
|
||||
*/
|
||||
public static void startExternalIntent(Context context, Intent intent, int request) {
|
||||
try {
|
||||
if(request > -1 && context instanceof Activity)
|
||||
((Activity)context).startActivityForResult(intent, request);
|
||||
else
|
||||
context.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
getExceptionService().displayAndReportError(context,
|
||||
"start-external-intent-" + intent.toString(), //$NON-NLS-1$
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the given intent, handling security exceptions if they arise
|
||||
*
|
||||
* @param activity
|
||||
* @param intent
|
||||
* @param requestCode
|
||||
*/
|
||||
public static void startExternalIntentForResult(
|
||||
Activity activity, Intent intent, int requestCode) {
|
||||
try {
|
||||
activity.startActivityForResult(intent, requestCode);
|
||||
} catch (SecurityException e) {
|
||||
getExceptionService().displayAndReportError(activity,
|
||||
"start-external-intent-" + intent.toString(), //$NON-NLS-1$
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an arbitrary object into a {@link ContentValues}
|
||||
* @param target
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public static void putInto(ContentValues target, String key, Object value) {
|
||||
if(value instanceof String)
|
||||
target.put(key, (String) value);
|
||||
else if(value instanceof Long)
|
||||
target.put(key, (Long) value);
|
||||
else if(value instanceof Integer)
|
||||
target.put(key, (Integer) value);
|
||||
else if(value instanceof Double)
|
||||
target.put(key, (Double) value);
|
||||
else
|
||||
throw new UnsupportedOperationException("Could not handle type " + //$NON-NLS-1$
|
||||
value.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rips apart a content value into two string arrays, keys and value
|
||||
*/
|
||||
public static String[][] contentValuesToStringArrays(ContentValues source) {
|
||||
String[][] result = new String[2][source.size()];
|
||||
int i = 0;
|
||||
for(Entry<String, Object> entry : source.valueSet()) {
|
||||
result[0][i] = entry.getKey();
|
||||
result[1][i++] = entry.getValue().toString();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return index of value in array
|
||||
* @param array array to search
|
||||
* @param value value to look for
|
||||
* @return
|
||||
*/
|
||||
public static <TYPE> int indexOf(TYPE[] array, TYPE value) {
|
||||
for(int i = 0; i < array.length; i++)
|
||||
if(array[i].equals(value))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes a content value into a string
|
||||
*/
|
||||
public static String contentValuesToSerializedString(ContentValues source) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for(Entry<String, Object> entry : source.valueSet()) {
|
||||
result.append(entry.getKey().replace(SERIALIZATION_SEPARATOR, SEPARATOR_ESCAPE)).append(
|
||||
SERIALIZATION_SEPARATOR);
|
||||
Object value = entry.getValue();
|
||||
if(value instanceof Integer)
|
||||
result.append('i').append(value);
|
||||
else if(value instanceof Double)
|
||||
result.append('d').append(value);
|
||||
else if(value instanceof Long)
|
||||
result.append('l').append(value);
|
||||
else if(value instanceof String)
|
||||
result.append('s').append(value.toString());
|
||||
else
|
||||
throw new UnsupportedOperationException(value.getClass().toString());
|
||||
result.append(SERIALIZATION_SEPARATOR);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn ContentValues into a string
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
public static ContentValues contentValuesFromSerializedString(String string) {
|
||||
if(string == null)
|
||||
return new ContentValues();
|
||||
|
||||
String[] pairs = string.split("\\" + SERIALIZATION_SEPARATOR); //$NON-NLS-1$
|
||||
ContentValues result = new ContentValues();
|
||||
for(int i = 0; i < pairs.length; i += 2) {
|
||||
String key = pairs[i].replaceAll(SEPARATOR_ESCAPE, SERIALIZATION_SEPARATOR);
|
||||
String value = pairs[i+1].substring(1);
|
||||
try {
|
||||
switch(pairs[i+1].charAt(0)) {
|
||||
case 'i':
|
||||
result.put(key, Integer.parseInt(value));
|
||||
break;
|
||||
case 'd':
|
||||
result.put(key, Double.parseDouble(value));
|
||||
break;
|
||||
case 'l':
|
||||
result.put(key, Long.parseLong(value));
|
||||
break;
|
||||
case 's':
|
||||
result.put(key, value.replace(SEPARATOR_ESCAPE, SERIALIZATION_SEPARATOR));
|
||||
break;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// failed parse to number, try to put a string
|
||||
result.put(key, value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn ContentValues into a string
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static ContentValues contentValuesFromString(String string) {
|
||||
if(string == null)
|
||||
return null;
|
||||
|
||||
String[] pairs = string.split("=");
|
||||
ContentValues result = new ContentValues();
|
||||
String key = null;
|
||||
for(int i = 0; i < pairs.length; i++) {
|
||||
String newKey = null;
|
||||
int lastSpace = pairs[i].lastIndexOf(' ');
|
||||
if(lastSpace != -1) {
|
||||
newKey = pairs[i].substring(lastSpace + 1);
|
||||
pairs[i] = pairs[i].substring(0, lastSpace);
|
||||
} else {
|
||||
newKey = pairs[i];
|
||||
}
|
||||
if(key != null)
|
||||
result.put(key.trim(), pairs[i].trim());
|
||||
key = newKey;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a and b or null or a.equals(b)
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
public static boolean equals(Object a, Object b) {
|
||||
if(a == null && b == null)
|
||||
return true;
|
||||
if(a == null)
|
||||
return false;
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file from one place to another
|
||||
*
|
||||
* @param in
|
||||
* @param out
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void copyFile(File in, File out) throws Exception {
|
||||
FileInputStream fis = new FileInputStream(in);
|
||||
FileOutputStream fos = new FileOutputStream(out);
|
||||
try {
|
||||
byte[] buf = new byte[1024];
|
||||
int i = 0;
|
||||
while ((i = fis.read(buf)) != -1) {
|
||||
fos.write(buf, 0, i);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
} finally {
|
||||
fis.close();
|
||||
fos.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a child view of a certain type
|
||||
* @param view
|
||||
* @param type
|
||||
* @return first view (by DFS) if found, or null if none
|
||||
*/
|
||||
public static <TYPE> TYPE findViewByType(View view, Class<TYPE> type) {
|
||||
if(view == null)
|
||||
return null;
|
||||
if(type.isInstance(view))
|
||||
return (TYPE) view;
|
||||
if(view instanceof ViewGroup) {
|
||||
ViewGroup group = (ViewGroup) view;
|
||||
for(int i = 0; i < group.getChildCount(); i++) {
|
||||
TYPE v = findViewByType(group.getChildAt(i), type);
|
||||
if(v != null)
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Android SDK version as an integer. Works on all versions
|
||||
*/
|
||||
public static int getSdkVersion() {
|
||||
return Integer.parseInt(android.os.Build.VERSION.SDK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy databases to a given folder. Useful for debugging
|
||||
* @param folder
|
||||
*/
|
||||
public static void copyDatabases(Context context, String folder) {
|
||||
File folderFile = new File(folder);
|
||||
if(!folderFile.exists())
|
||||
folderFile.mkdir();
|
||||
for(String db : context.databaseList()) {
|
||||
File dbFile = context.getDatabasePath(db);
|
||||
try {
|
||||
copyFile(dbFile, new File(folderFile.getAbsolutePath() +
|
||||
File.separator + db));
|
||||
} catch (Exception e) {
|
||||
Log.e("ERROR", "ERROR COPYING DB " + db, e); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort files by date so the newest file is on top
|
||||
* @param files
|
||||
*/
|
||||
public static void sortFilesByDateDesc(File[] files) {
|
||||
Arrays.sort(files, new Comparator<File>() {
|
||||
public int compare(File o1, File o2) {
|
||||
return Long.valueOf(o2.lastModified()).compareTo(Long.valueOf(o1.lastModified()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the given value in the map, returning key if found
|
||||
* @param map
|
||||
* @param value
|
||||
* @return null if not found, otherwise key
|
||||
*/
|
||||
public static <KEY, VALUE> KEY findKeyInMap(Map<KEY, VALUE> map, VALUE value){
|
||||
for (Entry<KEY, VALUE> entry: map.entrySet()) {
|
||||
if(entry.getValue().equals(value))
|
||||
return entry.getKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep, ignoring interruption. Before using this method, think carefully
|
||||
* about why you are ignoring interruptions.
|
||||
*
|
||||
* @param l
|
||||
*/
|
||||
public static void sleepDeep(long l) {
|
||||
try {
|
||||
Thread.sleep(l);
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a method via reflection if API level is at least minSdk
|
||||
* @param minSdk minimum sdk number (i.e. 8)
|
||||
* @param receiver object to call method on
|
||||
* @param methodName method name to call
|
||||
* @param params method parameter types
|
||||
* @param args arguments
|
||||
* @return method return value, or null if nothing was called or exception
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static Object callApiMethod(int minSdk, Object receiver,
|
||||
String methodName, Class<?>[] params, Object... args) {
|
||||
if(getSdkVersion() < minSdk)
|
||||
return null;
|
||||
|
||||
Method method;
|
||||
try {
|
||||
method = receiver.getClass().getMethod(methodName, params);
|
||||
return method.invoke(receiver, args);
|
||||
} catch (SecurityException e) {
|
||||
getExceptionService().reportError("call-method", e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
getExceptionService().reportError("call-method", e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
getExceptionService().reportError("call-method", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
getExceptionService().reportError("call-method", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
getExceptionService().reportError("call-method", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* From Android MyTracks project (http://mytracks.googlecode.com/).
|
||||
* Licensed under the Apache Public License v2
|
||||
* @param activity
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public static CharSequence readFile(Context activity, int id) {
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(
|
||||
activity.getResources().openRawResource(id)));
|
||||
String line;
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
while ((line = in.readLine()) != null) {
|
||||
buffer.append(line).append('\n');
|
||||
}
|
||||
return buffer;
|
||||
} catch (IOException e) {
|
||||
return ""; //$NON-NLS-1$
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an md5 hash on the input string
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static String md5(String input) {
|
||||
try {
|
||||
byte[] bytesOfMessage = input.getBytes("UTF-8");
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] digest = md.digest(bytesOfMessage);
|
||||
BigInteger bigInt = new BigInteger(1,digest);
|
||||
String hashtext = bigInt.toString(16);
|
||||
while(hashtext.length() < 32 ){
|
||||
hashtext = "0" + hashtext;
|
||||
}
|
||||
return hashtext;
|
||||
} catch (Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an intent to a remote activity
|
||||
* @param appPackage
|
||||
* @param activityClass
|
||||
* @return
|
||||
*/
|
||||
public static Intent remoteIntent(String appPackage, String activityClass) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(appPackage, activityClass);
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets application signature
|
||||
* @return application signature, or null if an error was encountered
|
||||
*/
|
||||
public static String getSignature(Context context, String packageName) {
|
||||
try {
|
||||
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.GET_SIGNATURES);
|
||||
return packageInfo.signatures[0].toCharsString();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Join items to a list
|
||||
* @param <TYPE>
|
||||
* @param list
|
||||
* @param newList
|
||||
* @param newItems
|
||||
* @return
|
||||
*/
|
||||
public static Property<?>[] addToArray(Property<?>[] list, Property<?>... newItems) {
|
||||
Property<?>[] newList = new Property<?>[list.length + newItems.length];
|
||||
for(int i = 0; i < list.length; i++)
|
||||
newList[i] = list[i];
|
||||
for(int i = 0; i < newItems.length; i++)
|
||||
newList[list.length + i] = newItems[i];
|
||||
return newList;
|
||||
}
|
||||
|
||||
// --- internal
|
||||
|
||||
private static ExceptionService exceptionService = null;
|
||||
|
||||
private static ExceptionService getExceptionService() {
|
||||
if(exceptionService == null)
|
||||
synchronized(AndroidUtilities.class) {
|
||||
if(exceptionService == null)
|
||||
exceptionService = new ExceptionService();
|
||||
}
|
||||
return exceptionService;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Todoroo Inc
|
||||
* All Rights Reserved
|
||||
* http://www.todoroo.com
|
||||
*/
|
||||
package com.todoroo.andlib.utility;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
|
||||
public class DateUtilities {
|
||||
|
||||
/* ======================================================================
|
||||
* ============================================================ long time
|
||||
* ====================================================================== */
|
||||
|
||||
/** Convert unixtime into date */
|
||||
public static final Date unixtimeToDate(long millis) {
|
||||
if(millis == 0)
|
||||
return null;
|
||||
return new Date(millis);
|
||||
}
|
||||
|
||||
/** Convert date into unixtime */
|
||||
public static final long dateToUnixtime(Date date) {
|
||||
if(date == null)
|
||||
return 0;
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
/** Returns unixtime for current time */
|
||||
public static final long now() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/** Returns unixtime one month from now */
|
||||
public static final long oneMonthFromNow() {
|
||||
Date date = new Date();
|
||||
date.setMonth(date.getMonth() + 1);
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
/** Represents a single hour */
|
||||
public static long ONE_HOUR = 3600000L;
|
||||
|
||||
/** Represents a single day */
|
||||
public static long ONE_DAY = 24 * ONE_HOUR;
|
||||
|
||||
/** Represents a single week */
|
||||
public static long ONE_WEEK = 7 * ONE_DAY;
|
||||
|
||||
/* ======================================================================
|
||||
* =========================================================== formatters
|
||||
* ====================================================================== */
|
||||
|
||||
static Boolean is24HourOverride = null;
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public static boolean is24HourFormat(Context context) {
|
||||
if(is24HourOverride != null)
|
||||
return is24HourOverride;
|
||||
|
||||
String value = android.provider.Settings.System.getString(context.getContentResolver(),
|
||||
android.provider.Settings.System.TIME_12_24);
|
||||
boolean b24 = !(value == null || value.equals("12"));
|
||||
return b24;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context android context
|
||||
* @param date time to format
|
||||
* @return time, with hours and minutes
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static String getTimeString(Context context, Date date) {
|
||||
String value;
|
||||
if (is24HourFormat(context)) {
|
||||
value = "H:mm";
|
||||
} else {
|
||||
value = "h:mm a";
|
||||
}
|
||||
return new SimpleDateFormat(value).format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context android context
|
||||
* @param date date to format
|
||||
* @return date, with month, day, and year
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static String getDateString(Context context, Date date) {
|
||||
String month = DateUtils.getMonthString(date.getMonth() +
|
||||
Calendar.JANUARY, DateUtils.LENGTH_MEDIUM);
|
||||
String value;
|
||||
// united states, you are special
|
||||
if (Locale.US.equals(Locale.getDefault())
|
||||
|| Locale.CANADA.equals(Locale.getDefault()))
|
||||
value = "'#' d yyyy";
|
||||
else
|
||||
value = "d '#' yyyy";
|
||||
return new SimpleDateFormat(value).format(date).replace("#", month);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return date format as getDateFormat with weekday
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static String getDateStringWithWeekday(Context context, Date date) {
|
||||
String weekday = DateUtils.getDayOfWeekString(date.getDay() + Calendar.SUNDAY,
|
||||
DateUtils.LENGTH_LONG);
|
||||
return weekday + ", " + getDateString(context, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return date format as getDateFormat with weekday
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static String getDateStringWithTimeAndWeekday(Context context, Date date) {
|
||||
return getDateStringWithWeekday(context, date) + " " + getTimeString(context, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return date with time at the end
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static String getDateStringWithTime(Context context, Date date) {
|
||||
return getDateString(context, date) + " " + getTimeString(context, date);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
package com.todoroo.andlib.utility;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.todoroo.astrid.api.R;
|
||||
|
||||
public class DialogUtilities {
|
||||
|
||||
/**
|
||||
* Displays a dialog box with a EditText and an ok / cancel
|
||||
*
|
||||
* @param activity
|
||||
* @param text
|
||||
* @param okListener
|
||||
*/
|
||||
public static void viewDialog(final Activity activity, final String text,
|
||||
final View view, final DialogInterface.OnClickListener okListener,
|
||||
final DialogInterface.OnClickListener cancelListener) {
|
||||
if(activity.isFinishing())
|
||||
return;
|
||||
|
||||
tryOnUiThread(activity, new Runnable() {
|
||||
public void run() {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.DLG_question_title)
|
||||
.setMessage(text)
|
||||
.setView(view)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setPositiveButton(android.R.string.ok, okListener)
|
||||
.setNegativeButton(android.R.string.cancel, cancelListener)
|
||||
.show().setOwnerActivity(activity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an OK dialog with HTML content
|
||||
*
|
||||
* @param context
|
||||
* @param html
|
||||
* @param title
|
||||
*/
|
||||
public static void htmlDialog(Context context, String html, int title) {
|
||||
WebView webView = new WebView(context);
|
||||
webView.loadData(html, "text/html", "utf-8"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
webView.setBackgroundColor(0);
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(title)
|
||||
.setView(webView)
|
||||
.setIcon(android.R.drawable.ic_dialog_info)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a dialog box with an OK button
|
||||
*
|
||||
* @param activity
|
||||
* @param text
|
||||
* @param okListener
|
||||
*/
|
||||
public static void okDialog(final Activity activity, final String text,
|
||||
final DialogInterface.OnClickListener okListener) {
|
||||
if(activity.isFinishing())
|
||||
return;
|
||||
|
||||
tryOnUiThread(activity, new Runnable() {
|
||||
public void run() {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.DLG_information_title)
|
||||
.setMessage(text)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setPositiveButton(android.R.string.ok, okListener)
|
||||
.show().setOwnerActivity(activity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a dialog box with an OK button
|
||||
*
|
||||
* @param activity
|
||||
* @param text
|
||||
* @param okListener
|
||||
*/
|
||||
public static void okDialog(final Activity activity, final String title,
|
||||
final int icon, final CharSequence text,
|
||||
final DialogInterface.OnClickListener okListener) {
|
||||
if(activity.isFinishing())
|
||||
return;
|
||||
|
||||
tryOnUiThread(activity, new Runnable() {
|
||||
public void run() {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(title)
|
||||
.setMessage(text)
|
||||
.setIcon(icon)
|
||||
.setPositiveButton(android.R.string.ok, okListener)
|
||||
.show().setOwnerActivity(activity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a dialog box with OK and Cancel buttons and custom title
|
||||
*
|
||||
* @param activity
|
||||
* @param title
|
||||
* @param text
|
||||
* @param okListener
|
||||
* @param cancelListener
|
||||
*/
|
||||
public static void okCancelDialog(final Activity activity, final String title,
|
||||
final String text, final DialogInterface.OnClickListener okListener,
|
||||
final DialogInterface.OnClickListener cancelListener) {
|
||||
if(activity.isFinishing())
|
||||
return;
|
||||
|
||||
tryOnUiThread(activity, new Runnable() {
|
||||
public void run() {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(title)
|
||||
.setMessage(text)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setPositiveButton(android.R.string.ok, okListener)
|
||||
.setNegativeButton(android.R.string.cancel, cancelListener)
|
||||
.show().setOwnerActivity(activity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a dialog box with OK and Cancel buttons
|
||||
*
|
||||
* @param activity
|
||||
* @param text
|
||||
* @param okListener
|
||||
* @param cancelListener
|
||||
*/
|
||||
public static void okCancelDialog(final Activity activity, final String text,
|
||||
final DialogInterface.OnClickListener okListener,
|
||||
final DialogInterface.OnClickListener cancelListener) {
|
||||
if(activity.isFinishing())
|
||||
return;
|
||||
|
||||
tryOnUiThread(activity, new Runnable() {
|
||||
public void run() {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.DLG_confirm_title)
|
||||
.setMessage(text)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setPositiveButton(android.R.string.ok, okListener)
|
||||
.setNegativeButton(android.R.string.cancel, cancelListener)
|
||||
.show().setOwnerActivity(activity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a progress dialog. Must be run on the UI thread
|
||||
* @param context
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
public static ProgressDialog progressDialog(Context context, String text) {
|
||||
ProgressDialog dialog = new ProgressDialog(context);
|
||||
dialog.setIndeterminate(true);
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
dialog.setMessage(text);
|
||||
dialog.show();
|
||||
dialog.setOwnerActivity((Activity)context);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss a dialog off the UI thread
|
||||
*
|
||||
* @param activity
|
||||
* @param dialog
|
||||
*/
|
||||
public static void dismissDialog(Activity activity, final Dialog dialog) {
|
||||
if(dialog == null)
|
||||
return;
|
||||
tryOnUiThread(activity, new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
dialog.dismiss();
|
||||
} catch (Exception e) {
|
||||
// could have killed activity
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static void tryOnUiThread(Activity activity, final Runnable runnable) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception e) {
|
||||
// probably window was closed
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.todoroo.andlib.utility;
|
||||
|
||||
/**
|
||||
* Pair utility class
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
* @param <L>
|
||||
* @param <R>
|
||||
*/
|
||||
public class Pair<L, R> {
|
||||
|
||||
private final L left;
|
||||
private final R right;
|
||||
|
||||
public R getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public L getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public Pair(final L left, final R right) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public static <A, B> Pair<A, B> create(A left, B right) {
|
||||
return new Pair<A, B>(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (!(o instanceof Pair<?, ?>))
|
||||
return false;
|
||||
|
||||
final Pair<?, ?> other = (Pair<?, ?>) o;
|
||||
return equal(getLeft(), other.getLeft()) && equal(getRight(), other.getRight());
|
||||
}
|
||||
|
||||
public static final boolean equal(Object o1, Object o2) {
|
||||
if (o1 == null) {
|
||||
return o2 == null;
|
||||
}
|
||||
return o1.equals(o2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hLeft = getLeft() == null ? 0 : getLeft().hashCode();
|
||||
int hRight = getRight() == null ? 0 : getRight().hashCode();
|
||||
|
||||
return hLeft + (57 * hRight);
|
||||
}
|
||||
}
|
@ -0,0 +1,255 @@
|
||||
package com.todoroo.andlib.utility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.content.res.Resources;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
|
||||
/**
|
||||
* Helper class for reading and writing SharedPreferences
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class Preferences {
|
||||
|
||||
/**
|
||||
* Helper to write to editor if key specified is null. Writes a String
|
||||
* property with the given integer
|
||||
*
|
||||
* @param prefs
|
||||
* @param editor
|
||||
* @param r
|
||||
* @param keyResource
|
||||
* @param value
|
||||
*/
|
||||
public static void setIfUnset(SharedPreferences prefs, Editor editor, Resources r, int keyResource, int value) {
|
||||
String key = r.getString(keyResource);
|
||||
if(!prefs.contains(key))
|
||||
editor.putString(key, Integer.toString(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to write to editor if key specified is null
|
||||
* @param prefs
|
||||
* @param editor
|
||||
* @param r
|
||||
* @param keyResource
|
||||
* @param value
|
||||
*/
|
||||
public static void setIfUnset(SharedPreferences prefs, Editor editor, Resources r, int keyResource, boolean value) {
|
||||
String key = r.getString(keyResource);
|
||||
if(!prefs.contains(key) || !(prefs.getAll().get(key) instanceof Boolean))
|
||||
editor.putBoolean(key, value);
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* ======================================================= helper methods
|
||||
* ====================================================================== */
|
||||
|
||||
/** Get preferences object from the context */
|
||||
public static SharedPreferences getPrefs(Context context) {
|
||||
context = context.getApplicationContext();
|
||||
return PreferenceManager.getDefaultSharedPreferences(context);
|
||||
}
|
||||
|
||||
/** @return true if given preference is set */
|
||||
public static boolean isSet(String key) {
|
||||
Context context = ContextManager.getContext();
|
||||
return getPrefs(context).contains(key);
|
||||
}
|
||||
|
||||
// --- preference fetching (string)
|
||||
|
||||
/** Gets an string value from a string preference. Returns null
|
||||
* if the value is not set
|
||||
*
|
||||
* @param context
|
||||
* @param key
|
||||
* @return integer value, or null on error
|
||||
*/
|
||||
public static String getStringValue(String key) {
|
||||
Context context = ContextManager.getContext();
|
||||
return getPrefs(context).getString(key, null);
|
||||
}
|
||||
|
||||
/** Gets an string value from a string preference. Returns null
|
||||
* if the value is not set
|
||||
*
|
||||
* @param context
|
||||
* @param key
|
||||
* @return integer value, or null on error
|
||||
*/
|
||||
public static String getStringValue(int keyResource) {
|
||||
Context context = ContextManager.getContext();
|
||||
return getPrefs(context).getString(context.getResources().getString(keyResource), null);
|
||||
}
|
||||
|
||||
/** Gets an integer value from a string preference. Returns null
|
||||
* if the value is not set or not an integer.
|
||||
*
|
||||
* @param keyResource resource from string.xml
|
||||
* @return integer value, or null on error
|
||||
*/
|
||||
public static int getIntegerFromString(int keyResource, int defaultValue) {
|
||||
Context context = ContextManager.getContext();
|
||||
Resources r = context.getResources();
|
||||
String value = getPrefs(context).getString(r.getString(keyResource), null);
|
||||
if(value == null)
|
||||
return defaultValue;
|
||||
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets an float value from a string preference. Returns null
|
||||
* if the value is not set or not an flat.
|
||||
*
|
||||
* @param keyResource resource from string.xml
|
||||
* @return
|
||||
*/
|
||||
public static Float getFloatFromString(int keyResource) {
|
||||
Context context = ContextManager.getContext();
|
||||
Resources r = context.getResources();
|
||||
String value = getPrefs(context).getString(r.getString(keyResource), ""); //$NON-NLS-1$
|
||||
|
||||
try {
|
||||
return Float.parseFloat(value);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets string preference
|
||||
*/
|
||||
public static void setString(int keyResource, String newValue) {
|
||||
Context context = ContextManager.getContext();
|
||||
setString(context.getString(keyResource), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets string preference
|
||||
*/
|
||||
public static void setString(String key, String newValue) {
|
||||
Context context = ContextManager.getContext();
|
||||
Editor editor = getPrefs(context).edit();
|
||||
editor.putString(key, newValue);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets string preference from integer value
|
||||
*/
|
||||
public static void setStringFromInteger(int keyResource, int newValue) {
|
||||
Context context = ContextManager.getContext();
|
||||
Editor editor = getPrefs(context).edit();
|
||||
editor.putString(context.getString(keyResource), Integer.toString(newValue));
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
// --- preference fetching (boolean)
|
||||
|
||||
/** Gets a boolean preference (e.g. a CheckBoxPreference setting)
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return default if value is unset otherwise the value
|
||||
*/
|
||||
public static boolean getBoolean(String key, boolean defValue) {
|
||||
Context context = ContextManager.getContext();
|
||||
try {
|
||||
return getPrefs(context).getBoolean(key, defValue);
|
||||
} catch (ClassCastException e) {
|
||||
return defValue;
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets a boolean preference (e.g. a CheckBoxPreference setting)
|
||||
*
|
||||
* @param keyResource
|
||||
* @param defValue
|
||||
* @return default if value is unset otherwise the value
|
||||
*/
|
||||
public static boolean getBoolean(int keyResources, boolean defValue) {
|
||||
return getBoolean(ContextManager.getString(keyResources), defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets boolean preference
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public static void setBoolean(int keyResource, boolean value) {
|
||||
setBoolean(ContextManager.getString(keyResource), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets boolean preference
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public static void setBoolean(String key, boolean value) {
|
||||
Context context = ContextManager.getContext();
|
||||
Editor editor = getPrefs(context).edit();
|
||||
editor.putBoolean(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
// --- preference fetching (int)
|
||||
|
||||
/** Gets a int preference
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return default if value is unset otherwise the value
|
||||
*/
|
||||
public static int getInt(String key, int defValue) {
|
||||
Context context = ContextManager.getContext();
|
||||
return getPrefs(context).getInt(key, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets int preference
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public static void setInt(String key, int value) {
|
||||
Context context = ContextManager.getContext();
|
||||
Editor editor = getPrefs(context).edit();
|
||||
editor.putInt(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
// --- preference fetching (long)
|
||||
|
||||
/** Gets a long preference
|
||||
*
|
||||
* @param key
|
||||
* @param defValue
|
||||
* @return default if value is unset otherwise the value
|
||||
*/
|
||||
public static long getLong(String key, long defValue) {
|
||||
Context context = ContextManager.getContext();
|
||||
return getPrefs(context).getLong(key, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets long preference
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public static void setLong(String key, long value) {
|
||||
Context context = ContextManager.getContext();
|
||||
Editor editor = getPrefs(context).edit();
|
||||
editor.putLong(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package com.todoroo.andlib.utility;
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.RingtonePreference;
|
||||
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
|
||||
/**
|
||||
* Displays a preference screen for users to edit their preferences. Override
|
||||
* updatePreferences to update the summary with preference values.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
abstract public class TodorooPreferenceActivity extends PreferenceActivity {
|
||||
|
||||
// --- abstract methods
|
||||
|
||||
public abstract int getPreferenceResource();
|
||||
|
||||
/**
|
||||
* Update preferences for the given preference
|
||||
* @param preference
|
||||
* @param value setting. may be null.
|
||||
*/
|
||||
public abstract void updatePreferences(Preference preference, Object value);
|
||||
|
||||
// --- implementation
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ContextManager.setContext(this);
|
||||
addPreferencesFromResource(getPreferenceResource());
|
||||
}
|
||||
|
||||
protected void initializePreference(Preference preference) {
|
||||
if(preference instanceof PreferenceGroup) {
|
||||
PreferenceGroup group = (PreferenceGroup)preference;
|
||||
for(int i = 0; i < group.getPreferenceCount(); i++) {
|
||||
initializePreference(group.getPreference(i));
|
||||
}
|
||||
} else {
|
||||
Object value = null;
|
||||
if(preference instanceof ListPreference)
|
||||
value = ((ListPreference)preference).getValue();
|
||||
else if(preference instanceof CheckBoxPreference)
|
||||
value = ((CheckBoxPreference)preference).isChecked();
|
||||
else if(preference instanceof EditTextPreference)
|
||||
value = ((EditTextPreference)preference).getText();
|
||||
else if(preference instanceof RingtonePreference)
|
||||
value = getPreferenceManager().getSharedPreferences().getString(preference.getKey(), null);
|
||||
|
||||
updatePreferences(preference, value);
|
||||
|
||||
preference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference myPreference, Object newValue) {
|
||||
updatePreferences(myPreference, newValue);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if(hasFocus) {
|
||||
initializePreference(getPreferenceScreen());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Todoroo Library utility classes
|
||||
*/
|
||||
package com.todoroo.andlib.utility;
|
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Represents an add-onn for Astrid. Users can enable or disable add-ons,
|
||||
* which affect all other extension points that share the same identifier.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class Addon implements Parcelable {
|
||||
|
||||
/**
|
||||
* Add-on Identifier
|
||||
*/
|
||||
public String addon = null;
|
||||
|
||||
/**
|
||||
* Plug-in Title
|
||||
*/
|
||||
public String title = null;
|
||||
|
||||
/**
|
||||
* Plug-in Author
|
||||
*/
|
||||
public String author = null;
|
||||
|
||||
/**
|
||||
* Plug-in Description
|
||||
*/
|
||||
public String description = null;
|
||||
|
||||
/**
|
||||
* Convenience constructor to generate a plug-in object
|
||||
*
|
||||
* @param addon
|
||||
* @param title
|
||||
* @param author
|
||||
* @param description
|
||||
*/
|
||||
public Addon(String addon, String title, String author, String description) {
|
||||
this.addon = addon;
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(addon);
|
||||
dest.writeString(title);
|
||||
dest.writeString(author);
|
||||
dest.writeString(description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable creator
|
||||
*/
|
||||
public static final Parcelable.Creator<Addon> CREATOR = new Parcelable.Creator<Addon>() {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Addon createFromParcel(Parcel source) {
|
||||
return new Addon(source.readString(), source.readString(),
|
||||
source.readString(), source.readString());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Addon[] newArray(int size) {
|
||||
return new Addon[size];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
/**
|
||||
* Constants for interfacing with Astrid.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public class AstridApiConstants {
|
||||
|
||||
// --- General Constants
|
||||
|
||||
/**
|
||||
* Astrid broadcast base package name
|
||||
*/
|
||||
public static final String PACKAGE = "com.todoroo.astrid";
|
||||
|
||||
/**
|
||||
* Permission for reading tasks and receiving to GET_FILTERS intent
|
||||
*/
|
||||
public static final String PERMISSION_READ = PACKAGE + ".READ";
|
||||
|
||||
/**
|
||||
* Permission for writing and creating tasks
|
||||
*/
|
||||
public static final String PERMISSION_WRITE = PACKAGE + ".WRITE";
|
||||
|
||||
/**
|
||||
* Name of Astrid's publicly readable preference store
|
||||
*/
|
||||
public static final String PUBLIC_PREFS = "public";
|
||||
|
||||
// --- Content Provider
|
||||
|
||||
/**
|
||||
* URI to append to base content URI for making group-by queries
|
||||
*/
|
||||
public static final String GROUP_BY_URI = "/groupby/";
|
||||
|
||||
// --- Broadcast Extras
|
||||
|
||||
/**
|
||||
* Extras name for task id
|
||||
*/
|
||||
public static final String EXTRAS_TASK_ID = "task";
|
||||
|
||||
/**
|
||||
* Extras name for a response item broadcast to astrid
|
||||
*/
|
||||
public static final String EXTRAS_RESPONSE = "response";
|
||||
|
||||
/**
|
||||
* Extras name for plug-in identifier
|
||||
*/
|
||||
public static final String EXTRAS_ADDON = "addon";
|
||||
|
||||
/**
|
||||
* Extras name for whether task detail request is extended
|
||||
*/
|
||||
public static final String EXTRAS_EXTENDED = "extended";
|
||||
|
||||
/**
|
||||
* Extras name for old task due date
|
||||
*/
|
||||
public static final String EXTRAS_OLD_DUE_DATE= "oldDueDate";
|
||||
|
||||
/**
|
||||
* Extras name for new task due date
|
||||
*/
|
||||
public static final String EXTRAS_NEW_DUE_DATE = "newDueDate";
|
||||
|
||||
/**
|
||||
* Extras name for sync provider name
|
||||
*/
|
||||
public static final String EXTRAS_NAME = "name";
|
||||
|
||||
// --- Add-ons API
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent requesting add-ons
|
||||
*/
|
||||
public static final String BROADCAST_REQUEST_ADDONS = PACKAGE + ".REQUEST_ADDONS";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent sending add-ons back to Astrid
|
||||
* <li> EXTRAS_RESPONSE an {@link Addon} object
|
||||
*/
|
||||
public static final String BROADCAST_SEND_ADDONS = PACKAGE + ".SEND_ADDONS";
|
||||
|
||||
// --- Filters API
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent requesting filters
|
||||
*/
|
||||
public static final String BROADCAST_REQUEST_FILTERS = PACKAGE + ".REQUEST_FILTERS";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent sending filters back to Astrid
|
||||
* <li> EXTRAS_ADDON your add-on identifier </li>
|
||||
* <li> EXTRAS_RESPONSE an array of {@link FilterListItem}s </li>
|
||||
*/
|
||||
public static final String BROADCAST_SEND_FILTERS = PACKAGE + ".SEND_FILTERS";
|
||||
|
||||
// -- Custom criteria API
|
||||
|
||||
/**
|
||||
* Action name for a broadcast intent requesting custom filter criteria (e.g. "Due by, Tagged, Tag contains", etc.)
|
||||
*/
|
||||
public static final String BROADCAST_REQUEST_CUSTOM_FILTER_CRITERIA = PACKAGE + ".REQUEST_CUSTOM_FILTER_CRITERIA";
|
||||
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent sending custom filter criteria back to Astrid
|
||||
* <li> EXTRAS_ADDON you add-on identifier
|
||||
* <li> EXTRAS_RESPONSE an array of {@link CustomFilterCriterion} </li>
|
||||
*/
|
||||
public static final String BROADCAST_SEND_CUSTOM_FILTER_CRITERIA = PACKAGE + ".SEND_CUSTOM_FILTER_CRITERIA";
|
||||
|
||||
// --- Edit Controls API
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent requesting task edit controls
|
||||
* <li> EXTRAS_TASK_ID id of the task user is editing
|
||||
*/
|
||||
public static final String BROADCAST_REQUEST_EDIT_CONTROLS = PACKAGE + ".REQUEST_EDIT_CONTROLS";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent sending task edit controls back to Astrid
|
||||
* <li> EXTRAS_ADDON your add-on identifier
|
||||
* <li> EXTRAS_RESPONSE a {@link RemoteViews} with your edit controls
|
||||
*/
|
||||
public static final String BROADCAST_SEND_EDIT_CONTROLS = PACKAGE + ".SEND_EDIT_CONTROLS";
|
||||
|
||||
// --- Task Details API
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent requesting details for a task.
|
||||
* Extended details are displayed when a user presses on a task.
|
||||
*
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
* <li> EXTRAS_EXTENDED whether request is for standard or extended details
|
||||
*/
|
||||
public static final String BROADCAST_REQUEST_DETAILS = PACKAGE + ".REQUEST_DETAILS";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent sending details back to Astrid
|
||||
* <li> EXTRAS_ADDON your add-on identifier
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
* <li> EXTRAS_EXTENDED whether request is for standard or extended details
|
||||
* <li> EXTRAS_RESPONSE a String
|
||||
*/
|
||||
public static final String BROADCAST_SEND_DETAILS = PACKAGE + ".SEND_DETAILS";
|
||||
|
||||
// --- Sync Action API
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent requesting a listing of active
|
||||
* sync actions users can activate from the menu
|
||||
*/
|
||||
public static final String BROADCAST_REQUEST_SYNC_ACTIONS = PACKAGE + ".REQUEST_SYNC_ACTIONS";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent sending sync provider information back to Astrid
|
||||
* <li> EXTRAS_ADDON your add-on identifier
|
||||
* <li> EXTRAS_RESPONSE a {@link SyncAction} to invoke synchronization
|
||||
*/
|
||||
public static final String BROADCAST_SEND_SYNC_ACTIONS = PACKAGE + ".SEND_SYNC_ACTIONS";
|
||||
|
||||
// --- Task Actions API
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent requesting actions for a task
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
*/
|
||||
public static final String BROADCAST_REQUEST_ACTIONS = PACKAGE + ".REQUEST_ACTIONS";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent sending actions back to Astrid
|
||||
* <li> EXTRAS_ADDON your add-on identifier
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
* <li> EXTRAS_RESPONSE a String
|
||||
*/
|
||||
public static final String BROADCAST_SEND_ACTIONS = PACKAGE + ".SEND_ACTIONS";
|
||||
|
||||
// --- Task Decorations API
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent requesting task list decorations for a task
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
*/
|
||||
public static final String BROADCAST_REQUEST_DECORATIONS = PACKAGE + ".REQUEST_DECORATIONS";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent sending decorations back to Astrid
|
||||
* <li> EXTRAS_ADDON your add-on identifier
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
* <li> EXTRAS_RESPONSE a {@link TaskDecoration}
|
||||
*/
|
||||
public static final String BROADCAST_SEND_DECORATIONS = PACKAGE + ".SEND_DECORATIONS";
|
||||
|
||||
// --- Actions API
|
||||
|
||||
/**
|
||||
* Action name for intents to be displayed on task context menu
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
*/
|
||||
public static final String ACTION_TASK_CONTEXT_MENU = PACKAGE + ".CONTEXT_MENU";
|
||||
|
||||
/**
|
||||
* Action name for intents to be displayed on Astrid's task list menu
|
||||
* <li> EXTRAS_ADDON your add-on identifier
|
||||
* <li> EXTRAS_RESPONSE an array of {@link Intent}s
|
||||
*/
|
||||
public static final String ACTION_TASK_LIST_MENU = PACKAGE + ".TASK_LIST_MENU";
|
||||
|
||||
/**
|
||||
* Action name for intents to be displayed in Astrid's settings. By default,
|
||||
* your application will be put into the category named by your application,
|
||||
* but you can add a string meta-data with name "category" to override this.
|
||||
*/
|
||||
public static final String ACTION_SETTINGS = PACKAGE + ".SETTINGS";
|
||||
|
||||
// --- Events API
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent notifying add-ons that Astrid started up
|
||||
*/
|
||||
public static final String BROADCAST_EVENT_STARTUP = PACKAGE + ".STARTUP";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent notifying Astrid task list to refresh
|
||||
*/
|
||||
public static final String BROADCAST_EVENT_REFRESH = PACKAGE + ".REFRESH";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent notifying Astrid to clear detail cache
|
||||
* because an event occurred that potentially affects all tasks (e.g.
|
||||
* logging out of a sync provider). Use this call carefully, as loading
|
||||
* details can degrade the performance of Astrid.
|
||||
*/
|
||||
public static final String BROADCAST_EVENT_FLUSH_DETAILS = PACKAGE + ".FLUSH_DETAILS";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent notifying that task was created or
|
||||
* title was changed
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
*/
|
||||
public static final String BROADCAST_EVENT_TASK_LIST_UPDATED = PACKAGE + ".TASK_LIST_UPDATED";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent notifying that task was completed
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
*/
|
||||
public static final String BROADCAST_EVENT_TASK_COMPLETED = PACKAGE + ".TASK_COMPLETED";
|
||||
|
||||
/**
|
||||
* Action name for broadcast intent notifying that task was created from repeating template
|
||||
* <li> EXTRAS_TASK_ID id of the task
|
||||
* <li> EXTRAS_OLD_DUE_DATE task old due date (could be 0)
|
||||
* <li> EXTRAS_NEW_DUE_DATE task new due date (will not be 0)
|
||||
*/
|
||||
public static final String BROADCAST_EVENT_TASK_REPEATED = PACKAGE + ".TASK_REPEATED";
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* CustomFilterCriteria allow users to build a custom filter by chaining
|
||||
* together criteria
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
abstract public class CustomFilterCriterion implements Parcelable {
|
||||
|
||||
/**
|
||||
* Criteria Identifier. This identifier allows saved filters to be reloaded.
|
||||
* <p>
|
||||
* e.g "duedate"
|
||||
*/
|
||||
public String identifier;
|
||||
|
||||
/**
|
||||
* Criteria Title. If the title contains ?, this is replaced by the entry
|
||||
* label string selected.
|
||||
* <p>
|
||||
* e.g "Due: ?"
|
||||
*/
|
||||
public String text;
|
||||
|
||||
/**
|
||||
* Criterion SQL. This query should return task id's. If this contains
|
||||
* ?, it will be replaced by the entry value
|
||||
* <p>
|
||||
* Examples:
|
||||
* <ul>
|
||||
* <li><code>SELECT _id FROM tasks WHERE dueDate <= ?</code>
|
||||
* <li><code>SELECT task FROM metadata WHERE value = '?'</code>
|
||||
* </ul>
|
||||
*/
|
||||
public String sql;
|
||||
|
||||
/**
|
||||
* Values to apply to a task when quick-adding a task from a filter
|
||||
* created from this criterion. ? will be replaced with the entry value.
|
||||
* For example, when a user views tasks tagged 'ABC', the
|
||||
* tasks they create should also be tagged 'ABC'. If set to null, no
|
||||
* additional values will be stored for a task.
|
||||
*/
|
||||
public ContentValues valuesForNewTasks = null;
|
||||
|
||||
/**
|
||||
* Icon for this criteria. Can be null for no bitmap
|
||||
*/
|
||||
public Bitmap icon;
|
||||
|
||||
/**
|
||||
* Criteria name. This is displayed when users are selecting a criteria
|
||||
*/
|
||||
public String name;
|
||||
|
||||
// --- parcelable utilities
|
||||
|
||||
/**
|
||||
* Utility method to write to parcel
|
||||
*/
|
||||
public void writeToParcel(Parcel dest) {
|
||||
dest.writeString(identifier);
|
||||
dest.writeString(text);
|
||||
dest.writeString(sql);
|
||||
dest.writeParcelable(valuesForNewTasks, 0);
|
||||
dest.writeParcelable(icon, 0);
|
||||
dest.writeString(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to read from parcel
|
||||
*/
|
||||
public void readFromParcel(Parcel source) {
|
||||
identifier = source.readString();
|
||||
text = source.readString();
|
||||
sql = source.readString();
|
||||
valuesForNewTasks = (ContentValues)source.readParcelable(ContentValues.class.getClassLoader());
|
||||
icon = (Bitmap)source.readParcelable(Bitmap.class.getClassLoader());
|
||||
name = source.readString();
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.todoroo.andlib.sql.QueryTemplate;
|
||||
|
||||
/**
|
||||
* A <code>FilterListFilter</code> allows users to display tasks that have
|
||||
* something in common.
|
||||
* <p>
|
||||
* A plug-in can expose new <code>FilterListFilter</code>s to the system by
|
||||
* responding to the <code>com.todoroo.astrid.GET_FILTERS</code> broadcast
|
||||
* intent.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class Filter extends FilterListItem {
|
||||
|
||||
// --- constants
|
||||
|
||||
/** Constant for valuesForNewTasks to indicate the value should be replaced
|
||||
* with the current time as long */
|
||||
public static final long VALUE_NOW = Long.MIN_VALUE + 1;
|
||||
|
||||
// --- instance variables
|
||||
|
||||
/**
|
||||
* Expanded title of this filter. This is displayed at the top
|
||||
* of the screen when user is viewing this filter.
|
||||
* <p>
|
||||
* e.g "Tasks With Notes"
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* {@link PermaSql} query for this filter. The query will be appended to the select
|
||||
* statement after "<code>SELECT fields FROM table %s</code>". It is
|
||||
* recommended that you use a {@link QueryTemplate} to construct your
|
||||
* query.
|
||||
* <p>
|
||||
* Examples:
|
||||
* <ul>
|
||||
* <li><code>"WHERE completionDate = 0"</code>
|
||||
* <li><code>"INNER JOIN " +
|
||||
* Constants.TABLE_METADATA + " ON metadata.task = tasks.id WHERE
|
||||
* metadata.namespace = " + NAMESPACE + " AND metadata.key = 'a' AND
|
||||
* metadata.value = 'b' GROUP BY tasks.id ORDER BY tasks.title"</code>
|
||||
* </ul>
|
||||
*/
|
||||
public String sqlQuery;
|
||||
|
||||
/**
|
||||
* Values to apply to a task when quick-adding a task from this filter.
|
||||
* For example, when a user views tasks tagged 'ABC', the
|
||||
* tasks they create should also be tagged 'ABC'. If set to null, no
|
||||
* additional values will be stored for a task. Can use {@link PermaSql}
|
||||
*/
|
||||
public ContentValues valuesForNewTasks = null;
|
||||
|
||||
/**
|
||||
* Utility constructor for creating a Filter object
|
||||
* @param listingTitle
|
||||
* Title of this item as displayed on the lists page, e.g. Inbox
|
||||
* @param title
|
||||
* Expanded title of this filter when user is viewing this
|
||||
* filter, e.g. Inbox (20 tasks)
|
||||
* @param sqlQuery
|
||||
* SQL query for this list (see {@link #sqlQuery} for examples).
|
||||
* @param valuesForNewTasks
|
||||
* see {@link #sqlForNewTasks}
|
||||
*/
|
||||
public Filter(String listingTitle, String title,
|
||||
QueryTemplate sqlQuery, ContentValues valuesForNewTasks) {
|
||||
this(listingTitle, title, sqlQuery == null ? null : sqlQuery.toString(),
|
||||
valuesForNewTasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility constructor for creating a Filter object
|
||||
* @param listingTitle
|
||||
* Title of this item as displayed on the lists page, e.g. Inbox
|
||||
* @param title
|
||||
* Expanded title of this filter when user is viewing this
|
||||
* filter, e.g. Inbox (20 tasks)
|
||||
* @param sqlQuery
|
||||
* SQL query for this list (see {@link #sqlQuery} for examples).
|
||||
* @param valuesForNewTasks
|
||||
* see {@link #sqlForNewTasks}
|
||||
*/
|
||||
public Filter(String listingTitle, String title,
|
||||
String sqlQuery, ContentValues valuesForNewTasks) {
|
||||
this.listingTitle = listingTitle;
|
||||
this.title = title;
|
||||
this.sqlQuery = sqlQuery;
|
||||
this.valuesForNewTasks = valuesForNewTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility constructor
|
||||
*
|
||||
* @param plugin
|
||||
* {@link Addon} identifier that encompasses object
|
||||
*/
|
||||
protected Filter() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// --- parcelable
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeString(title);
|
||||
dest.writeString(sqlQuery);
|
||||
dest.writeParcelable(valuesForNewTasks, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromParcel(Parcel source) {
|
||||
super.readFromParcel(source);
|
||||
title = source.readString();
|
||||
sqlQuery = source.readString();
|
||||
valuesForNewTasks = source.readParcelable(ContentValues.class.getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable Creator Object
|
||||
*/
|
||||
public static final Parcelable.Creator<Filter> CREATOR = new Parcelable.Creator<Filter>() {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Filter createFromParcel(Parcel source) {
|
||||
Filter item = new Filter();
|
||||
item.readFromParcel(source);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Filter[] newArray(int size) {
|
||||
return new Filter[size];
|
||||
}
|
||||
|
||||
};
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* A <code>FilterCategory</code> groups common {@link Filter}s and allows
|
||||
* a user to show/hide all of its children.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class FilterCategory extends FilterListItem {
|
||||
|
||||
/**
|
||||
* {@link Filter}s contained by this category
|
||||
*/
|
||||
public Filter[] children;
|
||||
|
||||
/**
|
||||
* Constructor for creating a new FilterCategory
|
||||
* @param listingTitle
|
||||
* Title of this item as displayed on the lists page, e.g. Inbox
|
||||
* @param children
|
||||
* filters belonging to this category
|
||||
*/
|
||||
public FilterCategory(String listingTitle, Filter[] children) {
|
||||
this.listingTitle = listingTitle;
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for creating a new FilterCategory
|
||||
*
|
||||
* @param plugin
|
||||
* {@link Addon} identifier that encompasses object
|
||||
*/
|
||||
protected FilterCategory() {
|
||||
//
|
||||
}
|
||||
|
||||
// --- parcelable
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeParcelableArray(children, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable creator
|
||||
*/
|
||||
public static final Parcelable.Creator<FilterCategory> CREATOR = new Parcelable.Creator<FilterCategory>() {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public FilterCategory createFromParcel(Parcel source) {
|
||||
FilterCategory item = new FilterCategory();
|
||||
item.readFromParcel(source);
|
||||
|
||||
Parcelable[] parcelableChildren = source.readParcelableArray(
|
||||
FilterCategory.class.getClassLoader());
|
||||
item.children = new Filter[parcelableChildren.length];
|
||||
for(int i = 0; i < item.children.length; i++) {
|
||||
if(parcelableChildren[i] instanceof FilterListItem)
|
||||
item.children[i] = (Filter) parcelableChildren[i];
|
||||
else
|
||||
item.children[i] = null;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public FilterCategory[] newArray(int size) {
|
||||
return new FilterCategory[size];
|
||||
}
|
||||
|
||||
};
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Section Header for Filter List
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class FilterListHeader extends FilterListItem {
|
||||
|
||||
/**
|
||||
* Constructor for creating a new FilterListHeader
|
||||
* @param listingTitle
|
||||
* @param listingIconResource
|
||||
* @param priority
|
||||
*/
|
||||
public FilterListHeader(String listingTitle) {
|
||||
this.listingTitle = listingTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for creating a new FilterListHeader
|
||||
*
|
||||
* @param plugin
|
||||
* {@link Addon} identifier that encompasses object
|
||||
*/
|
||||
protected FilterListHeader() {
|
||||
//
|
||||
}
|
||||
|
||||
// --- parcelable
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<FilterListHeader> CREATOR = new Parcelable.Creator<FilterListHeader>() {
|
||||
|
||||
public FilterListHeader createFromParcel(Parcel source) {
|
||||
FilterListHeader item = new FilterListHeader();
|
||||
item.readFromParcel(source);
|
||||
return item;
|
||||
}
|
||||
|
||||
public FilterListHeader[] newArray(int size) {
|
||||
return new FilterListHeader[size];
|
||||
}
|
||||
|
||||
};
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Represents an item displayed by Astrid's FilterListActivity
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
abstract public class FilterListItem implements Parcelable {
|
||||
|
||||
/**
|
||||
* Title of this item displayed on the Filters page
|
||||
*/
|
||||
public String listingTitle = null;
|
||||
|
||||
/**
|
||||
* Bitmap for icon used on listing page. <code>null</code> => no icon
|
||||
*/
|
||||
public Bitmap listingIcon = null;
|
||||
|
||||
/**
|
||||
* Text Color. <code>0</code> => default color
|
||||
*/
|
||||
public int color = 0;
|
||||
|
||||
/**
|
||||
* Context Menu labels. The context menu will be displayed when users
|
||||
* long-press on this filter list item.
|
||||
*/
|
||||
public String contextMenuLabels[] = new String[0];
|
||||
|
||||
/**
|
||||
* Context menu intents. This intent will be started when the corresponding
|
||||
* content menu label is invoked. This array must be the same size as
|
||||
* the contextMenuLabels array.
|
||||
*/
|
||||
public Intent contextMenuIntents[] = new Intent[0];
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(listingTitle);
|
||||
dest.writeParcelable(listingIcon, 0);
|
||||
dest.writeInt(color);
|
||||
|
||||
// write array lengths before arrays
|
||||
dest.writeStringArray(contextMenuLabels);
|
||||
dest.writeTypedArray(contextMenuIntents, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to read FilterListItem properties from a parcel.
|
||||
*
|
||||
* @param source
|
||||
*/
|
||||
public void readFromParcel(Parcel source) {
|
||||
listingTitle = source.readString();
|
||||
listingIcon = source.readParcelable(Bitmap.class.getClassLoader());
|
||||
color = source.readInt();
|
||||
|
||||
contextMenuLabels = source.createStringArray();
|
||||
contextMenuIntents = source.createTypedArray(Intent.CREATOR);
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentValues;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.todoroo.andlib.sql.QueryTemplate;
|
||||
|
||||
public class FilterWithCustomIntent extends Filter {
|
||||
|
||||
public ComponentName customTaskList = null;
|
||||
public Bundle customExtras = null;
|
||||
|
||||
protected FilterWithCustomIntent() {
|
||||
super();
|
||||
}
|
||||
|
||||
public FilterWithCustomIntent(String listingTitle, String title,
|
||||
QueryTemplate sqlQuery, ContentValues valuesForNewTasks) {
|
||||
super(listingTitle, title, sqlQuery, valuesForNewTasks);
|
||||
}
|
||||
|
||||
public FilterWithCustomIntent(String listingTitle, String title,
|
||||
String sqlQuery, ContentValues valuesForNewTasks) {
|
||||
super(listingTitle, title, sqlQuery, valuesForNewTasks);
|
||||
}
|
||||
|
||||
|
||||
// --- parcelable
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeParcelable(customTaskList, 0);
|
||||
dest.writeParcelable(customExtras, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromParcel(Parcel source) {
|
||||
super.readFromParcel(source);
|
||||
customTaskList = source.readParcelable(ComponentName.class.getClassLoader());
|
||||
customExtras = source.readParcelable(Bundle.class.getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable Creator Object
|
||||
*/
|
||||
@SuppressWarnings("hiding")
|
||||
public static final Parcelable.Creator<FilterWithCustomIntent> CREATOR = new Parcelable.Creator<FilterWithCustomIntent>() {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public FilterWithCustomIntent createFromParcel(Parcel source) {
|
||||
FilterWithCustomIntent item = new FilterWithCustomIntent();
|
||||
item.readFromParcel(source);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public FilterWithCustomIntent[] newArray(int size) {
|
||||
return new FilterWithCustomIntent[size];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
|
||||
/**
|
||||
* Special filter that launches a PendingIntent when accessed.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public final class IntentFilter extends FilterListItem implements Parcelable {
|
||||
|
||||
/**
|
||||
* PendingIntent to trigger when pressed
|
||||
*/
|
||||
public PendingIntent intent;
|
||||
|
||||
/**
|
||||
* Constructor for creating a new IntentFilter
|
||||
*
|
||||
* @param listingTitle
|
||||
* Title of this item as displayed on the lists page, e.g. Inbox
|
||||
* @param intent
|
||||
* intent to load
|
||||
*/
|
||||
public IntentFilter(String listingTitle, PendingIntent intent) {
|
||||
this.listingTitle = listingTitle;
|
||||
this.intent = intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for creating a new IntentFilter used internally
|
||||
*/
|
||||
protected IntentFilter(PendingIntent intent) {
|
||||
this.intent = intent;
|
||||
}
|
||||
|
||||
// --- parcelable
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(intent, 0);
|
||||
super.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable creator
|
||||
*/
|
||||
public static final Parcelable.Creator<IntentFilter> CREATOR = new Parcelable.Creator<IntentFilter>() {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public IntentFilter createFromParcel(Parcel source) {
|
||||
IntentFilter item = new IntentFilter((PendingIntent) source.readParcelable(
|
||||
PendingIntent.class.getClassLoader()));
|
||||
item.readFromParcel(source);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public IntentFilter[] newArray(int size) {
|
||||
return new IntentFilter[size];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* CustomFilterCriteria allow users to build a custom filter by chaining
|
||||
* together criteria
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class MultipleSelectCriterion extends CustomFilterCriterion implements Parcelable {
|
||||
|
||||
/**
|
||||
* Array of entries for user to select from
|
||||
*/
|
||||
public String[] entryTitles;
|
||||
|
||||
/**
|
||||
* Array of entry values corresponding to entries
|
||||
*/
|
||||
public String[] entryValues;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new CustomFilterCriteria object
|
||||
*
|
||||
* @param title
|
||||
* @param sql
|
||||
* @param valuesForNewTasks
|
||||
* @param entryTitles
|
||||
* @param entryValues
|
||||
* @param icon
|
||||
* @param name
|
||||
*/
|
||||
public MultipleSelectCriterion(String identifier, String title, String sql,
|
||||
ContentValues valuesForNewTasks, String[] entryTitles,
|
||||
String[] entryValues, Bitmap icon, String name) {
|
||||
this.identifier = identifier;
|
||||
this.text = title;
|
||||
this.sql = sql;
|
||||
this.valuesForNewTasks = valuesForNewTasks;
|
||||
this.entryTitles = entryTitles;
|
||||
this.entryValues = entryValues;
|
||||
this.icon = icon;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected MultipleSelectCriterion() {
|
||||
// constructor for inflating from parceling
|
||||
}
|
||||
|
||||
// --- parcelable
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeStringArray(entryTitles);
|
||||
dest.writeStringArray(entryValues);
|
||||
super.writeToParcel(dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable Creator Object
|
||||
*/
|
||||
public static final Parcelable.Creator<MultipleSelectCriterion> CREATOR = new Parcelable.Creator<MultipleSelectCriterion>() {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public MultipleSelectCriterion createFromParcel(Parcel source) {
|
||||
MultipleSelectCriterion item = new MultipleSelectCriterion();
|
||||
item.entryTitles = source.createStringArray();
|
||||
item.entryValues = source.createStringArray();
|
||||
item.readFromParcel(source);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public MultipleSelectCriterion[] newArray(int size) {
|
||||
return new MultipleSelectCriterion[size];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.todoroo.andlib.utility.DateUtilities;
|
||||
|
||||
/**
|
||||
* PermaSql allows for creating SQL statements that can be saved and used
|
||||
* later without dates getting stale. It also allows these values to be
|
||||
* used in
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public final class PermaSql {
|
||||
|
||||
// --- placeholder strings
|
||||
|
||||
/** value to be replaced with the current time as long */
|
||||
public static final String VALUE_NOW = "NOW()"; //$NON-NLS-1$
|
||||
|
||||
/** value to be replaced by end of day as long */
|
||||
public static final String VALUE_EOD = "EOD()"; //$NON-NLS-1$
|
||||
|
||||
/** value to be replaced by end of day yesterday as long */
|
||||
public static final String VALUE_EOD_YESTERDAY = "EODY()"; //$NON-NLS-1$
|
||||
|
||||
/** value to be replaced by end of day tomorrow as long */
|
||||
public static final String VALUE_EOD_TOMORROW = "EODT()"; //$NON-NLS-1$
|
||||
|
||||
/** value to be replaced by end of day day after tomorrow as long */
|
||||
public static final String VALUE_EOD_DAY_AFTER = "EODTT()"; //$NON-NLS-1$
|
||||
|
||||
/** value to be replaced by end of day next week as long */
|
||||
public static final String VALUE_EOD_NEXT_WEEK = "EODW()"; //$NON-NLS-1$
|
||||
|
||||
/** value to be replaced by approximate end of day next month as long */
|
||||
public static final String VALUE_EOD_NEXT_MONTH = "EODM()"; //$NON-NLS-1$
|
||||
|
||||
/** Replace placeholder strings with actual */
|
||||
public static String replacePlaceholders(String value) {
|
||||
if(value.contains(VALUE_NOW))
|
||||
value = value.replace(VALUE_NOW, Long.toString(DateUtilities.now()));
|
||||
if(value.contains(VALUE_EOD) || value.contains(VALUE_EOD_DAY_AFTER) ||
|
||||
value.contains(VALUE_EOD_NEXT_WEEK) || value.contains(VALUE_EOD_TOMORROW) ||
|
||||
value.contains(VALUE_EOD_YESTERDAY) || value.contains(VALUE_EOD_NEXT_MONTH)) {
|
||||
Date date = new Date();
|
||||
date.setHours(23);
|
||||
date.setMinutes(59);
|
||||
date.setSeconds(59);
|
||||
long time = date.getTime() / 1000l * 1000l; // chop milliseconds off
|
||||
value = value.replace(VALUE_EOD_YESTERDAY, Long.toString(time - DateUtilities.ONE_DAY));
|
||||
value = value.replace(VALUE_EOD, Long.toString(time));
|
||||
value = value.replace(VALUE_EOD_TOMORROW, Long.toString(time + DateUtilities.ONE_DAY));
|
||||
value = value.replace(VALUE_EOD_DAY_AFTER, Long.toString(time + 2 * DateUtilities.ONE_DAY));
|
||||
value = value.replace(VALUE_EOD_NEXT_WEEK, Long.toString(time + 7 * DateUtilities.ONE_DAY));
|
||||
value = value.replace(VALUE_EOD_NEXT_MONTH, Long.toString(time + 30 * DateUtilities.ONE_DAY));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Represents an intent that can be called to perform synchronization
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class SyncAction implements Parcelable {
|
||||
|
||||
/**
|
||||
* Label
|
||||
*/
|
||||
public String label = null;
|
||||
|
||||
/**
|
||||
* Intent to call when invoking this operation
|
||||
*/
|
||||
public PendingIntent intent = null;
|
||||
|
||||
/**
|
||||
* Create an EditOperation object
|
||||
*
|
||||
* @param label
|
||||
* label to display
|
||||
* @param intent
|
||||
* intent to invoke
|
||||
*/
|
||||
public SyncAction(String label, PendingIntent intent) {
|
||||
super();
|
||||
this.label = label;
|
||||
this.intent = intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label of this action
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return label.hashCode() ^ intent.getTargetPackage().hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* We consider two sync actions equal if target package is identical
|
||||
* and the labels are the same. This prevents duplicate pendingIntents
|
||||
* from creating multiple SyncAction objects.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(!(o instanceof SyncAction))
|
||||
return false;
|
||||
SyncAction other = (SyncAction) o;
|
||||
return label.equals(other.label) && intent.getTargetPackage().equals(other.intent.getTargetPackage());
|
||||
}
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(label);
|
||||
dest.writeParcelable(intent, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable creator
|
||||
*/
|
||||
public static final Parcelable.Creator<SyncAction> CREATOR = new Parcelable.Creator<SyncAction>() {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public SyncAction createFromParcel(Parcel source) {
|
||||
return new SyncAction(source.readString(), (PendingIntent)source.readParcelable(
|
||||
PendingIntent.class.getClassLoader()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public SyncAction[] newArray(int size) {
|
||||
return new SyncAction[size];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Represents an intent that can be called on a task
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class TaskAction implements Parcelable {
|
||||
|
||||
/**
|
||||
* Label
|
||||
*/
|
||||
public String text = null;
|
||||
|
||||
/**
|
||||
* Intent to call when invoking this operation
|
||||
*/
|
||||
public PendingIntent intent = null;
|
||||
|
||||
/**
|
||||
* Quick action icon
|
||||
*/
|
||||
public Bitmap icon = null;
|
||||
|
||||
/**
|
||||
* Create an EditOperation object
|
||||
*
|
||||
* @param text
|
||||
* label to display
|
||||
* @param intent
|
||||
* intent to invoke. {@link #EXTRAS_TASK_ID} will be passed
|
||||
*/
|
||||
public TaskAction(String text, PendingIntent intent, Bitmap icon) {
|
||||
super();
|
||||
this.text = text;
|
||||
this.intent = intent;
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(text);
|
||||
dest.writeParcelable(intent, 0);
|
||||
dest.writeParcelable(icon, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable creator
|
||||
*/
|
||||
public static final Parcelable.Creator<TaskAction> CREATOR = new Parcelable.Creator<TaskAction>() {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TaskAction createFromParcel(Parcel source) {
|
||||
return new TaskAction(source.readString(),
|
||||
(PendingIntent)source.readParcelable(PendingIntent.class.getClassLoader()),
|
||||
(Bitmap)source.readParcelable(Bitmap.class.getClassLoader()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TaskAction[] newArray(int size) {
|
||||
return new TaskAction[size];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.RemoteViews.RemoteView;
|
||||
|
||||
/**
|
||||
* Represents a line of text displayed in the Task List
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public final class TaskDecoration implements Parcelable {
|
||||
|
||||
/**
|
||||
* Place decoration between completion box and task title
|
||||
*/
|
||||
public static final int POSITION_LEFT = 0;
|
||||
|
||||
/**
|
||||
* Place decoration between task title and importance bar
|
||||
*/
|
||||
public static final int POSITION_RIGHT = 1;
|
||||
|
||||
/**
|
||||
* {@link RemoteView} decoration
|
||||
*/
|
||||
public RemoteViews decoration = null;
|
||||
|
||||
/**
|
||||
* Decoration position
|
||||
*/
|
||||
public int position = POSITION_LEFT;
|
||||
|
||||
/**
|
||||
* Decorated task background color. 0 is default
|
||||
*/
|
||||
public int color = 0;
|
||||
|
||||
/**
|
||||
* Creates a TaskDetail object
|
||||
* @param text
|
||||
* text to display
|
||||
* @param color
|
||||
* color to use for text. Use <code>0</code> for default color
|
||||
*/
|
||||
public TaskDecoration(RemoteViews decoration, int position, int color) {
|
||||
this.decoration = decoration;
|
||||
this.position = position;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(decoration, 0);
|
||||
dest.writeInt(position);
|
||||
dest.writeInt(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable creator
|
||||
*/
|
||||
public static final Parcelable.Creator<TaskDecoration> CREATOR = new Parcelable.Creator<TaskDecoration>() {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TaskDecoration createFromParcel(Parcel source) {
|
||||
return new TaskDecoration((RemoteViews)source.readParcelable(
|
||||
RemoteViews.class.getClassLoader()),
|
||||
source.readInt(), source.readInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TaskDecoration[] newArray(int size) {
|
||||
return new TaskDecoration[size];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* CustomFilterCriteria allow users to build a custom filter by chaining
|
||||
* together criteria
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class TextInputCriterion extends CustomFilterCriterion implements Parcelable {
|
||||
|
||||
/**
|
||||
* Text area prompt
|
||||
*/
|
||||
public String prompt;
|
||||
|
||||
/**
|
||||
* Text area hint
|
||||
*/
|
||||
public String hint;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new CustomFilterCriteria object
|
||||
*
|
||||
* @param identifier
|
||||
* @param title
|
||||
* @param sql
|
||||
* @param valuesForNewTasks
|
||||
* @param prompt
|
||||
* @param hint
|
||||
* @param icon
|
||||
* @param name
|
||||
*/
|
||||
public TextInputCriterion(String identifier, String title, String sql,
|
||||
ContentValues valuesForNewTasks, String prompt, String hint,
|
||||
Bitmap icon, String name) {
|
||||
this.identifier = identifier;
|
||||
this.text = title;
|
||||
this.sql = sql;
|
||||
this.valuesForNewTasks = valuesForNewTasks;
|
||||
this.prompt = prompt;
|
||||
this.hint = hint;
|
||||
this.icon = icon;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected TextInputCriterion() {
|
||||
// constructor for inflating from parceling
|
||||
}
|
||||
|
||||
// --- parcelable
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(prompt);
|
||||
dest.writeString(hint);
|
||||
super.writeToParcel(dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable Creator Object
|
||||
*/
|
||||
public static final Parcelable.Creator<TextInputCriterion> CREATOR = new Parcelable.Creator<TextInputCriterion>() {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TextInputCriterion createFromParcel(Parcel source) {
|
||||
TextInputCriterion item = new TextInputCriterion();
|
||||
item.prompt = source.readString();
|
||||
item.hint = source.readString();
|
||||
item.readFromParcel(source);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TextInputCriterion[] newArray(int size) {
|
||||
return new TextInputCriterion[size];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Astrid API constants and container packages
|
||||
*/
|
||||
package com.todoroo.astrid.api;
|
@ -0,0 +1,73 @@
|
||||
package com.todoroo.astrid.core;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.todoroo.astrid.api.FilterListItem;
|
||||
|
||||
/**
|
||||
* Special filter that triggers the search functionality when accessed.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class SearchFilter extends FilterListItem {
|
||||
|
||||
/**
|
||||
* Constructor for creating a new SearchFilter
|
||||
*
|
||||
* @param listingTitle
|
||||
* Title of this item as displayed on the lists page, e.g. Inbox
|
||||
*/
|
||||
public SearchFilter(String listingTitle) {
|
||||
this.listingTitle = listingTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for creating a new SearchFilter
|
||||
*/
|
||||
protected SearchFilter() {
|
||||
//
|
||||
}
|
||||
|
||||
// --- parcelable
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable creator
|
||||
*/
|
||||
public static final Parcelable.Creator<SearchFilter> CREATOR = new Parcelable.Creator<SearchFilter>() {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public SearchFilter createFromParcel(Parcel source) {
|
||||
SearchFilter item = new SearchFilter();
|
||||
item.readFromParcel(source);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public SearchFilter[] newArray(int size) {
|
||||
return new SearchFilter[size];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package com.todoroo.astrid.core;
|
||||
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
import com.todoroo.andlib.sql.Functions;
|
||||
import com.todoroo.andlib.sql.Order;
|
||||
import com.todoroo.andlib.utility.DateUtilities;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import com.todoroo.astrid.data.TaskApiDao.TaskCriteria;
|
||||
|
||||
/**
|
||||
* Helpers for sorting a list of tasks
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class SortHelper {
|
||||
|
||||
public static final int FLAG_REVERSE_SORT = 1 << 0;
|
||||
public static final int FLAG_SHOW_COMPLETED = 1 << 1;
|
||||
public static final int FLAG_SHOW_HIDDEN = 1 << 2;
|
||||
public static final int FLAG_SHOW_DELETED = 1 << 3;
|
||||
|
||||
public static final int SORT_AUTO = 0;
|
||||
public static final int SORT_ALPHA = 1;
|
||||
public static final int SORT_DUE = 2;
|
||||
public static final int SORT_IMPORTANCE = 3;
|
||||
public static final int SORT_MODIFIED = 4;
|
||||
|
||||
/** preference key for sort flags. stored in public prefs */
|
||||
public static final String PREF_SORT_FLAGS = "sort_flags"; //$NON-NLS-1$
|
||||
|
||||
/** preference key for sort sort. stored in public prefs */
|
||||
public static final String PREF_SORT_SORT = "sort_sort"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Takes a SQL query, and if there isn't already an order, creates an order.
|
||||
* @param originalSql
|
||||
* @param flags
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static String adjustQueryForFlagsAndSort(String originalSql, int flags, int sort) {
|
||||
// sort
|
||||
if(originalSql == null)
|
||||
originalSql = "";
|
||||
if(!originalSql.toUpperCase().contains("ORDER BY")) {
|
||||
Order order;
|
||||
switch(sort) {
|
||||
case SORT_ALPHA:
|
||||
order = Order.asc(Functions.upper(Task.TITLE));
|
||||
break;
|
||||
case SORT_DUE:
|
||||
order = Order.asc(Functions.caseStatement(Task.DUE_DATE.eq(0),
|
||||
DateUtilities.now()*2, Task.DUE_DATE) + "+" + Task.IMPORTANCE +
|
||||
"+3*" + Task.COMPLETION_DATE);
|
||||
break;
|
||||
case SORT_IMPORTANCE:
|
||||
order = Order.asc(Task.IMPORTANCE + "*" + (2*DateUtilities.now()) + //$NON-NLS-1$
|
||||
"+" + Functions.caseStatement(Task.DUE_DATE.eq(0), //$NON-NLS-1$
|
||||
Functions.now() + "+" + DateUtilities.ONE_WEEK, //$NON-NLS-1$
|
||||
Task.DUE_DATE) + "+8*" + Task.COMPLETION_DATE);
|
||||
break;
|
||||
case SORT_MODIFIED:
|
||||
order = Order.desc(Task.MODIFICATION_DATE);
|
||||
break;
|
||||
default:
|
||||
order = defaultTaskOrder();
|
||||
}
|
||||
|
||||
if((flags & FLAG_REVERSE_SORT) > 0)
|
||||
order = order.reverse();
|
||||
originalSql += " ORDER BY " + order;
|
||||
}
|
||||
|
||||
// flags
|
||||
if((flags & FLAG_SHOW_COMPLETED) > 0)
|
||||
originalSql = originalSql.replace(Task.COMPLETION_DATE.eq(0).toString(),
|
||||
Criterion.all.toString());
|
||||
if((flags & FLAG_SHOW_HIDDEN) > 0)
|
||||
originalSql = originalSql.replace(TaskCriteria.isVisible().toString(),
|
||||
Criterion.all.toString());
|
||||
if((flags & FLAG_SHOW_DELETED) > 0)
|
||||
originalSql = originalSql.replace(Task.DELETION_DATE.eq(0).toString(),
|
||||
Criterion.all.toString());
|
||||
|
||||
return originalSql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns SQL task ordering that is astrid's default algorithm
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public static Order defaultTaskOrder() {
|
||||
return Order.asc(Functions.caseStatement(Task.DUE_DATE.eq(0),
|
||||
DateUtilities.now() + DateUtilities.ONE_WEEK,
|
||||
Task.DUE_DATE) + " + 200000000 * " +
|
||||
Task.IMPORTANCE + " + 2*" + Task.COMPLETION_DATE);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.data;
|
||||
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.todoroo.andlib.data.AbstractModel;
|
||||
import com.todoroo.andlib.data.Property;
|
||||
import com.todoroo.andlib.data.Table;
|
||||
import com.todoroo.andlib.data.TodorooCursor;
|
||||
import com.todoroo.andlib.data.Property.LongProperty;
|
||||
import com.todoroo.andlib.data.Property.StringProperty;
|
||||
import com.todoroo.astrid.api.AstridApiConstants;
|
||||
|
||||
/**
|
||||
* Data Model which represents a piece of metadata associated with a task
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public class Metadata extends AbstractModel {
|
||||
|
||||
// --- table
|
||||
|
||||
/** table for this model */
|
||||
public static final Table TABLE = new Table("metadata", Metadata.class);
|
||||
|
||||
/** content uri for this model */
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://" + AstridApiConstants.PACKAGE + "/" +
|
||||
TABLE.name);
|
||||
|
||||
// --- properties
|
||||
|
||||
/** ID */
|
||||
public static final LongProperty ID = new LongProperty(
|
||||
TABLE, ID_PROPERTY_NAME);
|
||||
|
||||
/** Associated Task */
|
||||
public static final LongProperty TASK = new LongProperty(
|
||||
TABLE, "task");
|
||||
|
||||
/** Metadata Key */
|
||||
public static final StringProperty KEY = new StringProperty(
|
||||
TABLE, "key");
|
||||
|
||||
/** Metadata Text Value Column 1 */
|
||||
public static final StringProperty VALUE1 = new StringProperty(
|
||||
TABLE, "value");
|
||||
|
||||
/** Metadata Text Value Column 2 */
|
||||
public static final StringProperty VALUE2 = new StringProperty(
|
||||
TABLE, "value2");
|
||||
|
||||
/** Metadata Text Value Column 3 */
|
||||
public static final StringProperty VALUE3 = new StringProperty(
|
||||
TABLE, "value3");
|
||||
|
||||
/** Metadata Text Value Column 4 */
|
||||
public static final StringProperty VALUE4 = new StringProperty(
|
||||
TABLE, "value4");
|
||||
|
||||
/** Metadata Text Value Column 5 */
|
||||
public static final StringProperty VALUE5 = new StringProperty(
|
||||
TABLE, "value5");
|
||||
|
||||
/** List of all properties for this model */
|
||||
public static final Property<?>[] PROPERTIES = generateProperties(Metadata.class);
|
||||
|
||||
// --- defaults
|
||||
|
||||
/** Default values container */
|
||||
private static final ContentValues defaultValues = new ContentValues();
|
||||
|
||||
@Override
|
||||
public ContentValues getDefaultValues() {
|
||||
return defaultValues;
|
||||
}
|
||||
|
||||
// --- data access boilerplate
|
||||
|
||||
public Metadata() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Metadata(TodorooCursor<Metadata> cursor) {
|
||||
this();
|
||||
readPropertiesFromCursor(cursor);
|
||||
}
|
||||
|
||||
public void readFromCursor(TodorooCursor<Metadata> cursor) {
|
||||
super.readPropertiesFromCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return getIdHelper(ID);
|
||||
};
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
private static final Creator<Metadata> CREATOR = new ModelCreator<Metadata>(Metadata.class);
|
||||
|
||||
@Override
|
||||
protected Creator<? extends AbstractModel> getCreator() {
|
||||
return CREATOR;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package com.todoroo.astrid.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
|
||||
import com.todoroo.andlib.data.ContentResolverDao;
|
||||
import com.todoroo.andlib.data.TodorooCursor;
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
import com.todoroo.andlib.sql.Query;
|
||||
|
||||
/**
|
||||
* Data access object for accessing Astrid's {@link Metadata} table. A
|
||||
* piece of Metadata is information about a task, for example a tag or a
|
||||
* note. It operates in a one-to-many relation with tasks.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class MetadataApiDao extends ContentResolverDao<Metadata> {
|
||||
|
||||
public MetadataApiDao(Context context) {
|
||||
super(Metadata.class, context, Metadata.CONTENT_URI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates SQL clauses
|
||||
*/
|
||||
public static class MetadataCriteria {
|
||||
|
||||
/** Returns all metadata associated with a given task */
|
||||
public static Criterion byTask(long taskId) {
|
||||
return Metadata.TASK.eq(taskId);
|
||||
}
|
||||
|
||||
/** Returns all metadata associated with a given key */
|
||||
public static Criterion withKey(String key) {
|
||||
return Metadata.KEY.eq(key);
|
||||
}
|
||||
|
||||
/** Returns all metadata associated with a given key */
|
||||
public static Criterion byTaskAndwithKey(long taskId, String key) {
|
||||
return Criterion.and(withKey(key), byTask(taskId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize metadata for given task id. Deletes rows in database that
|
||||
* are not identical to those in the metadata list, creates rows that
|
||||
* have no match.
|
||||
*
|
||||
* @param taskId id of task to perform synchronization on
|
||||
* @param metadata list of new metadata items to save
|
||||
* @param metadataCriteria criteria to load data for comparison from metadata
|
||||
*/
|
||||
public void synchronizeMetadata(long taskId, ArrayList<Metadata> metadata,
|
||||
Criterion metadataCriteria) {
|
||||
HashSet<ContentValues> newMetadataValues = new HashSet<ContentValues>();
|
||||
for(Metadata metadatum : metadata) {
|
||||
metadatum.setValue(Metadata.TASK, taskId);
|
||||
metadatum.clearValue(Metadata.ID);
|
||||
newMetadataValues.add(metadatum.getMergedValues());
|
||||
}
|
||||
|
||||
Metadata item = new Metadata();
|
||||
TodorooCursor<Metadata> cursor = query(Query.select(Metadata.PROPERTIES).where(Criterion.and(MetadataCriteria.byTask(taskId),
|
||||
metadataCriteria)));
|
||||
try {
|
||||
// try to find matches within our metadata list
|
||||
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
||||
item.readFromCursor(cursor);
|
||||
long id = item.getId();
|
||||
|
||||
// clear item id when matching with incoming values
|
||||
item.clearValue(Metadata.ID);
|
||||
ContentValues itemMergedValues = item.getMergedValues();
|
||||
if(newMetadataValues.contains(itemMergedValues)) {
|
||||
newMetadataValues.remove(itemMergedValues);
|
||||
continue;
|
||||
}
|
||||
|
||||
// not matched. cut it
|
||||
delete(id);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
// everything that remains shall be written
|
||||
for(ContentValues values : newMetadataValues) {
|
||||
item.clear();
|
||||
item.mergeWith(values);
|
||||
save(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.data;
|
||||
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.todoroo.andlib.data.AbstractModel;
|
||||
import com.todoroo.andlib.data.Property;
|
||||
import com.todoroo.andlib.data.Table;
|
||||
import com.todoroo.andlib.data.TodorooCursor;
|
||||
import com.todoroo.andlib.data.Property.LongProperty;
|
||||
import com.todoroo.andlib.data.Property.StringProperty;
|
||||
import com.todoroo.astrid.api.AstridApiConstants;
|
||||
|
||||
/**
|
||||
* Data Model which represents a piece of data unrelated to a task
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public class StoreObject extends AbstractModel {
|
||||
|
||||
// --- table
|
||||
|
||||
/** table for this model */
|
||||
public static final Table TABLE = new Table("store", StoreObject.class);
|
||||
|
||||
/** content uri for this model */
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://" + AstridApiConstants.PACKAGE + "/" +
|
||||
TABLE.name);
|
||||
|
||||
// --- properties
|
||||
|
||||
/** ID */
|
||||
public static final LongProperty ID = new LongProperty(
|
||||
TABLE, ID_PROPERTY_NAME);
|
||||
|
||||
/** Store Type Key */
|
||||
public static final StringProperty TYPE = new StringProperty(
|
||||
TABLE, "type");
|
||||
|
||||
/** Store Item Key */
|
||||
public static final StringProperty ITEM= new StringProperty(
|
||||
TABLE, "item");
|
||||
|
||||
/** Store Value Column 1 */
|
||||
public static final StringProperty VALUE1 = new StringProperty(
|
||||
TABLE, "value");
|
||||
|
||||
/** Store Value Column 2 */
|
||||
public static final StringProperty VALUE2 = new StringProperty(
|
||||
TABLE, "value2");
|
||||
|
||||
/** Store Value Column 3 */
|
||||
public static final StringProperty VALUE3 = new StringProperty(
|
||||
TABLE, "value3");
|
||||
|
||||
/** Store Value Column 4 */
|
||||
public static final StringProperty VALUE4 = new StringProperty(
|
||||
TABLE, "value4");
|
||||
|
||||
/** Store Value Column 5 */
|
||||
public static final StringProperty VALUE5 = new StringProperty(
|
||||
TABLE, "value5");
|
||||
|
||||
/** List of all properties for this model */
|
||||
public static final Property<?>[] PROPERTIES = generateProperties(StoreObject.class);
|
||||
|
||||
// --- defaults
|
||||
|
||||
/** Default values container */
|
||||
private static final ContentValues defaultValues = new ContentValues();
|
||||
|
||||
@Override
|
||||
public ContentValues getDefaultValues() {
|
||||
return defaultValues;
|
||||
}
|
||||
|
||||
// --- data access boilerplate
|
||||
|
||||
public StoreObject() {
|
||||
super();
|
||||
}
|
||||
|
||||
public StoreObject(TodorooCursor<StoreObject> cursor) {
|
||||
this();
|
||||
readPropertiesFromCursor(cursor);
|
||||
}
|
||||
|
||||
public void readFromCursor(TodorooCursor<StoreObject> cursor) {
|
||||
super.readPropertiesFromCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return getIdHelper(ID);
|
||||
};
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
private static final Creator<StoreObject> CREATOR = new ModelCreator<StoreObject>(StoreObject.class);
|
||||
|
||||
@Override
|
||||
protected Creator<? extends AbstractModel> getCreator() {
|
||||
return CREATOR;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.todoroo.astrid.data;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.todoroo.andlib.data.ContentResolverDao;
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
|
||||
/**
|
||||
* Data access object for accessing Astrid's {@link StoreObject} table. A
|
||||
* StoreObject is an arbitrary piece of data stored inside of Astrid.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class StoreObjectApiDao extends ContentResolverDao<StoreObject> {
|
||||
|
||||
public StoreObjectApiDao(Context context) {
|
||||
super(StoreObject.class, context, StoreObject.CONTENT_URI);
|
||||
}
|
||||
|
||||
// --- SQL clause generators
|
||||
|
||||
/**
|
||||
* Generates SQL clauses
|
||||
*/
|
||||
public static class StoreObjectCriteria {
|
||||
|
||||
/** Returns all store objects with given type */
|
||||
public static Criterion byType(String type) {
|
||||
return StoreObject.TYPE.eq(type);
|
||||
}
|
||||
|
||||
/** Returns store object with type and key */
|
||||
public static Criterion byTypeAndItem(String type, String item) {
|
||||
return Criterion.and(byType(type), StoreObject.ITEM.eq(item));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,433 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Todoroo Inc
|
||||
* All Rights Reserved
|
||||
* http://www.todoroo.com
|
||||
*/
|
||||
package com.todoroo.astrid.data;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.todoroo.andlib.data.AbstractModel;
|
||||
import com.todoroo.andlib.data.Property;
|
||||
import com.todoroo.andlib.data.Table;
|
||||
import com.todoroo.andlib.data.TodorooCursor;
|
||||
import com.todoroo.andlib.data.Property.IntegerProperty;
|
||||
import com.todoroo.andlib.data.Property.LongProperty;
|
||||
import com.todoroo.andlib.data.Property.StringProperty;
|
||||
import com.todoroo.andlib.utility.DateUtilities;
|
||||
import com.todoroo.astrid.api.AstridApiConstants;
|
||||
import com.todoroo.astrid.api.R;
|
||||
|
||||
/**
|
||||
* Data Model which represents a task users need to accomplish.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public final class Task extends AbstractModel {
|
||||
|
||||
// --- table and uri
|
||||
|
||||
/** table for this model */
|
||||
public static final Table TABLE = new Table("tasks", Task.class);
|
||||
|
||||
/** content uri for this model */
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://" + AstridApiConstants.PACKAGE + "/" +
|
||||
TABLE.name);
|
||||
|
||||
// --- properties
|
||||
|
||||
/** ID */
|
||||
public static final LongProperty ID = new LongProperty(
|
||||
TABLE, ID_PROPERTY_NAME);
|
||||
|
||||
/** Name of Task */
|
||||
public static final StringProperty TITLE = new StringProperty(
|
||||
TABLE, "title");
|
||||
|
||||
/** Importance of Task (see importance flags) */
|
||||
public static final IntegerProperty IMPORTANCE = new IntegerProperty(
|
||||
TABLE, "importance");
|
||||
|
||||
/** Unixtime Task is due, 0 if not set */
|
||||
public static final LongProperty DUE_DATE = new LongProperty(
|
||||
TABLE, "dueDate");
|
||||
|
||||
/** Unixtime Task should be hidden until, 0 if not set */
|
||||
public static final LongProperty HIDE_UNTIL = new LongProperty(
|
||||
TABLE, "hideUntil");
|
||||
|
||||
/** Unixtime Task was created */
|
||||
public static final LongProperty CREATION_DATE = new LongProperty(
|
||||
TABLE, "created");
|
||||
|
||||
/** Unixtime Task was last touched */
|
||||
public static final LongProperty MODIFICATION_DATE = new LongProperty(
|
||||
TABLE, "modified");
|
||||
|
||||
/** Unixtime Task was completed. 0 means active */
|
||||
public static final LongProperty COMPLETION_DATE = new LongProperty(
|
||||
TABLE, "completed");
|
||||
|
||||
/** Unixtime Task was deleted. 0 means not deleted */
|
||||
public static final LongProperty DELETION_DATE = new LongProperty(
|
||||
TABLE, "deleted");
|
||||
|
||||
/** Cached Details Column - built from add-on detail exposers. A null
|
||||
* value means there is no value in the cache and it needs to be
|
||||
* refreshed */
|
||||
public static final StringProperty DETAILS = new StringProperty(
|
||||
TABLE, "details");
|
||||
|
||||
/** Date details were last updated */
|
||||
public static final LongProperty DETAILS_DATE = new LongProperty(
|
||||
TABLE, "detailsDate");
|
||||
|
||||
// --- for migration purposes from astrid 2 (eventually we may want to
|
||||
// move these into the metadata table and treat them as plug-ins
|
||||
|
||||
public static final StringProperty NOTES = new StringProperty(
|
||||
TABLE, "notes");
|
||||
|
||||
public static final IntegerProperty ESTIMATED_SECONDS = new IntegerProperty(
|
||||
TABLE, "estimatedSeconds");
|
||||
|
||||
public static final IntegerProperty ELAPSED_SECONDS = new IntegerProperty(
|
||||
TABLE, "elapsedSeconds");
|
||||
|
||||
public static final LongProperty TIMER_START = new LongProperty(
|
||||
TABLE, "timerStart");
|
||||
|
||||
public static final IntegerProperty POSTPONE_COUNT = new IntegerProperty(
|
||||
TABLE, "postponeCount");
|
||||
|
||||
/** Flags for when to send reminders */
|
||||
public static final IntegerProperty REMINDER_FLAGS = new IntegerProperty(
|
||||
TABLE, "notificationFlags");
|
||||
|
||||
/** Reminder period, in milliseconds. 0 means disabled */
|
||||
public static final LongProperty REMINDER_PERIOD = new LongProperty(
|
||||
TABLE, "notifications");
|
||||
|
||||
/** Unixtime the last reminder was triggered */
|
||||
public static final LongProperty REMINDER_LAST = new LongProperty(
|
||||
TABLE, "lastNotified");
|
||||
|
||||
/** Unixtime snooze is set (0 -> no snooze) */
|
||||
public static final LongProperty REMINDER_SNOOZE = new LongProperty(
|
||||
TABLE, "snoozeTime");
|
||||
|
||||
public static final StringProperty RECURRENCE = new StringProperty(
|
||||
TABLE, "recurrence");
|
||||
|
||||
public static final IntegerProperty FLAGS = new IntegerProperty(
|
||||
TABLE, "flags");
|
||||
|
||||
public static final StringProperty CALENDAR_URI = new StringProperty(
|
||||
TABLE, "calendarUri");
|
||||
|
||||
/** List of all properties for this model */
|
||||
public static final Property<?>[] PROPERTIES = generateProperties(Task.class);
|
||||
|
||||
// --- flags
|
||||
|
||||
/** whether repeat occurs relative to completion date instead of due date */
|
||||
public static final int FLAG_REPEAT_AFTER_COMPLETION = 1 << 1;
|
||||
|
||||
// --- notification flags
|
||||
|
||||
/** whether to send a reminder at deadline */
|
||||
public static final int NOTIFY_AT_DEADLINE = 1 << 1;
|
||||
|
||||
/** whether to send reminders while task is overdue */
|
||||
public static final int NOTIFY_AFTER_DEADLINE = 1 << 2;
|
||||
|
||||
/** reminder mode non-stop */
|
||||
public static final int NOTIFY_NONSTOP = 1 << 3;
|
||||
|
||||
// --- importance settings (note: importance > 3 are supported via plugin)
|
||||
|
||||
public static final int IMPORTANCE_DO_OR_DIE = 0;
|
||||
public static final int IMPORTANCE_MUST_DO = 1;
|
||||
public static final int IMPORTANCE_SHOULD_DO = 2;
|
||||
public static final int IMPORTANCE_NONE = 3;
|
||||
|
||||
/**
|
||||
* @return colors that correspond to importance values
|
||||
*/
|
||||
public static int[] getImportanceColors(Resources r) {
|
||||
return new int[] {
|
||||
r.getColor(R.color.importance_1),
|
||||
r.getColor(R.color.importance_2),
|
||||
r.getColor(R.color.importance_3),
|
||||
r.getColor(R.color.importance_4),
|
||||
r.getColor(R.color.importance_5),
|
||||
r.getColor(R.color.importance_6),
|
||||
};
|
||||
}
|
||||
|
||||
public static final int IMPORTANCE_MOST = IMPORTANCE_DO_OR_DIE;
|
||||
public static final int IMPORTANCE_LEAST = IMPORTANCE_NONE;
|
||||
|
||||
// --- defaults
|
||||
|
||||
/** Default values container */
|
||||
private static final ContentValues defaultValues = new ContentValues();
|
||||
|
||||
static {
|
||||
defaultValues.put(TITLE.name, "");
|
||||
defaultValues.put(DUE_DATE.name, 0);
|
||||
defaultValues.put(HIDE_UNTIL.name, 0);
|
||||
defaultValues.put(COMPLETION_DATE.name, 0);
|
||||
defaultValues.put(DELETION_DATE.name, 0);
|
||||
defaultValues.put(IMPORTANCE.name, IMPORTANCE_NONE);
|
||||
|
||||
defaultValues.put(CALENDAR_URI.name, "");
|
||||
defaultValues.put(RECURRENCE.name, "");
|
||||
defaultValues.put(REMINDER_PERIOD.name, 0);
|
||||
defaultValues.put(REMINDER_FLAGS.name, 0);
|
||||
defaultValues.put(REMINDER_LAST.name, 0);
|
||||
defaultValues.put(REMINDER_SNOOZE.name, 0);
|
||||
defaultValues.put(ESTIMATED_SECONDS.name, 0);
|
||||
defaultValues.put(ELAPSED_SECONDS.name, 0);
|
||||
defaultValues.put(POSTPONE_COUNT.name, 0);
|
||||
defaultValues.put(NOTES.name, "");
|
||||
defaultValues.put(FLAGS.name, 0);
|
||||
defaultValues.put(TIMER_START.name, 0);
|
||||
defaultValues.put(DETAILS.name, (String)null);
|
||||
defaultValues.put(DETAILS_DATE.name, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentValues getDefaultValues() {
|
||||
return defaultValues;
|
||||
}
|
||||
|
||||
// --- data access boilerplate
|
||||
|
||||
public Task() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Task(TodorooCursor<Task> cursor) {
|
||||
this();
|
||||
readPropertiesFromCursor(cursor);
|
||||
}
|
||||
|
||||
public void readFromCursor(TodorooCursor<Task> cursor) {
|
||||
super.readPropertiesFromCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return getIdHelper(ID);
|
||||
}
|
||||
|
||||
// --- parcelable helpers
|
||||
|
||||
public static final Creator<Task> CREATOR = new ModelCreator<Task>(Task.class);
|
||||
|
||||
@Override
|
||||
protected Creator<? extends AbstractModel> getCreator() {
|
||||
return CREATOR;
|
||||
}
|
||||
|
||||
// --- data access methods
|
||||
|
||||
/** Checks whether task is done. Requires COMPLETION_DATE */
|
||||
public boolean isCompleted() {
|
||||
return getValue(COMPLETION_DATE) > 0;
|
||||
}
|
||||
|
||||
/** Checks whether task is deleted. Will return false if DELETION_DATE not read */
|
||||
public boolean isDeleted() {
|
||||
// assume false if we didn't load deletion date
|
||||
if(!containsValue(DELETION_DATE))
|
||||
return false;
|
||||
else
|
||||
return getValue(DELETION_DATE) > 0;
|
||||
}
|
||||
|
||||
/** Checks whether task is hidden. Requires HIDDEN_UNTIL */
|
||||
public boolean isHidden() {
|
||||
return getValue(HIDE_UNTIL) > DateUtilities.now();
|
||||
}
|
||||
|
||||
/** Checks whether task is done. Requires DUE_DATE */
|
||||
public boolean hasDueDate() {
|
||||
return getValue(DUE_DATE) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set state of the given flag on the given property
|
||||
* @param property
|
||||
* @param flag
|
||||
* @return
|
||||
*/
|
||||
public boolean getFlag(IntegerProperty property, int flag) {
|
||||
return (getValue(property) & flag) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the given flag on the given property
|
||||
* @param property
|
||||
* @param flag
|
||||
* @param value
|
||||
*/
|
||||
public void setFlag(IntegerProperty property, int flag, boolean value) {
|
||||
if(value)
|
||||
setValue(property, getValue(property) | flag);
|
||||
else
|
||||
setValue(property, getValue(property) & ~flag);
|
||||
}
|
||||
|
||||
// --- due and hide until date management
|
||||
|
||||
/** urgency array index -> significance */
|
||||
public static final int URGENCY_NONE = 0;
|
||||
public static final int URGENCY_TODAY = 1;
|
||||
public static final int URGENCY_TOMORROW = 2;
|
||||
public static final int URGENCY_DAY_AFTER = 3;
|
||||
public static final int URGENCY_NEXT_WEEK = 4;
|
||||
public static final int URGENCY_NEXT_MONTH = 5;
|
||||
public static final int URGENCY_SPECIFIC_DAY = 6;
|
||||
public static final int URGENCY_SPECIFIC_DAY_TIME = 7;
|
||||
|
||||
/** hide until array index -> significance */
|
||||
public static final int HIDE_UNTIL_NONE = 0;
|
||||
public static final int HIDE_UNTIL_DUE = 1;
|
||||
public static final int HIDE_UNTIL_DAY_BEFORE = 2;
|
||||
public static final int HIDE_UNTIL_WEEK_BEFORE = 3;
|
||||
public static final int HIDE_UNTIL_SPECIFIC_DAY = 4;
|
||||
public static final int HIDE_UNTIL_SPECIFIC_DAY_TIME = 5;
|
||||
|
||||
/**
|
||||
* Creates due date for this task. If this due date has no time associated,
|
||||
* we move it to the last millisecond of the day.
|
||||
*
|
||||
* @param setting
|
||||
* one of the URGENCY_* constants
|
||||
* @param customDate
|
||||
* if specific day or day & time is set, this value
|
||||
*/
|
||||
public long createDueDate(int setting, long customDate) {
|
||||
long date;
|
||||
|
||||
switch(setting) {
|
||||
case URGENCY_NONE:
|
||||
date = 0;
|
||||
break;
|
||||
case URGENCY_TODAY:
|
||||
date = DateUtilities.now();
|
||||
break;
|
||||
case URGENCY_TOMORROW:
|
||||
date = DateUtilities.now() + DateUtilities.ONE_DAY;
|
||||
break;
|
||||
case URGENCY_DAY_AFTER:
|
||||
date = DateUtilities.now() + 2 * DateUtilities.ONE_DAY;
|
||||
break;
|
||||
case URGENCY_NEXT_WEEK:
|
||||
date = DateUtilities.now() + DateUtilities.ONE_WEEK;
|
||||
break;
|
||||
case URGENCY_NEXT_MONTH:
|
||||
date = DateUtilities.oneMonthFromNow();
|
||||
break;
|
||||
case URGENCY_SPECIFIC_DAY:
|
||||
case URGENCY_SPECIFIC_DAY_TIME:
|
||||
date = customDate;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown setting " + setting);
|
||||
}
|
||||
|
||||
if(date <= 0)
|
||||
return date;
|
||||
|
||||
Date dueDate = new Date(date / 1000L * 1000L); // get rid of millis
|
||||
if(setting != URGENCY_SPECIFIC_DAY_TIME) {
|
||||
dueDate.setHours(23);
|
||||
dueDate.setMinutes(59);
|
||||
dueDate.setSeconds(59);
|
||||
} else if(isEndOfDay(dueDate)) {
|
||||
dueDate.setSeconds(58);
|
||||
}
|
||||
return dueDate.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create hide until for this task.
|
||||
*
|
||||
* @param setting
|
||||
* one of the HIDE_UNTIL_* constants
|
||||
* @param customDate
|
||||
* if specific day is set, this value
|
||||
* @return
|
||||
*/
|
||||
public long createHideUntil(int setting, long customDate) {
|
||||
long date;
|
||||
|
||||
switch(setting) {
|
||||
case HIDE_UNTIL_NONE:
|
||||
return 0;
|
||||
case HIDE_UNTIL_DUE:
|
||||
date = getValue(DUE_DATE);
|
||||
break;
|
||||
case HIDE_UNTIL_DAY_BEFORE:
|
||||
date = getValue(DUE_DATE) - DateUtilities.ONE_DAY;
|
||||
break;
|
||||
case HIDE_UNTIL_WEEK_BEFORE:
|
||||
date = getValue(DUE_DATE) - DateUtilities.ONE_WEEK;
|
||||
break;
|
||||
case HIDE_UNTIL_SPECIFIC_DAY:
|
||||
case HIDE_UNTIL_SPECIFIC_DAY_TIME:
|
||||
date = customDate;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown setting " + setting);
|
||||
}
|
||||
|
||||
if(date <= 0)
|
||||
return date;
|
||||
|
||||
Date hideUntil = new Date(date / 1000L * 1000L); // get rid of millis
|
||||
if(setting != HIDE_UNTIL_SPECIFIC_DAY_TIME) {
|
||||
hideUntil.setHours(0);
|
||||
hideUntil.setMinutes(0);
|
||||
hideUntil.setSeconds(0);
|
||||
}
|
||||
return hideUntil.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if hours, minutes, and seconds indicate end of day
|
||||
*/
|
||||
private static boolean isEndOfDay(Date date) {
|
||||
int hours = date.getHours();
|
||||
int minutes = date.getMinutes();
|
||||
int seconds = date.getSeconds();
|
||||
return hours == 23 && minutes == 59 && seconds == 59;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this due date has a due time or only a date
|
||||
*/
|
||||
public boolean hasDueTime() {
|
||||
if(!hasDueDate())
|
||||
return false;
|
||||
return hasDueTime(getValue(Task.DUE_DATE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether provided due date has a due time or only a date
|
||||
*/
|
||||
public static boolean hasDueTime(long dueDate) {
|
||||
return !isEndOfDay(new Date(dueDate));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
package com.todoroo.astrid.data;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.todoroo.andlib.data.ContentResolverDao;
|
||||
import com.todoroo.andlib.data.TodorooCursor;
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
import com.todoroo.andlib.sql.Functions;
|
||||
import com.todoroo.andlib.sql.Query;
|
||||
import com.todoroo.astrid.api.AstridApiConstants;
|
||||
import com.todoroo.astrid.api.PermaSql;
|
||||
|
||||
/**
|
||||
* Data access object for accessing Astrid's {@link Task} table. If you
|
||||
* are looking to store extended information about a Task, you probably
|
||||
* want to use the {@link MetadataApiDao} object.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class TaskApiDao extends ContentResolverDao<Task> {
|
||||
|
||||
public TaskApiDao(Context context) {
|
||||
super(Task.class, context, Task.CONTENT_URI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates SQL clauses
|
||||
*/
|
||||
public static class TaskCriteria {
|
||||
|
||||
/** @return tasks by id */
|
||||
public static Criterion byId(long id) {
|
||||
return Task.ID.eq(id);
|
||||
}
|
||||
|
||||
/** @return tasks that were deleted */
|
||||
public static Criterion isDeleted() {
|
||||
return Task.DELETION_DATE.neq(0);
|
||||
}
|
||||
|
||||
/** @return tasks that were not deleted */
|
||||
public static Criterion notDeleted() {
|
||||
return Task.DELETION_DATE.eq(0);
|
||||
}
|
||||
|
||||
/** @return tasks that have not yet been completed or deleted */
|
||||
public static Criterion activeAndVisible() {
|
||||
return Criterion.and(Task.COMPLETION_DATE.eq(0),
|
||||
Task.DELETION_DATE.eq(0),
|
||||
Task.HIDE_UNTIL.lt(Functions.now()));
|
||||
}
|
||||
|
||||
/** @return tasks that have not yet been completed or deleted */
|
||||
public static Criterion isActive() {
|
||||
return Criterion.and(Task.COMPLETION_DATE.eq(0),
|
||||
Task.DELETION_DATE.eq(0));
|
||||
}
|
||||
|
||||
/** @return tasks that are not hidden at current time */
|
||||
public static Criterion isVisible() {
|
||||
return Task.HIDE_UNTIL.lt(Functions.now());
|
||||
}
|
||||
|
||||
/** @return tasks that have a due date */
|
||||
public static Criterion hasDeadlines() {
|
||||
return Task.DUE_DATE.neq(0);
|
||||
}
|
||||
|
||||
/** @return tasks that are due before a certain unixtime */
|
||||
public static Criterion dueBeforeNow() {
|
||||
return Criterion.and(Task.DUE_DATE.gt(0), Task.DUE_DATE.lt(Functions.now()));
|
||||
}
|
||||
|
||||
/** @return tasks that are due after a certain unixtime */
|
||||
public static Criterion dueAfterNow() {
|
||||
return Task.DUE_DATE.gt(Functions.now());
|
||||
}
|
||||
|
||||
/** @return tasks completed before a given unixtime */
|
||||
public static Criterion completed() {
|
||||
return Criterion.and(Task.COMPLETION_DATE.gt(0), Task.COMPLETION_DATE.lt(Functions.now()));
|
||||
}
|
||||
|
||||
/** @return tasks that have a blank or null title */
|
||||
@SuppressWarnings("nls")
|
||||
public static Criterion hasNoTitle() {
|
||||
return Criterion.or(Task.TITLE.isNull(), Task.TITLE.eq(""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Count tasks matching criterion
|
||||
* @param criterion
|
||||
* @return # of tasks matching
|
||||
*/
|
||||
public int countTasks(Criterion criterion) {
|
||||
TodorooCursor<Task> cursor = query(Query.select(Task.ID).where(criterion));
|
||||
try {
|
||||
return cursor.getCount();
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count tasks matching query tepmlate
|
||||
* @param queryTemplate
|
||||
* @return # of tasks matching
|
||||
*/
|
||||
public int countTasks(String queryTemplate) {
|
||||
queryTemplate = PermaSql.replacePlaceholders(queryTemplate);
|
||||
TodorooCursor<Task> cursor = query(Query.select(Task.ID).withQueryTemplate(queryTemplate));
|
||||
try {
|
||||
return cursor.getCount();
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save(Task model) {
|
||||
ContentValues setValues = model.getSetValues();
|
||||
if(super.save(model)) {
|
||||
afterSave(model, setValues);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @return true if task change shouldn't be broadcast */
|
||||
public static boolean insignificantChange(ContentValues values) {
|
||||
if(values == null || values.size() == 0)
|
||||
return true;
|
||||
|
||||
if(values.containsKey(Task.DETAILS_DATE.name) &&
|
||||
values.containsKey(Task.DETAILS.name) &&
|
||||
values.size() == 2)
|
||||
return true;
|
||||
|
||||
if(values.containsKey(Task.REMINDER_LAST.name) &&
|
||||
values.size() == 1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send broadcasts on task change (triggers things like task repeats)
|
||||
* @param task task that was saved
|
||||
* @param values values that were updated
|
||||
*/
|
||||
public static void afterSave(Task task, ContentValues values) {
|
||||
if(insignificantChange(values))
|
||||
return;
|
||||
|
||||
if(values.containsKey(Task.COMPLETION_DATE.name) && task.isCompleted()) {
|
||||
Context context = ContextManager.getContext();
|
||||
if(context != null) {
|
||||
Intent broadcastIntent;
|
||||
broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_COMPLETED);
|
||||
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId());
|
||||
context.sendOrderedBroadcast(broadcastIntent, null);
|
||||
}
|
||||
}
|
||||
|
||||
afterTaskListChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send broadcast when task list changes. Widgets should update.
|
||||
*/
|
||||
public static void afterTaskListChanged() {
|
||||
Context context = ContextManager.getContext();
|
||||
if(context != null) {
|
||||
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_LIST_UPDATED);
|
||||
context.sendOrderedBroadcast(broadcastIntent, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue