Compare commits
158 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 16c20287ca | |||
| a733d87c37 | |||
| 79d8ba9ef8 | |||
| 3ee7d4504c | |||
| 579509aad8 | |||
| 24ff73ab06 | |||
| 60d5e7e515 | |||
| c610758ae1 | |||
| 17d2755844 | |||
| 0ab14e0f3d | |||
| bcbaf4985a | |||
| b2e8713db0 | |||
| af60e1fdfb | |||
| 75043325ff | |||
| 337e5b9e4d | |||
| 1ff986f1e6 | |||
| 6412bb9fcd | |||
| 8425997c29 | |||
| f4b585b830 | |||
| 47c259fa9a | |||
| 80208e3188 | |||
| 2655d3e773 | |||
| ca8814c478 | |||
| 6a397922d2 | |||
| ee062f8a38 | |||
| c8bdf8e641 | |||
| 0b2bd6899f | |||
| 32d811b46e | |||
| 80a8017a18 | |||
| 2b90bfd054 | |||
| 8cb6d63abe | |||
| 9837680540 | |||
| e2b741dd08 | |||
| 18546fd3cc | |||
| a87d2e5b09 | |||
| 3ae30e2468 | |||
| f821c8ba86 | |||
| 5c96774e79 | |||
| c26a5edc03 | |||
| f8afa9dbad | |||
| db1167ead5 | |||
| 0008673ab0 | |||
| 59d4bfa4ac | |||
| 04f146c641 | |||
| ea97ff65df | |||
| 9827b3fc92 | |||
| a35ed2e9b1 | |||
| 26d2a861d7 | |||
| 389ed9b362 | |||
| c5e5e862ad | |||
| b676fd6614 | |||
| 0194efafbc | |||
| 9ba1357dbb | |||
| 64b66a0c57 | |||
| 7787dae9f6 | |||
| d0ca06f964 | |||
| f7d1a53622 | |||
| 5f13d027af | |||
| cf45a8079c | |||
| 9e553cc900 | |||
| 1f3466e4b2 | |||
| c813934bcb | |||
| 480202853d | |||
| 4c58bd81bb | |||
| 9f9b6966a8 | |||
| 52c97b63d5 | |||
| eee18ec7a4 | |||
| 4d444046de | |||
| 4d5e31b231 | |||
| 8544f7d20a | |||
| 1feb5cbb65 | |||
| 1d2fde6e69 | |||
| 20423121ee | |||
| ebf7b0a0c3 | |||
| 1189a07794 | |||
| 63e9041922 | |||
| 699be450b0 | |||
| 66b175c56c | |||
| 81a7aca4a0 | |||
| 065f42fbef | |||
| c92371b36a | |||
| 97c46183c3 | |||
| c02b8fab53 | |||
| 6540913d59 | |||
| b70c3be5af | |||
| 461f1c246b | |||
| 6d091dfa81 | |||
| 97ad6bc2f8 | |||
| 93ee8a53ed | |||
| bf9b6d6627 | |||
| 5f637952aa | |||
| 17de8cea6f | |||
| afea79476f | |||
| 7215a2def0 | |||
| b8d2d14d68 | |||
| a2b53c75f4 | |||
| 7a5f69d3a5 | |||
| 7fd9893560 | |||
| f209031df0 | |||
| 2dbab929ac | |||
| e9eb764d12 | |||
| 41a4a5527a | |||
| 4ded3c6bc8 | |||
| 51e573e475 | |||
| 98c3169929 | |||
| ff65a4d04f | |||
| 278f49dec8 | |||
| d444e1ca3c | |||
| 13e07696b9 | |||
| 23c3a4d651 | |||
| c9869bab0e | |||
| ecdb509371 | |||
| de376a84f8 | |||
| 9abd8bcaa6 | |||
| 8ddadb8e6d | |||
| 924ef3313e | |||
| 8cb68a6e64 | |||
| 23f47f10f8 | |||
| 251fa17487 | |||
| bae3373fe9 | |||
| 0a685a66e3 | |||
| 5ca9ca857a | |||
| d9dfa6d746 | |||
| 3a5220546e | |||
| 047d5c2340 | |||
| 725c21c0a1 | |||
| 7939e39fc1 | |||
| a133bd8f9e | |||
| 1f9790cba8 | |||
| a3ba1e1490 | |||
| accb30152f | |||
| dc7daa6e8c | |||
| 1d8e788d53 | |||
| 568b908b26 | |||
| 3ab63adb34 | |||
| 91692f345e | |||
| dbdb98a682 | |||
| df66cd5753 | |||
| 6e39dd37f8 | |||
| 7212f7be94 | |||
| 77fe494e6c | |||
| 2f491e8c10 | |||
| f4fe7b1ab3 | |||
| 7e444cbf31 | |||
| ed6ab9c53c | |||
| f91ca3154c | |||
| bbfab1b201 | |||
| 1f2e3bcf70 | |||
| d1f3791f97 | |||
| 490b95a001 | |||
| 12e6f03098 | |||
| d86f42e2e9 | |||
| 360d59d3de | |||
| b617420290 | |||
| 53b267150b | |||
| 0dfd55ed52 | |||
| daabd5381d | |||
| a842129e37 |
@@ -1,4 +1,4 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
liberapay: dennis.guse
|
liberapay: OpenTracks
|
||||||
custom: https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore
|
custom: https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore
|
||||||
|
|||||||
@@ -8,3 +8,6 @@ A clear and concise description of what the pull request changes/adds.
|
|||||||
|
|
||||||
**License agreement**
|
**License agreement**
|
||||||
By opening this pull request, you are providing your contribution under the _Apache License 2.0_ (see [LICENSE.md](LICENSE.md)).
|
By opening this pull request, you are providing your contribution under the _Apache License 2.0_ (see [LICENSE.md](LICENSE.md)).
|
||||||
|
|
||||||
|
**Note: new dependencies/libraries**
|
||||||
|
Please refrain from introducing new libraries without consulting the team.
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "gradle"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 6 * * 1'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyse:
|
||||||
|
name: Analyse
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
|
||||||
|
- run: git checkout HEAD^2
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v1
|
||||||
|
with:
|
||||||
|
languages: java
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
./gradlew build
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v1
|
||||||
@@ -66,6 +66,9 @@ captures/
|
|||||||
.idea/sqlDataSources.xml
|
.idea/sqlDataSources.xml
|
||||||
.idea/vcs.xml
|
.idea/vcs.xml
|
||||||
.idea/uiDesigner.xml
|
.idea/uiDesigner.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/markdown-navigator-enh.xml
|
||||||
|
.idea/markdown-navigator.xml
|
||||||
|
|
||||||
# Keystore files
|
# Keystore files
|
||||||
*.jks
|
*.jks
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://liberapay.com/dennis.guse/donate">
|
<a href="https://liberapay.com/OpenTracks/donate">
|
||||||
<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="45" align="middle">
|
<img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg" height="45" align="middle">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
@@ -51,13 +51,19 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
|||||||
__Only required permissions:__
|
__Only required permissions:__
|
||||||
* _ACCESS_FINE_LOCATION_: required to use the GPS.
|
* _ACCESS_FINE_LOCATION_: required to use the GPS.
|
||||||
|
|
||||||
|
An overview of Bluetooth LE sensors that are known to work with OpenTracks is in [README_TESTED_SENSORS.md](README_TESTED_SENSORS.md).
|
||||||
|
|
||||||
_Please note:_
|
_Please note:_
|
||||||
_OpenTracks_ does not contain a _map_ (as this would required Internet access).
|
_OpenTracks_ does not contain a _map_ (as this would required Internet access).
|
||||||
To show your tracks on a map, a 3rd party application (e.g., [OsmAnd](https://play.google.com/store/apps/details?id=net.osmand) or [MAPS.ME](https://play.google.com/store/apps/details?id=com.mapswithme.maps.pro)) needs to be installed.
|
|
||||||
|
|
||||||
## Custom Dashboards
|
## Custom Dashboards (incl. Map)
|
||||||
As of v3.3.1 OpenTracks enables to use custom dashboards.
|
As of v3.3.1 OpenTracks enables to use custom dashboards.
|
||||||
The reference implementation is [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard), which presents an OpenStreetMap map (showing the current track, incl. updates).
|
The reference implementation is [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard), which presents an OpenStreetMap map (showing the current track, incl. updates).
|
||||||
|
The developer documentation is in [README_API.md](README_API.md).
|
||||||
|
|
||||||
|
Alternatively, recorded tracks can be shared as KMZ/GPX to installed applications (e.g., [OsmAnd](https://play.google.com/store/apps/details?id=net.osmand) or [MAPS.ME](https://play.google.com/store/apps/details?id=com.mapswithme.maps.pro)).
|
||||||
|
However, this is rather slow and does not provide updates while recording.
|
||||||
|
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
<div>
|
<div>
|
||||||
@@ -87,7 +93,7 @@ Rework of _OpenTracks_ included:
|
|||||||
* removing calorie estimation and activity estimation,
|
* removing calorie estimation and activity estimation,
|
||||||
* removing support for ANT+ and Classic Bluetooth,
|
* removing support for ANT+ and Classic Bluetooth,
|
||||||
* adding support for Bluetooth LE heart rate sensors,
|
* adding support for Bluetooth LE heart rate sensors,
|
||||||
* removing Protobuf (store sensor data in SQLite columns directly), and
|
* removing Protobuf (store sensosensorr data in SQLite columns directly), and
|
||||||
* removing Android Service API for other apps.
|
* removing Android Service API for other apps.
|
||||||
|
|
||||||
Artwork, logos and user interface remained more or less unchanged.
|
Artwork, logos and user interface remained more or less unchanged.
|
||||||
|
|||||||
@@ -7,14 +7,11 @@ Although this might be (mostly) sufficient, it has some limitations.
|
|||||||
This include limited configurability (e.g., ordering of shown elements) and the lack of Internet access.
|
This include limited configurability (e.g., ordering of shown elements) and the lack of Internet access.
|
||||||
In fact, the later is considered a feature but severely limits the implementation presenting a map (at least in an easy way).
|
In fact, the later is considered a feature but severely limits the implementation presenting a map (at least in an easy way).
|
||||||
|
|
||||||
_NOTE:_ for showing a track on a map a workaround was implemented in OpenTracks.
|
|
||||||
Data could be exported as KMZ and presented in 3rd-party application (e.g., [OsmAnd](https://play.google.com/store/apps/details?id=net.osmand) or [MAPS.ME](https://play.google.com/store/apps/details?id=com.mapswithme.maps.pro)).
|
|
||||||
|
|
||||||
For the time being, the OpenTracks Data API can be used to implement mainly custom dashboards.
|
For the time being, the OpenTracks Data API can be used to implement mainly custom dashboards.
|
||||||
|
|
||||||
## Implementation
|
## Implementation
|
||||||
OpenTracks by default does not expose any data to 3rd-party applications.
|
OpenTracks by default does not expose any data to 3rd-party applications.
|
||||||
On the request of the user (i.e., pressing a button), an Intent is created that exposes the `Track` data (it's summary) as well as the `TrackPoint`s of one or more selected tracks.
|
On the request of the user (i.e., pressing a button), an Intent is created that exposes the `Track` data (it's summary), the `TrackPoint`s, and the `Waypoint`s of one or more selected tracks.
|
||||||
For each, one URI is provided.
|
For each, one URI is provided.
|
||||||
These URIs notify observers if on content changes (e.g., a new `TrackPoint` was added).
|
These URIs notify observers if on content changes (e.g., a new `TrackPoint` was added).
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Craft new releases
|
## Craft new releases
|
||||||
|
|
||||||
1. Get next _version code_ (master branch): `git rev-list HEAD --count master`
|
1. Get next _version code_ (main): `git rev-list HEAD --count main`
|
||||||
2. Decide on _version name_ (semantic versioning)
|
2. Decide on _version name_ (semantic versioning)
|
||||||
3. Manually update _version code_ and _version name_ in `build.gradle`
|
3. Manually update _version code_ and _version name_ in `build.gradle`
|
||||||
4. Create changelog (`_version code_.txt`)
|
4. Create changelog (`_version code_.txt`)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Overview of tested Bluetooth LE sensors
|
||||||
|
|
||||||
|
## HRS: Heartrate Service
|
||||||
|
* Decathlon|Geonaute|Kalenji Dual HRM Belt
|
||||||
|
* Polar H7
|
||||||
|
* Polar OH1
|
||||||
|
Has updatable firmware that requires a user account at polar.com
|
||||||
|
* Wahoo Tickr (Model: WFBTHR02)
|
||||||
|
|
||||||
|
## CSCP: Cycling Cadence and Speed Service
|
||||||
|
Please note that the according to the specification these sensors _may_ provide speed as well as cadence.
|
||||||
|
However, often only one value is provided.
|
||||||
|
|
||||||
|
### Speed
|
||||||
|
* Wahoo Speed (Model: WFRPMSPD)
|
||||||
|
|
||||||
|
### Cadence
|
||||||
|
* Wahoo Cadence (Model: WFPODCAD2)
|
||||||
|
This sensor reports cadence data as speed.
|
||||||
|
A workaround is in place.
|
||||||
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.6.2'
|
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,20 +17,6 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getVersionCode = { ->
|
|
||||||
try {
|
|
||||||
def stdout = new ByteArrayOutputStream()
|
|
||||||
exec {
|
|
||||||
commandLine 'git', 'rev-list', 'HEAD', '--count'
|
|
||||||
standardOutput = stdout
|
|
||||||
}
|
|
||||||
return Integer.parseInt(stdout.toString().trim())
|
|
||||||
}
|
|
||||||
catch (ignored) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def getVersionName = { ->
|
def getVersionName = { ->
|
||||||
try {
|
try {
|
||||||
def stdout = new ByteArrayOutputStream()
|
def stdout = new ByteArrayOutputStream()
|
||||||
@@ -50,25 +36,26 @@ def getVersionName = { ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileOptions {
|
||||||
|
coreLibraryDesugaringEnabled true
|
||||||
|
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
compileSdkVersion 30
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "de.dennisguse.opentracks"
|
applicationId "de.dennisguse.opentracks"
|
||||||
manifestPlaceholders = [
|
versionCode 3544
|
||||||
applicationLogo: "@drawable/ic_logo_color_24dp",
|
versionName "v3.9.3"
|
||||||
applicationName: "@string/app_name"
|
|
||||||
]
|
|
||||||
|
|
||||||
versionCode 3386
|
|
||||||
//versionCode getVersionCode() //Useful for debugging.
|
|
||||||
versionName "v3.7.3"
|
|
||||||
|
|
||||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@@ -77,10 +64,6 @@ android {
|
|||||||
debug {
|
debug {
|
||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
versionNameSuffix "-debug"
|
versionNameSuffix "-debug"
|
||||||
manifestPlaceholders = [
|
|
||||||
applicationLogo: "@drawable/ic_logo_black_24dp",
|
|
||||||
applicationName: "OpenTracks (Debug)"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
release {
|
release {
|
||||||
@@ -99,19 +82,17 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
|
||||||
implementation 'androidx.preference:preference:1.1.0'
|
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
|
implementation 'androidx.preference:preference:1.1.1'
|
||||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||||
|
implementation 'com.google.android.material:material:1.2.0'
|
||||||
|
implementation 'com.android.support.constraint:constraint-layout:2.0.1'
|
||||||
|
|
||||||
androidTestImplementation 'androidx.test:core:1.2.0'
|
androidTestImplementation 'androidx.test:core:1.3.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0'
|
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||||
androidTestImplementation 'androidx.test:rules:1.2.0'
|
androidTestImplementation 'org.mockito:mockito-android:3.4.6'
|
||||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
|
||||||
androidTestImplementation 'org.mockito:mockito-android:3.0.0'
|
|
||||||
|
|
||||||
testImplementation 'androidx.test:core:1.2.0'
|
|
||||||
testImplementation 'org.mockito:mockito-core:3.0.0'
|
|
||||||
implementation 'com.google.android.material:material:1.1.0'
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,23 +9,35 @@ from every activity showing a menu.
|
|||||||
endlegend
|
endlegend
|
||||||
|
|
||||||
[*] --> TrackListActivity
|
[*] --> TrackListActivity
|
||||||
TrackListActivity --> TrackDetailActivity : Start recording
|
TrackListActivity --> TrackRecordingActivity : Start recording
|
||||||
TrackListActivity --> SearchListActivity
|
TrackListActivity --> SearchListActivity
|
||||||
TrackListActivity --> MarkerListActivity : Show all markers
|
TrackListActivity --> MarkerListActivity : Show all markers
|
||||||
TrackListActivity --> TrackDetailActivity : Show track
|
TrackListActivity --> AggregatedStatisticsActivity : Aggregated stats
|
||||||
|
TrackListActivity --> TrackRecordedActivity : Show track
|
||||||
TrackListActivity --> TrackDeleteActivity
|
TrackListActivity --> TrackDeleteActivity
|
||||||
|
|
||||||
SearchListActivity --> MarkerDetailActivity : Search result
|
SearchListActivity --> MarkerDetailActivity : Search result
|
||||||
SearchListActivity --> TrackDetailActivity : Search result
|
SearchListActivity --> TrackRecordedActivity : Search result
|
||||||
|
|
||||||
TrackDetailActivity --> TrackDeleteActivity
|
TrackRecordedActivity --> TrackDeleteActivity
|
||||||
TrackDetailActivity --> TrackEditActivity
|
TrackRecordedActivity --> TrackEditActivity
|
||||||
TrackDetailActivity --> MarkerListActivity
|
TrackRecordedActivity --> MarkerListActivity
|
||||||
TrackDetailActivity --> MarkerEditActivity : Add marker
|
TrackRecordedActivity --> MarkerEditActivity : Add marker
|
||||||
TrackDetailActivity --> CameraIntent : Add marker (with photo)
|
TrackRecordedActivity --> CameraIntent : Add marker (with photo)
|
||||||
TrackDetailActivity --> ShareFileIntent
|
TrackRecordedActivity --> ShareFileIntent
|
||||||
TrackDetailActivity --> DashboardIntent : Database cursor
|
TrackRecordedActivity --> DashboardIntent : Database cursor
|
||||||
TrackDetailActivity --> TrackOnMapIntent : KMZ
|
TrackRecordedActivity --> TrackOnMapIntent : KMZ
|
||||||
|
TrackRecordedActivity --> TrackRecordingActivity
|
||||||
|
TrackRecordedActivity --> SettingsActivity
|
||||||
|
TrackRecordedActivity --> TrackListActivity : Back button
|
||||||
|
|
||||||
|
TrackRecordingActivity --> TrackOnMapIntent
|
||||||
|
TrackRecordingActivity --> MarkerEditActivity : Add marker
|
||||||
|
TrackRecordingActivity --> MarkerListActivity
|
||||||
|
TrackRecordingActivity --> TrackEditActivity
|
||||||
|
TrackRecordingActivity --> SettingsActivity
|
||||||
|
TrackRecordingActivity --> TrackRecordedActivity : Stop recording
|
||||||
|
TrackRecordingActivity --> TrackListActivity : Back button
|
||||||
|
|
||||||
MarkerListActivity --> MarkerDetailActivity
|
MarkerListActivity --> MarkerDetailActivity
|
||||||
|
|
||||||
@@ -35,6 +47,9 @@ MarkerDetailActivity --> CoordinateOnMapIntent : URI
|
|||||||
SettingsActivity --> AboutActivity
|
SettingsActivity --> AboutActivity
|
||||||
SettingsActivity --> HelpActivity
|
SettingsActivity --> HelpActivity
|
||||||
SettingsActivity --> ExportActivity
|
SettingsActivity --> ExportActivity
|
||||||
SettingsActivity --> ImportActivity
|
SettingsActivity --> DirectoryChooserActivity
|
||||||
|
SettingsActivity --> DirectoryChooserActivity
|
||||||
|
DirectoryChooserActivity$ImportDirectoryChooserActivity --> ImportActivity
|
||||||
|
DirectoryChooserActivity$ExportDirectoryChooserActivity --> ExportActivity
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
@startuml
|
||||||
|
interface TrackExporter {
|
||||||
|
}
|
||||||
|
class KmzTrackExporter implements TrackExporter
|
||||||
|
KmzTrackExporter o-- FileTrackExporter
|
||||||
|
class FileTrackExporter implements TrackExporter {
|
||||||
|
/' One track only '/
|
||||||
|
}
|
||||||
|
FileTrackExporter o-- TrackWriter
|
||||||
|
|
||||||
|
interface TrackWriter {
|
||||||
|
}
|
||||||
|
class GpxTrackWriter implements TrackWriter
|
||||||
|
class KmlTrackWriter implements TrackWriter
|
||||||
|
|
||||||
|
|
||||||
|
interface TrackImporter {
|
||||||
|
}
|
||||||
|
class KmzTrackImporter implements TrackImporter {
|
||||||
|
}
|
||||||
|
KmzTrackImporter o-- KmlFileTrackImporter
|
||||||
|
class AbstractFileTrackImporter implements TrackImporter {
|
||||||
|
}
|
||||||
|
class GpxFileTrackImporter extends AbstractFileTrackImporter {
|
||||||
|
}
|
||||||
|
class KmlFileTrackImporter extends AbstractFileTrackImporter {
|
||||||
|
/' Supports multiple tracks via folders '/
|
||||||
|
}
|
||||||
|
@enduml
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
@startuml
|
||||||
|
SensorManager --> ElevationSumManager
|
||||||
|
LocationManager --> TrackRecordingService
|
||||||
|
ElevationSumManager --> TrackRecordingService
|
||||||
|
|
||||||
|
TrackRecordingService --> TrackRecordingServiceConnection
|
||||||
|
TrackRecordingService --> Database
|
||||||
|
|
||||||
|
Database --> CustomContentProvider
|
||||||
|
CustomContentProvider --> TrackDataHub
|
||||||
|
CustomContentProvider --> ShareContentProvider
|
||||||
|
TrackDataHub --> StatisticsRecordingFragment : TrackPoints, TrackStatistics, Waypoints (push)
|
||||||
|
TrackDataHub --> StatisticsRecordedFragment : TrackPoints, TrackStatistics, Waypoints (push)
|
||||||
|
TrackDataHub --> ChartFragment --> ChartView
|
||||||
|
|
||||||
|
TrackRecordingServiceConnection --> StatisticsRecordingFragment : Sensor data (heartrate, cadence, elevation gain; pull 1s)
|
||||||
|
TrackRecordingServiceConnection --> TrackController : Start time (pull, onStart)
|
||||||
|
@enduml
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
targetNamespace="http://opentracksapp.com/xmlschemas/v1">
|
||||||
|
|
||||||
|
<xs:element name="trackuuid"
|
||||||
|
type="xs:string" />
|
||||||
|
|
||||||
|
</xs:schema>
|
||||||
@@ -0,0 +1,474 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
sodipodi:docname="ic_activity_climbing.svg"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
height="22"
|
||||||
|
width="22">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect3162"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect3149"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect2514"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect950"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect946"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect918"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect912"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect894"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:window-y="64"
|
||||||
|
inkscape:window-x="219"
|
||||||
|
inkscape:window-height="880"
|
||||||
|
inkscape:window-width="1500"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
units="px"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:cy="12.271037"
|
||||||
|
inkscape:cx="7.0404004"
|
||||||
|
inkscape:zoom="22.390336"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#232629"
|
||||||
|
id="base">
|
||||||
|
<inkscape:grid
|
||||||
|
dotted="true"
|
||||||
|
empspacing="22"
|
||||||
|
id="grid833"
|
||||||
|
type="xygrid" />
|
||||||
|
<inkscape:grid
|
||||||
|
originy="0.26458333"
|
||||||
|
originx="0.26458333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
empspacing="1"
|
||||||
|
id="grid835"
|
||||||
|
type="xygrid" />
|
||||||
|
<sodipodi:guide
|
||||||
|
inkscape:color="rgb(0,0,255)"
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:label=""
|
||||||
|
id="guide887"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
position="4.195,4.2333333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
id="guide900"
|
||||||
|
orientation="0,-1"
|
||||||
|
position="0.26458333,1.9843751" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<g
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)"
|
||||||
|
id="g954">
|
||||||
|
<rect
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect919"
|
||||||
|
width="68.791664"
|
||||||
|
height="79.375"
|
||||||
|
x="-357.1875"
|
||||||
|
y="-7.9375" />
|
||||||
|
<rect
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect851"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect853"
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect855"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect857"
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect859"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect861"
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect863"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect865"
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect867"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect869"
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect871"
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect873"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect875"
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect877"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect879"
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect881"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect883"
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect885"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect887"
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect889"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect891"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect893"
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect895"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect897"
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect899"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect901"
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect903"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect905"
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect907"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect909"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect911"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect913"
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="path920"
|
||||||
|
d="M 6.3144531 -0.15234375 L 5.6464844 0.34179688 L 4.8945312 2.8847656 L 3.7050781 3.2324219 L 3.0292969 4.9121094 L 1.6992188 5.1113281 L 1.5371094 5.4570312 L -0.2265625 5.8183594 L -0.17382812 6.0761719 L 1.7207031 5.6914062 L 1.8789062 5.3515625 L 3.21875 5.1503906 L 3.9023438 3.4492188 L 5.1074219 3.0976562 L 5.875 0.50195312 L 6.4726562 0.060546875 L 6.3144531 -0.15234375 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<g
|
||||||
|
transform="matrix(1.226984,0,0,1.226984,-0.81596813,-1.2462535)"
|
||||||
|
id="g924">
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.168524;stroke-opacity:1"
|
||||||
|
id="path17"
|
||||||
|
d="M 2.4564013,2.0252139 C 2.6387748,1.9919855 2.7608027,1.8155843 2.7275743,1.6332107 2.6943459,1.4508371 2.5179443,1.3288092 2.3355708,1.3620376 2.1531971,1.395266 2.0311693,1.5716675 2.0643978,1.7540412 2.0976262,1.9364148 2.2740276,2.0584424 2.4564013,2.0252139 Z M 2.0390821,4.4361706 2.2561417,3.8057362 2.6726641,3.9140028 3.0571092,4.4259571 3.3404272,4.1900271 2.8859586,3.5506757 2.4962919,3.3764255 2.6074394,2.8541847 C 2.8682831,3.0636061 3.230079,3.168985 3.5948261,3.1025284 L 3.5344109,2.7709399 C 3.219402,2.8283344 2.9239238,2.7108724 2.7489979,2.5029267 L 2.5348714,2.2678637 C 2.4504294,2.1804703 2.3388697,2.1322773 2.2228138,2.1534226 c -0.049738,0.00906 -0.079877,0.031683 -0.1296145,0.040745 L 1.9734996,2.8024787 1.8537998,3.4107898 1.689464,4.211545 1.0707466,5.2436753 1.3712806,5.4904898 Z"
|
||||||
|
sodipodi:nodetypes="sssssccccccccccccsccccccc" />
|
||||||
|
<path
|
||||||
|
id="rect915"
|
||||||
|
style="opacity:0.997;fill:#ffffff;stroke:#ffffff;stroke-width:0.248933;stroke-linejoin:round;stroke-opacity:1;paint-order:stroke fill markers"
|
||||||
|
transform="matrix(0.99300752,0.11805114,-0.2203786,0.97541441,0,0)"
|
||||||
|
d="m 2.276527,2.111288 v 0 0.8237278 -0.08059 z"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,496 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="22"
|
||||||
|
height="22"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
sodipodi:docname="ic_activity_escooter.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect3162"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect3149"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect2514"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect950"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect946"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect918"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect912"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect894"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#232629"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="22.390336"
|
||||||
|
inkscape:cx="13.383174"
|
||||||
|
inkscape:cy="12.569634"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1444"
|
||||||
|
inkscape:window-height="780"
|
||||||
|
inkscape:window-x="245"
|
||||||
|
inkscape:window-y="142"
|
||||||
|
inkscape:window-maximized="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid833"
|
||||||
|
empspacing="22"
|
||||||
|
dotted="true" />
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid835"
|
||||||
|
empspacing="1"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
originx="0.26458333"
|
||||||
|
originy="0.26458333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="4.195,4.2333333"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
id="guide887"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:color="rgb(0,0,255)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0.26458333,1.9843751"
|
||||||
|
orientation="0,-1"
|
||||||
|
id="guide900" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
id="g3168"
|
||||||
|
style="stroke:#909090;stroke-opacity:1">
|
||||||
|
<path
|
||||||
|
id="path901"
|
||||||
|
d="M 2.3632812 1.984375 A 0.1324995 0.1324995 0 0 0 2.25 2.1347656 A 0.1324995 0.1324995 0 0 0 2.3984375 2.2480469 C 2.6424435 2.2158044 2.9061719 2.3043649 3.0820312 2.4765625 C 3.2048822 2.5968554 3.2894144 2.7590671 3.3085938 2.9257812 C 3.3213476 3.0366427 3.3054638 3.1596364 3.2929688 3.2949219 C 3.2804368 3.4306071 3.2701901 3.583197 3.3105469 3.7382812 C 3.3438455 3.8662421 3.4102315 3.9828889 3.5019531 4.078125 C 3.5936748 4.1733611 3.7093185 4.2451189 3.8359375 4.2832031 A 0.1324995 0.1324995 0 0 0 4.0019531 4.1933594 A 0.1324995 0.1324995 0 0 0 3.9121094 4.0292969 C 3.8297238 4.0045171 3.7530387 3.9564973 3.6933594 3.8945312 C 3.63368 3.8325652 3.5900254 3.7531805 3.5683594 3.6699219 C 3.5418024 3.5678678 3.5466893 3.4492033 3.5585938 3.3203125 C 3.5705351 3.191022 3.5879256 3.0476308 3.5703125 2.8945312 C 3.5435298 2.6617257 3.4320694 2.4481756 3.2675781 2.2871094 C 3.0309201 2.0553789 2.691646 1.9409856 2.3632812 1.984375 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#909090;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<path
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
id="path905"
|
||||||
|
d="M 6 5.5 A 0.50083507 0.50083507 0 0 0 5.5 6 L 5.5 10 A 0.50083507 0.50083507 0 0 0 6 10.5 L 7 10.5 C 8.3752137 10.5 9.5000001 9.3752139 9.5 8 C 9.4999999 6.6247863 8.3752137 5.5000001 7 5.5 L 6 5.5 z M 6.5 6.5 L 7 6.5 C 7.8339253 6.5000001 8.4999999 7.1660747 8.5 8 C 8.5000001 8.8339251 7.8339253 9.4999999 7 9.5 L 6.5 9.5 L 6.5 6.5 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#909090;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00157;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path909"
|
||||||
|
d="M 1.0585938 1.71875 A 0.1324995 0.1324995 0 0 0 0.92578125 1.8515625 A 0.1324995 0.1324995 0 0 0 1.0585938 1.984375 L 1.5878906 1.984375 A 0.1324995 0.1324995 0 0 0 1.7207031 1.8515625 A 0.1324995 0.1324995 0 0 0 1.5878906 1.71875 L 1.0585938 1.71875 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#909090;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path913"
|
||||||
|
d="M 1.0585938 2.2480469 A 0.1324995 0.1324995 0 0 0 0.92578125 2.3808594 A 0.1324995 0.1324995 0 0 0 1.0585938 2.5136719 L 1.5878906 2.5136719 A 0.1324995 0.1324995 0 0 0 1.7207031 2.3808594 A 0.1324995 0.1324995 0 0 0 1.5878906 2.2480469 L 1.0585938 2.2480469 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#909090;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="path924"
|
||||||
|
style="opacity:1;fill:#fdbc4b;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke"
|
||||||
|
d="m -1.3252903,1.5032615 -0.4100651,0.6834418 a 0.12845631,0.12845631 60.481872 0 0 0.1101504,0.1945466 l 0.2495783,-10e-8 -0.1100188,0.5495576 a 0.08982544,0.08982544 21.142221 0 0 0.1651025,0.063848 L -0.91047797,2.3112131 A 0.12845634,0.12845634 60.481877 0 0 -1.0206284,2.1166665 H -1.2702067 L -1.1601879,1.567109 a 0.08982541,0.08982541 21.142225 0 0 -0.1651024,-0.063848 z"
|
||||||
|
sodipodi:nodetypes="ccccccc"
|
||||||
|
inkscape:original-d="m -1.0583333,1.0583332 -0.79375,1.3229167 0.4764566,-10e-8 L -1.5875,3.4395832 -0.79375003,2.1166665 H -1.2702067 Z"
|
||||||
|
inkscape:path-effect="#path-effect950" />
|
||||||
|
<g
|
||||||
|
id="g954"
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)">
|
||||||
|
<rect
|
||||||
|
y="-7.9375"
|
||||||
|
x="-357.1875"
|
||||||
|
height="79.375"
|
||||||
|
width="68.791664"
|
||||||
|
id="rect919"
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect851"
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect853"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect855"
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect857"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect859"
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect861"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect863"
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect865"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect867"
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect869"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect871"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect873"
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect875"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect877"
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect879"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect881"
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect883"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect885"
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect887"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect889"
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect891"
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect893"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect895"
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect897"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect899"
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect901"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect903"
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect905"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect907"
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect909"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect911"
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect913"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="58.208336" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
id="path887"
|
||||||
|
d="M 13.994141 4.5 A 0.49999949 0.49999949 0 0 0 13.552734 4.7773438 A 0.49999949 0.49999949 0 0 0 13.777344 5.4472656 L 14.908203 6.0136719 C 15.328243 6.2241517 15.636226 6.6066586 15.75 7.0625 L 17.390625 13.623047 C 15.381402 13.909129 13.837817 15.475476 13.601562 17.5 L 8.3984375 17.5 C 8.1378934 15.267332 6.3043435 13.50201 4.0039062 13.5 C 3.982495 13.499838 3.9608645 13.499856 3.9394531 13.5 L 2 13.5 A 0.49999949 0.49999949 0 0 0 1.5 14 A 0.49999949 0.49999949 0 0 0 2 14.5 L 3.9394531 14.5 A 0.50004949 0.50004949 0 0 0 3.9433594 14.5 C 3.9610145 14.499866 3.9784387 14.499866 3.9960938 14.5 A 0.50004949 0.50004949 0 0 0 4 14.5 C 5.9389193 14.5 7.5000003 16.061081 7.5 18 A 0.50004949 0.50004949 0 0 0 8 18.5 L 14 18.5 A 0.50004949 0.50004949 0 0 0 14.5 18 C 14.5 16.061081 16.061081 14.5 18 14.5 A 0.50004949 0.50004949 0 0 0 18.484375 13.878906 L 16.71875 6.8203125 C 16.534472 6.0819921 16.037756 5.460052 15.357422 5.1191406 A 0.50004949 0.50004949 0 0 0 15.355469 5.1191406 L 14.222656 4.5527344 A 0.49999949 0.49999949 0 0 0 13.994141 4.5 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00157481;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path970"
|
||||||
|
d="M 4.7617188 4.1367188 C 4.4265639 4.1367188 4.1523438 4.4109389 4.1523438 4.7460938 C 4.1523438 5.0812486 4.4265639 5.3554687 4.7617188 5.3554688 C 5.0968736 5.3554687 5.3710937 5.0812486 5.3710938 4.7460938 C 5.3710937 4.4109389 5.0968736 4.1367188 4.7617188 4.1367188 z M 4.7617188 4.3378906 C 4.9879388 4.3378906 5.1679687 4.5198737 5.1679688 4.7460938 C 5.1679687 4.9723138 4.9879388 5.1542969 4.7617188 5.1542969 C 4.5354987 5.1542969 4.3535156 4.9723138 4.3535156 4.7460938 C 4.3535156 4.5198737 4.5354987 4.3378906 4.7617188 4.3378906 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.201567;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:0.997" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.997;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.201567;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 1.0221536,4.1367188 c -0.33515491,0 -0.60937501,0.2742201 -0.60937501,0.609375 0,0.3351548 0.2742201,0.6093749 0.60937501,0.609375 0.3351548,-10e-8 0.6093749,-0.2742202 0.609375,-0.609375 -1e-7,-0.3351549 -0.2742202,-0.609375 -0.609375,-0.609375 z m 0,0.2011718 c 0.22622,0 0.4062499,0.1819831 0.40625,0.4082032 -1e-7,0.2262201 -0.18003,0.4082031 -0.40625,0.4082031 -0.22622011,0 -0.40820321,-0.181983 -0.40820321,-0.4082031 0,-0.2262201 0.1819831,-0.4082032 0.40820321,-0.4082032 z"
|
||||||
|
id="path970-7" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,515 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
sodipodi:docname="ic_activity_inlineskater.svg"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
height="22"
|
||||||
|
width="22">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect3162"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect3149"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect2514"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect950"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect946"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect918"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect912"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect894"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-x="67"
|
||||||
|
inkscape:window-height="1025"
|
||||||
|
inkscape:window-width="1853"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
units="px"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:cy="10.868962"
|
||||||
|
inkscape:cx="8.471442"
|
||||||
|
inkscape:zoom="22.390336"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#232629"
|
||||||
|
id="base">
|
||||||
|
<inkscape:grid
|
||||||
|
dotted="true"
|
||||||
|
empspacing="22"
|
||||||
|
id="grid833"
|
||||||
|
type="xygrid" />
|
||||||
|
<inkscape:grid
|
||||||
|
originy="0.26458333"
|
||||||
|
originx="0.26458333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
empspacing="1"
|
||||||
|
id="grid835"
|
||||||
|
type="xygrid" />
|
||||||
|
<sodipodi:guide
|
||||||
|
inkscape:color="rgb(0,0,255)"
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:label=""
|
||||||
|
id="guide887"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
position="4.195,4.2333333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
id="guide900"
|
||||||
|
orientation="0,-1"
|
||||||
|
position="0.26458333,1.9843751" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<path
|
||||||
|
d="m 3.3722093,1.2527829 c 0.2415068,0 0.4391032,-0.1975962 0.4391032,-0.43910305 0,-0.24150691 -0.1975964,-0.43910339 -0.4391032,-0.43910339 -0.241507,0 -0.4391033,0.19759648 -0.4391033,0.43910339 0,0.24150685 0.1975963,0.43910305 0.4391033,0.43910305 z M 2.5818232,4.3045509 2.8013749,3.3385235 3.2624334,3.7776271 V 5.0949369 H 3.7015366 V 3.4482998 L 3.2404782,3.0091963 3.3722093,2.3505413 c 0.285417,0.3293275 0.7245203,0.5488792 1.207534,0.5488792 V 2.4603172 c -0.4171482,0 -0.7684308,-0.2195517 -0.944072,-0.5269241 L 3.4161195,1.5821105 C 3.3282991,1.4503796 3.1965678,1.3625589 3.0428817,1.3625589 c -0.065865,0 -0.1097755,0.021955 -0.1756413,0.021955 L 1.7255717,1.867528 V 2.8994208 H 2.1646753 V 2.1529448 L 2.5598682,1.9992587 2.2085854,3.7776271 1.1327827,3.5580754 1.0449623,3.9971789 Z"
|
||||||
|
id="path17"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.219552;stroke-opacity:1" />
|
||||||
|
<g
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)"
|
||||||
|
id="g954">
|
||||||
|
<rect
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect919"
|
||||||
|
width="68.791664"
|
||||||
|
height="79.375"
|
||||||
|
x="-357.1875"
|
||||||
|
y="-7.9375" />
|
||||||
|
<rect
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect851"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect853"
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect855"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect857"
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect859"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect861"
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect863"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect865"
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect867"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect869"
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect871"
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect873"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect875"
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect877"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect879"
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect881"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect883"
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect885"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect887"
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect889"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect891"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect893"
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect895"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect897"
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect899"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect901"
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect903"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect905"
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect907"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect909"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect911"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect913"
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(-0.30905888,1.6151387,-1.6151387,-0.30905888,9.3627856,1.8488419)"
|
||||||
|
id="g943">
|
||||||
|
<circle
|
||||||
|
style="opacity:0.997;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||||
|
id="path892"
|
||||||
|
cx="1.6512442"
|
||||||
|
cy="4.9452085"
|
||||||
|
r="0.12575205" />
|
||||||
|
<circle
|
||||||
|
r="0.12575205"
|
||||||
|
cy="4.9452085"
|
||||||
|
cx="1.9359355"
|
||||||
|
id="path892-3"
|
||||||
|
style="opacity:0.997;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linejoin:round;paint-order:stroke fill markers" />
|
||||||
|
<circle
|
||||||
|
style="opacity:0.997;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||||
|
id="path892-3-6"
|
||||||
|
cx="2.2206268"
|
||||||
|
cy="4.9452085"
|
||||||
|
r="0.12575205" />
|
||||||
|
<circle
|
||||||
|
r="0.12575205"
|
||||||
|
cy="4.9452085"
|
||||||
|
cx="2.5053182"
|
||||||
|
id="path892-3-6-7"
|
||||||
|
style="opacity:0.997;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linejoin:round;paint-order:stroke fill markers" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g943-2"
|
||||||
|
transform="matrix(1.6443153,-0.0204346,0.0204346,1.6443153,-0.01361945,-2.6499566)">
|
||||||
|
<circle
|
||||||
|
r="0.12575205"
|
||||||
|
cy="4.9452085"
|
||||||
|
cx="1.6512442"
|
||||||
|
id="path892-7"
|
||||||
|
style="opacity:0.997;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linejoin:round;paint-order:stroke fill markers" />
|
||||||
|
<circle
|
||||||
|
style="opacity:0.997;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||||
|
id="path892-3-0"
|
||||||
|
cx="1.9359355"
|
||||||
|
cy="4.9452085"
|
||||||
|
r="0.12575205" />
|
||||||
|
<circle
|
||||||
|
r="0.12575205"
|
||||||
|
cy="4.9452085"
|
||||||
|
cx="2.2206268"
|
||||||
|
id="path892-3-6-9"
|
||||||
|
style="opacity:0.997;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linejoin:round;paint-order:stroke fill markers" />
|
||||||
|
<circle
|
||||||
|
style="opacity:0.997;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||||
|
id="path892-3-6-7-3"
|
||||||
|
cx="2.5053182"
|
||||||
|
cy="4.9452085"
|
||||||
|
r="0.12575205" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,546 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
sodipodi:docname="ic_activity_motorbike.svg"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
height="22"
|
||||||
|
width="22">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect1386"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect1382"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.99999977,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect1373"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect1369"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect1357"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,2,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.093080149,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect3277"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,2,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0,0,1 @ F,0,1,1,0,0,0,1 @ F,0,0,1,0,3.210527,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect2514"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect950"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect946"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect918"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect912"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect894"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-x="67"
|
||||||
|
inkscape:window-height="1025"
|
||||||
|
inkscape:window-width="1853"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
units="px"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:cy="12.219337"
|
||||||
|
inkscape:cx="11.776234"
|
||||||
|
inkscape:zoom="27.983802"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#232629"
|
||||||
|
id="base">
|
||||||
|
<inkscape:grid
|
||||||
|
dotted="true"
|
||||||
|
empspacing="22"
|
||||||
|
id="grid833"
|
||||||
|
type="xygrid" />
|
||||||
|
<inkscape:grid
|
||||||
|
originy="0.26458333"
|
||||||
|
originx="0.26458333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
empspacing="1"
|
||||||
|
id="grid835"
|
||||||
|
type="xygrid" />
|
||||||
|
<sodipodi:guide
|
||||||
|
inkscape:color="rgb(0,0,255)"
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:label=""
|
||||||
|
id="guide887"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
position="4.195,4.2333333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
id="guide900"
|
||||||
|
orientation="0,-1"
|
||||||
|
position="0.26458333,1.9843751" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<g
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)"
|
||||||
|
id="g954">
|
||||||
|
<rect
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect919"
|
||||||
|
width="68.791664"
|
||||||
|
height="79.375"
|
||||||
|
x="-357.1875"
|
||||||
|
y="-7.9375" />
|
||||||
|
<rect
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect851"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect853"
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect855"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect857"
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect859"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect861"
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect863"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect865"
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect867"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect869"
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect871"
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect873"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect875"
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect877"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect879"
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect881"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect883"
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect885"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect887"
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect889"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect891"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect893"
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect895"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect897"
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect899"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect901"
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect903"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect905"
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect907"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect909"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect911"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect913"
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="path901"
|
||||||
|
d="M 1.8574219 3.3066406 A 0.1322915 0.1322915 0 0 0 1.7363281 3.375 L 1.0742188 4.5664062 A 0.13230472 0.13230472 0 0 0 1.2050781 4.7617188 L 2.3964844 4.6289062 A 0.1322915 0.1322915 0 0 0 2.5136719 4.4824219 A 0.1322915 0.1322915 0 0 0 2.3671875 4.3671875 L 1.4316406 4.4707031 L 1.9667969 3.5039062 A 0.1322915 0.1322915 0 0 0 1.9160156 3.3242188 A 0.1322915 0.1322915 0 0 0 1.8574219 3.3066406 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path905"
|
||||||
|
d="M 3.1757812 1.984375 A 0.1322915 0.1322915 0 0 0 3.0429688 2.1171875 A 0.1322915 0.1322915 0 0 0 3.1757812 2.2480469 L 3.6113281 2.2480469 L 4.5058594 4.6757812 A 0.1322915 0.1322915 0 0 0 4.6757812 4.7539062 A 0.1322915 0.1322915 0 0 0 4.7539062 4.5839844 L 3.828125 2.0703125 A 0.13230472 0.13230472 0 0 0 3.7050781 1.984375 L 3.1757812 1.984375 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<path
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
id="path909"
|
||||||
|
d="M 4.9765625 11.5 A 0.50004949 0.50004949 0 0 0 4.5 12 L 4.5 13 A 0.50004949 0.50004949 0 0 0 5 13.5 L 8 13.5 A 0.50004949 0.50004949 0 0 0 8.4882812 13.064453 A 0.50004949 0.50004949 0 0 0 8.4921875 13.005859 A 0.50004949 0.50004949 0 0 0 8.2871094 12.595703 A 0.50004949 0.50004949 0 0 0 8.2382812 12.564453 A 0.50004949 0.50004949 0 0 0 8.0703125 12.505859 A 0.50004949 0.50004949 0 0 0 8.0117188 12.5 A 0.50004949 0.50004949 0 0 0 8 12.5 C 7.0833333 12.5 6.4130278 12.27292 5.9726562 12.052734 C 5.5322847 11.832549 5.3535156 11.646484 5.3535156 11.646484 A 0.50004949 0.50004949 0 0 0 4.9765625 11.5 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path913"
|
||||||
|
d="M 2.7773438 4.1015625 A 0.13249999 0.13249999 0 0 0 2.6464844 4.2324219 A 0.13249999 0.13249999 0 0 0 2.7773438 4.3652344 L 3.0429688 4.3652344 A 0.13249999 0.13249999 0 0 0 3.1757812 4.2324219 A 0.13249999 0.13249999 0 0 0 3.0429688 4.1015625 L 2.7773438 4.1015625 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.265;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<g
|
||||||
|
style="opacity:1"
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
id="g915">
|
||||||
|
<path
|
||||||
|
id="path917"
|
||||||
|
d="m 16.5,10.5 c -0.271556,0.0063 -0.500074,0.228371 -0.5,0.5 0,0.276144 0.223858,0.5 0.5,0.5 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00157;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1.0;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;" />
|
||||||
|
<path
|
||||||
|
id="path919"
|
||||||
|
d="M 16.488281 10 C 15.950439 10.012478 15.499849 10.447427 15.5 11 C 15.5 11.546787 15.953215 12 16.5 12 A 0.50083507 0.50083507 0 0 0 17 11.5 L 17 10.5 A 0.50083507 0.50083507 0 0 0 16.488281 10 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00157;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1.0;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
transform="scale(0.26458333)"
|
||||||
|
id="path923"
|
||||||
|
d="M 11 11.5 C 10.371809 11.5 9.9307721 11.946836 9.7089844 12.5 L 8 12.5 A 0.50004949 0.50004949 0 0 0 7.5234375 13.152344 L 9.1230469 18.152344 A 0.50004949 0.50004949 0 0 0 9.5996094 18.5 L 13 18.5 A 0.50004949 0.50004949 0 0 0 13.5 18 C 13.5 17.777537 13.499839 17.669786 13.5 17.5 C 13.500093 15.822204 14.542706 14.325749 16.117188 13.746094 A 0.50004949 0.50004949 0 0 0 16.414062 13.103516 L 15.943359 11.826172 A 0.50004949 0.50004949 0 0 0 15.474609 11.5 L 11 11.5 z M 11 12.5 L 15.126953 12.5 L 15.357422 13.128906 C 13.674401 13.966365 12.500106 15.589879 12.5 17.5 L 9.9648438 17.5 L 8.6855469 13.5 L 10 13.5 A 0.50004949 0.50004949 0 0 0 10.5 13 C 10.5 12.717935 10.717935 12.5 11 12.5 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:531.552;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:0.994135" />
|
||||||
|
<path
|
||||||
|
id="path927"
|
||||||
|
d="M 2.7773438 3.703125 A 0.13249999 0.13249999 0 0 0 2.6464844 3.8359375 A 0.13249999 0.13249999 0 0 0 2.7773438 3.96875 L 3.0429688 3.96875 A 0.13249999 0.13249999 0 0 0 3.1757812 3.8359375 A 0.13249999 0.13249999 0 0 0 3.0429688 3.703125 L 2.7773438 3.703125 z "
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.265;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.997;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.261354;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 4.6258209,3.8250746 c -0.4345653,0 -0.7901218,0.3555565 -0.7901218,0.7901218 0,0.4345652 0.3555565,0.7901217 0.7901218,0.7901218 0.4345652,-1e-7 0.7901217,-0.3555566 0.7901217,-0.7901218 0,-0.4345653 -0.3555565,-0.7901218 -0.7901217,-0.7901218 z m 0,0.2608413 c 0.2933192,0 0.5267476,0.2359612 0.5267479,0.5292805 0,0.2933193 -0.2334287,0.5292803 -0.5267479,0.5292803 -0.2933193,0 -0.5292805,-0.235961 -0.5292805,-0.5292803 0,-0.2933193 0.2359612,-0.5292805 0.5292805,-0.5292805 z"
|
||||||
|
id="path970-7-3" />
|
||||||
|
<path
|
||||||
|
id="path970-7-3-6"
|
||||||
|
d="m 1.2138007,3.8250746 c -0.43456528,0 -0.79012178,0.3555565 -0.79012178,0.7901218 0,0.4345652 0.3555565,0.7901217 0.79012178,0.7901218 0.4345652,-1e-7 0.7901217,-0.3555566 0.7901217,-0.7901218 0,-0.4345653 -0.3555565,-0.7901218 -0.7901217,-0.7901218 z m 0,0.2608413 c 0.2933192,0 0.5267476,0.2359612 0.5267479,0.5292805 0,0.2933193 -0.2334287,0.5292803 -0.5267479,0.5292803 -0.29331928,0 -0.52928048,-0.235961 -0.52928048,-0.5292803 0,-0.2933193 0.2359612,-0.5292805 0.52928048,-0.5292805 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.997;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.261354;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 35 KiB |
@@ -0,0 +1,464 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="22"
|
||||||
|
height="22"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
sodipodi:docname="ic_activity_mtb.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect3162"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect3149"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect2514"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect950"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect946"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect918"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect912"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect894"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#232629"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="15.832358"
|
||||||
|
inkscape:cx="2.2323103"
|
||||||
|
inkscape:cy="8.8776466"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1596"
|
||||||
|
inkscape:window-height="917"
|
||||||
|
inkscape:window-x="123"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid833"
|
||||||
|
empspacing="22"
|
||||||
|
dotted="true" />
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid835"
|
||||||
|
empspacing="1"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
originx="0.26458333"
|
||||||
|
originy="0.26458333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="4.195,4.2333333"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
id="guide887"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:color="rgb(0,0,255)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0.26458333,1.9843751"
|
||||||
|
orientation="0,-1"
|
||||||
|
id="guide900" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
id="g954"
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)">
|
||||||
|
<rect
|
||||||
|
y="-7.9375"
|
||||||
|
x="-357.1875"
|
||||||
|
height="79.375"
|
||||||
|
width="68.791664"
|
||||||
|
id="rect919"
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect851"
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect853"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect855"
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect857"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect859"
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect861"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect863"
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect865"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect867"
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect869"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect871"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect873"
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect875"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect877"
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect879"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect881"
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect883"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect885"
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect887"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect889"
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect891"
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect893"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect895"
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect897"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect899"
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect901"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect903"
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect905"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect907"
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect909"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect911"
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect913"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="58.208336" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:0.196349"
|
||||||
|
id="path51"
|
||||||
|
d="M 1.8042087,1.0709424 C 1.9783861,0.94322723 2.0164009,0.69622363 1.8886857,0.52204593 1.7609704,0.34786823 1.5139667,0.30985363 1.3397894,0.43756873 1.1656114,0.56528423 1.1275967,0.81228773 1.2553124,0.98646553 1.3830273,1.1606434 1.6300308,1.198658 1.8042087,1.0709424 Z M 0.89628461,3.3192757 C 0.4529229,3.6443694 0.35999832,4.2481554 0.68509192,4.6915169 1.0101856,5.1348783 1.6139715,5.2278033 2.0573332,4.9027093 2.5006949,4.5776158 2.5936197,3.9738298 2.2685259,3.5304682 1.9434323,3.0871067 1.3396463,2.9941819 0.89628461,3.3192757 Z M 1.883176,4.6651945 C 1.5823234,4.8857933 1.143206,4.8182123 0.92260684,4.5173598 0.70200762,4.2165074 0.76958946,3.77739 1.0704419,3.5567908 1.3712945,3.3361914 1.8104113,3.4037735 2.0310104,3.7046258 2.2516097,4.0054783 2.1840285,4.4445951 1.883176,4.6651945 Z M 1.6405189,2.4083524 1.7418913,1.7496767 1.9614496,1.7834677 c 0.3567831,0.05491 0.7188509,-0.015794 1.051372,-0.2596139 L 2.7806119,1.2071669 C 2.5430963,1.3813245 2.2834214,1.4256443 2.0364186,1.3876293 L 1.5149667,1.3073761 C 1.3893532,1.3020906 1.2869605,1.3284748 1.1919542,1.3981379 1.0969485,1.4678006 1.0409979,1.5575218 1.0399363,1.6556909 L 0.92166874,2.4241458 c -0.0168959,0.1097797 0.009488,0.2121721 0.0675406,0.2913438 0.0696627,0.095006 0.15938086,0.150959 0.25755306,0.1520177 L 2.0785546,2.9393333 2.6590789,3.7310504 2.9757655,3.4988407 2.2559153,2.5171116 Z M 3.1130918,1.6938078 C 2.6697307,2.0189011 2.5768054,2.6226876 2.9018991,3.0660491 3.2269927,3.5094107 3.8307793,3.602335 4.2741404,3.2772417 4.7175021,2.952148 4.8104268,2.348362 4.4853331,1.9050004 4.1602394,1.4616389 3.5564535,1.368714 3.1130918,1.6938078 Z M 4.0999832,3.0397266 C 3.7991307,3.2603259 3.3600139,3.1927439 3.1394147,2.8918914 2.9188155,2.5910391 2.9863967,2.1519221 3.2872491,1.9313229 3.5881015,1.7107237 4.0272189,1.7783052 4.2478182,2.0791576 4.4684174,2.38001 4.4008356,2.8191274 4.0999832,3.0397266 Z" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccccccccccc"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="M 6.2355927,2.3458251 4.366485,3.4225311 3.0292969,4.9121094 2.0999371,5.0657395 1.5371094,5.4570312 -0.2265625,5.8183594 -0.17382812,6.0761719 1.7207031,5.6914062 2.2796245,5.3059739 3.21875,5.1503906 4.5637507,3.639328 6.4484834,2.5587157 Z"
|
||||||
|
id="path920" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,477 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="22"
|
||||||
|
height="22"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
sodipodi:docname="ic_activity_sailing.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect3162"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect3149"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect2514"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect950"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect946"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect918"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect912"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect894"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#232629"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="22.390336"
|
||||||
|
inkscape:cx="13.656644"
|
||||||
|
inkscape:cy="9.1983306"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1596"
|
||||||
|
inkscape:window-height="917"
|
||||||
|
inkscape:window-x="123"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid833"
|
||||||
|
empspacing="22"
|
||||||
|
dotted="true" />
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid835"
|
||||||
|
empspacing="1"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
originx="0.26458333"
|
||||||
|
originy="0.26458333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="4.195,4.2333333"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
id="guide887"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:color="rgb(0,0,255)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0.26458333,1.9843751"
|
||||||
|
orientation="0,-1"
|
||||||
|
id="guide900" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
id="g954"
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)">
|
||||||
|
<rect
|
||||||
|
y="-7.9375"
|
||||||
|
x="-357.1875"
|
||||||
|
height="79.375"
|
||||||
|
width="68.791664"
|
||||||
|
id="rect919"
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect851"
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect853"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect855"
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect857"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect859"
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect861"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect863"
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect865"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect867"
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect869"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect871"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect873"
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect875"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect877"
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect879"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect881"
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect883"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect885"
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect887"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect889"
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect891"
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect893"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect895"
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect897"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect899"
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect901"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect903"
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect905"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect907"
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect909"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect911"
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect913"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="58.208336" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
id="path900"
|
||||||
|
d="M 0.56041665,4.4708333 1.1604167,5.4 h 3.5 l 0.6,-0.9291667 z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
id="path902"
|
||||||
|
d="M 2.8024332,0.32721116 V 4.5 H 3.0184001 V 0.32721116 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.244823px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path904"
|
||||||
|
d="M 2.6527855,1.0066933 2.6459669,4.192806 0.73848581,4.2035269 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.257218px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.281927px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 3.1616713,0.35463877 0.00682,3.82765233 1.9074808,0.01288 z"
|
||||||
|
id="path904-3" />
|
||||||
|
<path
|
||||||
|
id="path921"
|
||||||
|
d="M 2.8105515,0.32721116 V 0.75450025 L 2.0324942,0.57664397 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.286457px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,482 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="22"
|
||||||
|
height="22"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
sodipodi:docname="ic_activity_skateboarding.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect3162"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect3149"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect2514"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect950"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect946"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect918"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect912"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect894"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
guidetolerance="7.7"
|
||||||
|
objecttolerance="7.7"
|
||||||
|
inkscape:lockguides="true"
|
||||||
|
id="base"
|
||||||
|
pagecolor="#232629"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.195168"
|
||||||
|
inkscape:cx="12.030411"
|
||||||
|
inkscape:cy="9.6162221"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1853"
|
||||||
|
inkscape:window-height="1025"
|
||||||
|
inkscape:window-x="67"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
snapvisiblegridlinesonly="false"
|
||||||
|
type="xygrid"
|
||||||
|
id="grid833"
|
||||||
|
empspacing="22"
|
||||||
|
dotted="true" />
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid835"
|
||||||
|
empspacing="1"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
originx="0.26458333"
|
||||||
|
originy="0.26458333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="4.195,4.2333333"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
id="guide887"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:locked="true"
|
||||||
|
inkscape:color="rgb(0,0,255)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
inkscape:locked="true"
|
||||||
|
position="0.26458333,1.9843751"
|
||||||
|
orientation="0,-1"
|
||||||
|
id="guide900" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssccccccccccccsccccccccccc"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.244651;stroke-opacity:1"
|
||||||
|
id="path17"
|
||||||
|
d="M 3.4497594,1.2723995 C 3.7188321,1.2675879 3.9350456,1.043501 3.9302338,0.7744294 3.9254222,0.50535723 3.7013352,0.28914379 3.4322626,0.29395542 3.1631898,0.29876705 2.9469764,0.5228543 2.9517881,0.7919262 2.9565981,1.0609979 3.1806867,1.2772111 3.4497594,1.2723995 Z M 3.0637352,4.3310097 2.8499094,3.4654121 3.5050565,3.7377246 4.0318851,5.1078311 4.4885872,4.9322216 3.8300515,3.2195885 3.1749046,2.9472761 3.3770914,2.4212785 C 3.7016475,2.7825092 4.1834322,3.0452834 4.7215778,3.0356596 L 4.7128291,2.5464372 C 4.2480673,2.5547482 3.9586663,2.3644029 3.7568534,2.0254461 L 3.5052429,1.6384419 C 3.4047741,1.4934249 3.2562572,1.3982048 3.0850292,1.4012668 c -0.073384,0.00131 -0.1218679,0.026649 -0.1952518,0.02796 L 1.627421,1.9901187 1.2471269,3.0265669 1.6538376,3.2423177 2.0691965,2.3071052 2.5595693,2.120264 2.1081061,3.2524111 2.4089713,4.1591882 1.3164273,4.8578585 1.9480117,4.971638 Z" />
|
||||||
|
<g
|
||||||
|
id="g954"
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)">
|
||||||
|
<rect
|
||||||
|
y="-7.9375"
|
||||||
|
x="-357.1875"
|
||||||
|
height="79.375"
|
||||||
|
width="68.791664"
|
||||||
|
id="rect919"
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect851"
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect853"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect855"
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect857"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect859"
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect861"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect863"
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect865"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect867"
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect869"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect871"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect873"
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect875"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect877"
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect879"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect881"
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect883"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect885"
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect887"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect889"
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect891"
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect893"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect895"
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect897"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect899"
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect901"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect903"
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect905"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect907"
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect909"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect911"
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect913"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="58.208336" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccccccccc"
|
||||||
|
d="M 0.70720657,4.618942 0.50519813,4.8871827 c -3e-8,0 0.1915452,0.1543669 0.29349555,0.2268814 0.0408697,0.022353 0.0297057,0.028139 0.10131117,0.035126 l 2.08762525,-0.0023 2.0876253,0.0023 c 0.071605,-0.00699 0.061055,-0.012773 0.1019258,-0.035126 C 5.2791315,5.04155 5.4700628,4.8871827 5.4700628,4.8871827 L 5.2680537,4.618942 5.0181529,4.8124246 3.1356059,4.811273 H 2.8396543 l -1.88193269,0.00115 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.304444px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="path894-3" />
|
||||||
|
<circle
|
||||||
|
r="0.1149179"
|
||||||
|
cy="5.4143333"
|
||||||
|
cx="1.4282604"
|
||||||
|
id="path999"
|
||||||
|
style="opacity:0.997;fill:#ffffff;stroke:#ffffff;stroke-width:0.264999;stroke-linejoin:round;stroke-opacity:1;paint-order:stroke fill markers" />
|
||||||
|
<circle
|
||||||
|
style="opacity:0.997;fill:#ffffff;stroke:#ffffff;stroke-width:0.264999;stroke-linejoin:round;stroke-opacity:1;paint-order:stroke fill markers"
|
||||||
|
id="path999-5"
|
||||||
|
cx="4.4387093"
|
||||||
|
cy="5.4143333"
|
||||||
|
r="0.1149179" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,469 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
sodipodi:docname="ic_activity_skiing.svg"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
height="22"
|
||||||
|
width="22">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect3162"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect3149"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect2514"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect950"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect946"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect918"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect912"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect894"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:window-y="175"
|
||||||
|
inkscape:window-x="67"
|
||||||
|
inkscape:window-height="780"
|
||||||
|
inkscape:window-width="1444"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
units="px"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:cy="11.008507"
|
||||||
|
inkscape:cx="12.634965"
|
||||||
|
inkscape:zoom="15.832358"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#232629"
|
||||||
|
id="base">
|
||||||
|
<inkscape:grid
|
||||||
|
dotted="true"
|
||||||
|
empspacing="22"
|
||||||
|
id="grid833"
|
||||||
|
type="xygrid" />
|
||||||
|
<inkscape:grid
|
||||||
|
originy="0.26458333"
|
||||||
|
originx="0.26458333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
empspacing="1"
|
||||||
|
id="grid835"
|
||||||
|
type="xygrid" />
|
||||||
|
<sodipodi:guide
|
||||||
|
inkscape:color="rgb(0,0,255)"
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:label=""
|
||||||
|
id="guide887"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
position="4.195,4.2333333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
id="guide900"
|
||||||
|
orientation="0,-1"
|
||||||
|
position="0.26458333,1.9843751" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ssssscccccccccccsacccccc"
|
||||||
|
d="M 4.5585535,1.8682464 C 4.730575,2.037758 5.0100109,2.0357042 5.1795224,1.8636824 5.3490338,1.6916608 5.3469796,1.4122249 5.1749586,1.2427137 5.0029369,1.0732022 4.7235009,1.075256 4.5539893,1.2472777 4.3844781,1.419299 4.3865322,1.6987351 4.5585535,1.8682464 Z M 2.5616473,2.8895379 2.9818066,3.7412695 2.1627798,4.156586 2.4890714,4.5159652 3.6644142,3.9783412 3.3324214,3.2071044 3.7880462,2.6501643 C 3.760192,3.0850707 3.9188577,3.5496566 4.2629009,3.8886795 L 4.5711034,3.575913 C 4.2739752,3.2831205 4.1778634,2.8801752 4.2684987,2.5379577 L 4.3586776,2.1336426 C 4.3885856,1.9781722 4.356396,1.8231572 4.2469278,1.7152862 4.2000132,1.6690561 4.0431309,1.5310148 3.9171527,1.4852939 3.6109432,1.3741621 2.9436171,1.4000918 2.9436171,1.4000918 L 1.9817647,1.9917143 2.2945313,2.2999171 3.0666299,1.8154812 3.4559921,1.8297725 Z"
|
||||||
|
id="path17"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.219552;stroke-opacity:1" />
|
||||||
|
<g
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.97482,-12.494408)"
|
||||||
|
id="g954">
|
||||||
|
<rect
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect919"
|
||||||
|
width="68.791664"
|
||||||
|
height="79.375"
|
||||||
|
x="-357.1875"
|
||||||
|
y="-7.9375" />
|
||||||
|
<rect
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect851"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect853"
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect855"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect857"
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect859"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect861"
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect863"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect865"
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect867"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect869"
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect871"
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect873"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect875"
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect877"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect879"
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect881"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect883"
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect885"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect887"
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect889"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect891"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect893"
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect895"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect897"
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect899"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect901"
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect903"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect905"
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect907"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect909"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect911"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect913"
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccc"
|
||||||
|
id="path894-3"
|
||||||
|
d="m 0.42966147,3.4124371 3.27271563,1.98984 c 0.1037203,0.05566 0.091268,0.04209 0.159023,0.05977 0.1768227,0.031256 0.4686557,-0.030884 0.4686557,-0.030884 L 4.2534675,5.1832708 3.8763995,5.1892147 0.56600626,3.186415 Z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.369514px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="M 1.3650688,1.2665262 1.2347897,1.4356529 1.0541865,1.3107744 0.939761,1.4515535 1.1246616,1.5780728 0.99349664,1.748178 1.1114823,1.8390193 1.247937,1.6625738 4.3621692,3.7943987 4.471835,3.6701937 1.357598,1.5201785 1.4830545,1.3573675 Z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.238916px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="path898" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,470 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="22"
|
||||||
|
height="22"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
sodipodi:docname="ic_activity_snowboarding.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect3162"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect3149"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9999999,0,1 @ F,0,0,1,0,2.0000001,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
hide_knots="false"
|
||||||
|
only_selected="false"
|
||||||
|
apply_with_radius="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
use_knot_distance="true"
|
||||||
|
flexible="false"
|
||||||
|
chamfer_steps="1"
|
||||||
|
radius="0"
|
||||||
|
mode="F"
|
||||||
|
method="auto"
|
||||||
|
unit="px"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.97014234,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
lpeversion="1"
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect2514"
|
||||||
|
effect="fillet_chamfer" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect950"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.51887107,0,1 @ F,0,0,1,0,0.22687835,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect946"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.34892149,0,1 @ F,0,0,1,0,0.18398697,0,1 @ F,0,1,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect918"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,2.00309,0,1 @ F,0,0,1,0,2.00309,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect912"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,7.0000002,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect894"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
satellites_param="F,0,0,1,0,0.49832891,0,1 @ F,0,0,1,0,0.49832891,0,1 @ F,0,1,1,0,0.5316463,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49999976,0,1 @ F,0,0,1,0,0.50000024,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,0,1,0,0.99999982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0295214,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5316463,0,1"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
radius="0"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
guidetolerance="7.7"
|
||||||
|
objecttolerance="7.7"
|
||||||
|
inkscape:lockguides="true"
|
||||||
|
id="base"
|
||||||
|
pagecolor="#232629"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="22.390336"
|
||||||
|
inkscape:cx="3.9483707"
|
||||||
|
inkscape:cy="10.41996"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
inkscape:snap-text-baseline="true"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1853"
|
||||||
|
inkscape:window-height="1025"
|
||||||
|
inkscape:window-x="67"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
snapvisiblegridlinesonly="false"
|
||||||
|
type="xygrid"
|
||||||
|
id="grid833"
|
||||||
|
empspacing="22"
|
||||||
|
dotted="true" />
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid835"
|
||||||
|
empspacing="1"
|
||||||
|
spacingy="1.0583333"
|
||||||
|
spacingx="1.0583333"
|
||||||
|
originx="0.26458333"
|
||||||
|
originy="0.26458333" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="4.195,4.2333333"
|
||||||
|
orientation="0.96592583,0.25881905"
|
||||||
|
id="guide887"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:locked="true"
|
||||||
|
inkscape:color="rgb(0,0,255)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
inkscape:locked="true"
|
||||||
|
position="0.26458333,1.9843751"
|
||||||
|
orientation="0,-1"
|
||||||
|
id="guide900" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssccccccccccccsccccccccccc"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.244651;stroke-opacity:1"
|
||||||
|
id="path17"
|
||||||
|
d="M 3.4497594,1.6623572 C 3.7188321,1.6575456 3.9350456,1.4334587 3.9302338,1.1643861 3.9254222,0.89531328 3.7013352,0.67909984 3.4322626,0.68391147 3.1631898,0.6887231 2.9469764,0.91281035 2.9517881,1.181883 2.9566019,1.4509556 3.1806867,1.6671688 3.4497594,1.6623572 Z M 3.0637352,4.7209674 2.8499094,3.8553698 3.5050565,4.1276823 4.0318851,5.4977888 4.4885872,5.3221793 3.8300515,3.6095462 3.1749046,3.3372338 3.3770914,2.8112362 C 3.7016475,3.1724669 4.1834322,3.4352411 4.7215778,3.4256173 L 4.7128291,2.9363949 C 4.2480673,2.9447059 3.9586663,2.7543606 3.7568534,2.4154038 L 3.5052429,2.0283996 C 3.4047741,1.8833826 3.2562572,1.7881625 3.0850292,1.7912245 3.0116457,1.7925394 2.9631613,1.8178734 2.8897774,1.819185 L 1.627421,2.3800764 1.2471269,3.4165246 1.6538376,3.6322754 2.0691965,2.6970629 2.5595693,2.5102217 2.1081061,3.6423688 2.4089713,4.5491459 1.3164273,5.2478162 1.9480117,5.3615957 Z" />
|
||||||
|
<g
|
||||||
|
id="g954"
|
||||||
|
transform="matrix(0.38576851,0,0,0.38576851,152.56385,-12.494408)">
|
||||||
|
<rect
|
||||||
|
y="-7.9375"
|
||||||
|
x="-357.1875"
|
||||||
|
height="79.375"
|
||||||
|
width="68.791664"
|
||||||
|
id="rect919"
|
||||||
|
style="fill:#cacaca;fill-opacity:1;stroke-width:14.6855;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect851"
|
||||||
|
style="fill:#e74c3c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ed1515;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect853"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect855"
|
||||||
|
style="fill:#f47750;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fdbc4b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect857"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="-5.2916665" />
|
||||||
|
<rect
|
||||||
|
y="-5.2916665"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect859"
|
||||||
|
style="fill:#c9ce3b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#da4453;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect861"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect863"
|
||||||
|
style="fill:#c0392b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d35400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect865"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
y="5.291667"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect867"
|
||||||
|
style="fill:#f67400;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#f39c1f;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect869"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="5.291667" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1cdc9a;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect871"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54169"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-343.95834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect873"
|
||||||
|
style="fill:#2ecc71;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#1abc9c;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect875"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.375"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-322.79169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect877"
|
||||||
|
style="fill:#3498db;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#3daee9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect879"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20834"
|
||||||
|
y="21.166666" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-354.54169"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect881"
|
||||||
|
style="fill:#10d116;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#27ae60;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect883"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95834"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-333.375"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect885"
|
||||||
|
style="fill:#16a085;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2980b9;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect887"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79169"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="31.75"
|
||||||
|
x="-312.20834"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect889"
|
||||||
|
style="fill:#1d99f3;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
y="21.166666"
|
||||||
|
x="-301.625"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect891"
|
||||||
|
style="fill:#9b59b6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#8e44ad;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect893"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-301.625"
|
||||||
|
y="31.75" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-354.54166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect895"
|
||||||
|
style="fill:#34495e;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#31363b;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect897"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-343.95831"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-333.37497"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect899"
|
||||||
|
style="fill:#7f8c8d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#bdc3c7;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect901"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-322.79166"
|
||||||
|
y="47.625" />
|
||||||
|
<rect
|
||||||
|
y="47.625"
|
||||||
|
x="-312.20831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect903"
|
||||||
|
style="fill:#fcfcfc;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#2c3e50;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect905"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-354.54166"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-343.95831"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect907"
|
||||||
|
style="fill:#232629;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect909"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-333.37497"
|
||||||
|
y="58.208336" />
|
||||||
|
<rect
|
||||||
|
y="58.208336"
|
||||||
|
x="-322.79166"
|
||||||
|
height="10.583333"
|
||||||
|
width="10.583333"
|
||||||
|
id="rect911"
|
||||||
|
style="fill:#95a5a6;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552" />
|
||||||
|
<rect
|
||||||
|
style="fill:#eff0f1;fill-opacity:1;stroke-width:14.955;stroke-linecap:square;stroke-linejoin:round;stroke-dashoffset:531.552"
|
||||||
|
id="rect913"
|
||||||
|
width="10.583333"
|
||||||
|
height="10.583333"
|
||||||
|
x="-312.20831"
|
||||||
|
y="58.208336" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccccccccc"
|
||||||
|
d="M 0.70720657,5.0088997 0.50519813,5.2771404 c -3e-8,0 0.1915452,0.1543669 0.29349555,0.2268814 0.0408697,0.022353 0.0297057,0.028139 0.10131117,0.035126 l 2.08762525,-0.0023 2.0876253,0.0023 c 0.071605,-0.00699 0.061055,-0.012773 0.1019258,-0.035126 C 5.2791315,5.4315077 5.4700628,5.2771404 5.4700628,5.2771404 L 5.2680537,5.0088997 5.0181529,5.2023823 3.1356059,5.2012307 H 2.8396543 l -1.88193269,0.00115 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.304444px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="path894-3" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
id="svg6"
|
||||||
|
version="1.1"
|
||||||
|
height="24px"
|
||||||
|
width="24px"
|
||||||
|
fill="black"
|
||||||
|
viewBox="0 0 24 24">
|
||||||
|
<metadata id="metadata12">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<path
|
||||||
|
id="dotSmall"
|
||||||
|
d="m 14.24,12.01 2.32,2.32 C 16.84,13.61 17,12.82 17,12 17,11.18 16.84,10.41 16.57,9.69 Z" />
|
||||||
|
<path
|
||||||
|
id="dotBig"
|
||||||
|
d="m 19.53,6.71 -1.26,1.26 c 0.63,1.21 0.98,2.57 0.98,4.02 0,1.45 -0.36,2.82 -0.98,4.02 l 1.2,1.2 C 20.44,15.67 21.01,13.85 21.01,11.9 21,10.01 20.46,8.23 19.53,6.71 Z" />
|
||||||
|
<path
|
||||||
|
d="M 12.88,16.29 11,18.17 V 14.41 Z M 11,5.83 12.88,7.71 11,9.59 Z M 15.71,7.71 10,2 H 9 V 9.59 L 4.41,5 3,6.41 8.59,12 3,17.59 4.41,19 9,14.41 V 22 h 1 L 15.71,16.29 11.41,12 Z"
|
||||||
|
id="path4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,116 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
|
sodipodi:docname="ic_marker_orange_pushpin_with_shadow.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient871"
|
||||||
|
|
||||||
|
x1="91.712517"
|
||||||
|
y1="266.48581"
|
||||||
|
x2="95.902588"
|
||||||
|
y2="266.72339"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="rotate(22.027833,208.46275,168.26892)"
|
||||||
|
|
||||||
|
|
||||||
|
>
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1"
|
||||||
|
offset="0"
|
||||||
|
id="stop867" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#898d8d;stop-opacity:1"
|
||||||
|
offset="1"
|
||||||
|
id="stop869" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.49497475"
|
||||||
|
inkscape:cx="298.98541"
|
||||||
|
inkscape:cy="561.0427"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1012"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="1080"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
d="m 108.52826,213.29755 a 56.035402,7.0061195 5.281088 0 0 -22.425508,2.5321 56.035402,7.0061195 5.281088 0 0 -0.233576,0.17697 l -0.206706,-0.0237 c -0.04471,0.11554 -0.07454,0.2314 -0.09612,0.34752 a 56.035402,7.0061195 5.281088 0 0 0.337963,1.58159 c 0.980726,1.70884 3.760629,3.46326 6.583579,5.2188 l -22.744347,15.50009 a 67.064653,11.556784 4.2275244 0 0 -39.967588,5.26867 67.064653,11.556784 4.2275244 0 0 -0.729154,0.57564 67.064653,11.556784 4.2275244 0 0 -2.754353,1.36358 67.064653,11.556784 4.2275244 0 0 38.908736,16.04324 l -32.176847,27.0646 52.228334,-24.74551 a 67.064653,11.556784 4.2275244 0 0 71.411147,-3.8186 67.064653,11.556784 4.2275244 0 0 0.72812,-0.57507 67.064653,11.556784 4.2275244 0 0 2.75539,-1.36415 67.064653,11.556784 4.2275244 0 0 -12.38374,-10.59818 40.033569,5.0733922 5.2502179 0 0 0.0563,-0.0369 40.033569,5.0733922 5.2502179 0 0 0.37672,-0.34325 l 22.45186,-15.30075 c 8.23597,-0.65161 17.65581,-1.47811 22.94433,-3.00957 a 56.035402,7.0061195 5.281088 0 0 2.65514,-1.03772 56.035402,7.0061195 5.281088 0 0 -46.08401,-12.26953 56.035402,7.0061195 5.281088 0 0 -41.6357,-2.54991 z"
|
||||||
|
style="fill:#333333;fill-opacity:0.49421525;stroke:#000000;stroke-width:0.138931px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.265501"
|
||||||
|
id="path839" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient871);fill-opacity:1;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.265501"
|
||||||
|
d="M 70.603317,174.30832 33.024148,288.94657 94.566672,183.19473 Z"
|
||||||
|
id="path865"
|
||||||
|
sodipodi:nodetypes="cccc" />
|
||||||
|
<ellipse
|
||||||
|
cx="144.42586"
|
||||||
|
cy="113.06232"
|
||||||
|
rx="70.318817"
|
||||||
|
ry="39.974442"
|
||||||
|
id="ellipse26"
|
||||||
|
style="fill:#d45500;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264583"
|
||||||
|
transform="rotate(22.027833)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ff6600;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264583"
|
||||||
|
id="ellipse30"
|
||||||
|
ry="39.974442"
|
||||||
|
rx="70.318817"
|
||||||
|
cy="105.23625"
|
||||||
|
cx="145.017"
|
||||||
|
transform="rotate(22.027833)" />
|
||||||
|
<path
|
||||||
|
id="rect28"
|
||||||
|
style="fill:#d45500;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264583"
|
||||||
|
d="m 85.662408,24.322061 c -0.890996,8.350369 2.928035,17.133472 6.825491,25.923906 l -23.333902,57.672763 -0.730686,1.80598 0.248621,0.10059 a 42.43035,17.360788 22.027833 0 0 33.303948,30.10067 42.43035,17.360788 22.027833 0 0 44.86507,1.52585 l 0.13892,0.0562 0.24519,-0.60599 a 42.43035,17.360788 22.027833 0 0 0.59472,-1.15581 42.43035,17.360788 22.027833 0 0 0.37668,-1.24514 l 22.45185,-55.492655 c 9.28986,-2.66566 20.09069,-6.13552 24.76397,-13.17485 z" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ff6600;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264583"
|
||||||
|
id="path24"
|
||||||
|
ry="23.966745"
|
||||||
|
rx="59.409279"
|
||||||
|
cy="-10.262156"
|
||||||
|
cx="148.14029"
|
||||||
|
transform="rotate(22.027833)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.0 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
v3.7.4: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Sharing/export format configurable
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Wheel diameter not stored correctly (for speed sensor)
|
||||||
|
- Help: links are clickable
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Split TrackDetailActivity
|
||||||
|
- StatsFragement successor uses ConstraintLayout
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
v3.7.5: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Added aggregated statistics summary (from main the screen's menu)
|
||||||
|
- Dashboard API: pass "show on lock screen"- and "keep screen on"-setting
|
||||||
|
- Updated translations
|
||||||
|
- Import: be lenient with ISO8601 date format
|
||||||
|
- Show track on map: file format can be selected and opening dashboard works on Android R (API 30+)
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- App icon now correctly implemented
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
v3.7.6: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Landscape mode
|
||||||
|
- Track deletion UI is now only a spinner
|
||||||
|
- Speed is exported and imported (GPX/KML/KMZ)
|
||||||
|
- Default export format is KMZ incl. all data and pictures
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Replaced AsyncTasks with Threads
|
||||||
|
- Synchronization: UUID is generated per track (not yet exported)
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
v3.8.0: OpenTracks
|
||||||
|
|
||||||
|
Breaking change:
|
||||||
|
- GPX import/export speed, cadence, and heartrate via TrackPointExtension/v2
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Dashboard API: provide access to markers (incl. callback to show in OpenTracks)
|
||||||
|
- New marker icon (orange push pin, SVG)
|
||||||
|
- Files to import can be selected via file manager
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
- Aggregated stats UI respects preferred rate
|
||||||
|
- Editing a marker failed on orientation change
|
||||||
|
|
||||||
|
Developer:
|
||||||
|
- Refactored TrackRecordingService
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
v3.8.1: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- While recording: add option for fullscreen
|
||||||
|
- Dashboard is started on the same task
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
- Intent filters for importing files were far too optimistic
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
v3.9.0: OpenTracks
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Export tracks with their UUID
|
||||||
|
- Prevent import of already existing tracks by UUID (configurable; default yes)
|
||||||
|
- Pause/stop button now require long press
|
||||||
|
- GPS pre-start shows status of fix
|
||||||
|
- Added new activity icons
|
||||||
|
- Speed sensor: wheelsize now configurable in millimeter
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
- Fixed some rare crashes (NPE)
|
||||||
|
- Pace formatting corrected
|
||||||
|
- App icon in launcher repositioned
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
v3.9.1: OpenTracks
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
- GPS pre-start shows status of fix
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
v3.9.2: OpenTracks
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
- Fixed force close on API<25 (due to an animation)
|
||||||
|
- Reset recording state (on app startup) if crashed while recording
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
v3.9.3: OpenTracks
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
- Fixed export all tracks bug.
|
||||||
@@ -67,7 +67,7 @@ public class DescriptionGeneratorTest {
|
|||||||
track.setTrackStatistics(stats);
|
track.setTrackStatistics(stats);
|
||||||
track.setCategory("hiking");
|
track.setCategory("hiking");
|
||||||
String expected = //"Created by"
|
String expected = //"Created by"
|
||||||
"<a href='https://github.com/OpenTracksApp/OpenTracks'>OpenTracks</a><p>"
|
"<a href='https://github.com/OpenTracksApp/OpenTracks'>OpenTracks (Debug)</a><p>"
|
||||||
+ "Name: -<br>"
|
+ "Name: -<br>"
|
||||||
+ "Activity type: hiking<br>"
|
+ "Activity type: hiking<br>"
|
||||||
+ "Description: -<br>"
|
+ "Description: -<br>"
|
||||||
@@ -103,7 +103,7 @@ public class DescriptionGeneratorTest {
|
|||||||
track.setTrackStatistics(stats);
|
track.setTrackStatistics(stats);
|
||||||
track.setCategory("hiking");
|
track.setCategory("hiking");
|
||||||
String expected = //"Created by"
|
String expected = //"Created by"
|
||||||
"<a href='https://github.com/OpenTracksApp/OpenTracks'>OpenTracks</a><p>"
|
"<a href='https://github.com/OpenTracksApp/OpenTracks'>OpenTracks (Debug)</a><p>"
|
||||||
+ "Name: -<br>"
|
+ "Name: -<br>"
|
||||||
+ "Activity type: hiking<br>"
|
+ "Activity type: hiking<br>"
|
||||||
+ "Description: -<br>"
|
+ "Description: -<br>"
|
||||||
|
|||||||
@@ -17,18 +17,17 @@
|
|||||||
package de.dennisguse.opentracks.content;
|
package de.dennisguse.opentracks.content;
|
||||||
|
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.Context;
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.rule.provider.ProviderTestRule;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -39,6 +38,8 @@ import de.dennisguse.opentracks.content.SearchEngine.SearchQuery;
|
|||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.Waypoint;
|
import de.dennisguse.opentracks.content.data.Waypoint;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
|
import de.dennisguse.opentracks.content.provider.CustomContentProvider;
|
||||||
|
import de.dennisguse.opentracks.content.provider.CustomSQLiteOpenHelper;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,29 +49,32 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
|||||||
*
|
*
|
||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class SearchEngineTest {
|
public class SearchEngineTest {
|
||||||
|
|
||||||
|
private static final String TAG = SearchEngineTest.class.getSimpleName();
|
||||||
|
|
||||||
private static final Location HERE = new Location("gps");
|
private static final Location HERE = new Location("gps");
|
||||||
private static final long NOW = SearchEngine.OLDEST_ALLOWED_TIMESTAMP + 1000; // After OLDEST_ALLOWED_TIMESTAMP
|
private static final long NOW = SearchEngine.OLDEST_ALLOWED_TIMESTAMP + 1000;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ProviderTestRule sqliteContentProviderRule = new ProviderTestRule.Builder(CustomContentProvider.class, ContentProviderUtils.AUTHORITY_PACKAGE).setPrefix(TAG).build();
|
||||||
|
|
||||||
private ContentProviderUtils providerUtils;
|
private ContentProviderUtils providerUtils;
|
||||||
private SearchEngine engine;
|
private SearchEngine engine;
|
||||||
|
|
||||||
private final Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
providerUtils = new ContentProviderUtils(context);
|
providerUtils = new ContentProviderUtils(sqliteContentProviderRule.getResolver());
|
||||||
|
|
||||||
engine = new SearchEngine(providerUtils);
|
engine = new SearchEngine(providerUtils);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
providerUtils.deleteAllTracks(context);
|
InstrumentationRegistry.getInstrumentation().getTargetContext().deleteDatabase(TAG + CustomSQLiteOpenHelper.DATABASE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertTrack(String title, String description, String category, long hoursAgo) {
|
private Track.Id insertTrack(String title, String description, String category, long hoursAgo) {
|
||||||
Track track = new Track();
|
Track track = new Track();
|
||||||
track.setName(title);
|
track.setName(title);
|
||||||
track.setDescription(description);
|
track.setDescription(description);
|
||||||
@@ -84,18 +88,18 @@ public class SearchEngineTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Uri uri = providerUtils.insertTrack(track);
|
Uri uri = providerUtils.insertTrack(track);
|
||||||
return ContentUris.parseId(uri);
|
return new Track.Id(ContentUris.parseId(uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertTrack(String title, String description, String category) {
|
private Track.Id insertTrack(String title, String description, String category) {
|
||||||
return insertTrack(title, description, category, -1);
|
return insertTrack(title, description, category, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertTrack(String title, long hoursAgo) {
|
private Track.Id insertTrack(String title, long hoursAgo) {
|
||||||
return insertTrack(title, "", "", hoursAgo);
|
return insertTrack(title, "", "", hoursAgo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertWaypoint(String title, String description, String category, double distance, long hoursAgo, long trackId) {
|
private Waypoint.Id insertWaypoint(String title, String description, String category, double distance, long hoursAgo, Track.Id trackId) {
|
||||||
Location location = new Location(HERE);
|
Location location = new Location(HERE);
|
||||||
location.setLatitude(location.getLatitude() + distance);
|
location.setLatitude(location.getLatitude() + distance);
|
||||||
location.setLongitude(location.getLongitude() + distance);
|
location.setLongitude(location.getLongitude() + distance);
|
||||||
@@ -109,22 +113,22 @@ public class SearchEngineTest {
|
|||||||
waypoint.setTrackId(trackId);
|
waypoint.setTrackId(trackId);
|
||||||
|
|
||||||
Uri uri = providerUtils.insertWaypoint(waypoint);
|
Uri uri = providerUtils.insertWaypoint(waypoint);
|
||||||
return ContentUris.parseId(uri);
|
return new Waypoint.Id(ContentUris.parseId(uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertWaypoint(String title, String description, String category) {
|
private Waypoint.Id insertWaypoint(String title, String description, String category) {
|
||||||
return insertWaypoint(title, description, category, 0.0, -1, -1);
|
return insertWaypoint(title, description, category, 0.0, -1, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertWaypoint(String title, double distance) {
|
private Waypoint.Id insertWaypoint(String title, double distance) {
|
||||||
return insertWaypoint(title, "", "", distance, -1, -1);
|
return insertWaypoint(title, "", "", distance, -1, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertWaypoint(String title, long hoursAgo) {
|
private Waypoint.Id insertWaypoint(String title, long hoursAgo) {
|
||||||
return insertWaypoint(title, "", "", 0.0, hoursAgo, -1);
|
return insertWaypoint(title, "", "", 0.0, hoursAgo, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertWaypoint(String title, long hoursAgo, long trackId) {
|
private Waypoint.Id insertWaypoint(String title, long hoursAgo, Track.Id trackId) {
|
||||||
return insertWaypoint(title, "", "", 0.0, hoursAgo, trackId);
|
return insertWaypoint(title, "", "", 0.0, hoursAgo, trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,14 +143,14 @@ public class SearchEngineTest {
|
|||||||
// - one which will match in title and description
|
// - one which will match in title and description
|
||||||
// - one which will match in all fields
|
// - one which will match in all fields
|
||||||
insertTrack("bb", "cc", "dd");
|
insertTrack("bb", "cc", "dd");
|
||||||
long descriptionMatchId = insertTrack("bb", "aa", "cc");
|
Track.Id descriptionMatchId = insertTrack("bb", "aa", "cc");
|
||||||
long categoryMatchId = insertTrack("bb", "cc", "aa");
|
Track.Id categoryMatchId = insertTrack("bb", "cc", "aa");
|
||||||
long titleMatchId = insertTrack("aa", "bb", "cc");
|
Track.Id titleMatchId = insertTrack("aa", "bb", "cc");
|
||||||
long titleCategoryMatchId = insertTrack("aa", "bb", "ca");
|
Track.Id titleCategoryMatchId = insertTrack("aa", "bb", "ca");
|
||||||
long titleDescriptionMatchId = insertTrack("aa", "ba", "cc");
|
Track.Id titleDescriptionMatchId = insertTrack("aa", "ba", "cc");
|
||||||
long allMatchId = insertTrack("aa", "ba", "ca");
|
Track.Id allMatchId = insertTrack("aa", "ba", "ca");
|
||||||
|
|
||||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
SearchQuery query = new SearchQuery("a", null, null, NOW);
|
||||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||||
|
|
||||||
// Title > Description > Category.
|
// Title > Description > Category.
|
||||||
@@ -164,14 +168,14 @@ public class SearchEngineTest {
|
|||||||
// - one which will match in title and description
|
// - one which will match in title and description
|
||||||
// - one which will match in all fields
|
// - one which will match in all fields
|
||||||
insertWaypoint("bb", "cc", "dd");
|
insertWaypoint("bb", "cc", "dd");
|
||||||
long descriptionMatchId = insertWaypoint("bb", "aa", "cc");
|
Waypoint.Id descriptionMatchId = insertWaypoint("bb", "aa", "cc");
|
||||||
long categoryMatchId = insertWaypoint("bb", "cc", "aa");
|
Waypoint.Id categoryMatchId = insertWaypoint("bb", "cc", "aa");
|
||||||
long titleMatchId = insertWaypoint("aa", "bb", "cc");
|
Waypoint.Id titleMatchId = insertWaypoint("aa", "bb", "cc");
|
||||||
long titleCategoryMatchId = insertWaypoint("aa", "bb", "ca");
|
Waypoint.Id titleCategoryMatchId = insertWaypoint("aa", "bb", "ca");
|
||||||
long titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc");
|
Waypoint.Id titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc");
|
||||||
long allMatchId = insertWaypoint("aa", "ba", "ca");
|
Waypoint.Id allMatchId = insertWaypoint("aa", "ba", "ca");
|
||||||
|
|
||||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
SearchQuery query = new SearchQuery("a", null, null, NOW);
|
||||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||||
|
|
||||||
// Title > Description > Category.
|
// Title > Description > Category.
|
||||||
@@ -186,13 +190,13 @@ public class SearchEngineTest {
|
|||||||
// - one waypoint which will match by title
|
// - one waypoint which will match by title
|
||||||
// - one track which won't match
|
// - one track which won't match
|
||||||
// - one track which will match by title
|
// - one track which will match by title
|
||||||
long descriptionWaypointId = insertWaypoint("bb", "aa", "cc");
|
Waypoint.Id descriptionWaypointId = insertWaypoint("bb", "aa", "cc");
|
||||||
insertWaypoint("bb", "cc", "dd");
|
insertWaypoint("bb", "cc", "dd");
|
||||||
long titleWaypointId = insertWaypoint("aa", "bb", "cc");
|
Waypoint.Id titleWaypointId = insertWaypoint("aa", "bb", "cc");
|
||||||
insertTrack("bb", "cc", "dd");
|
insertTrack("bb", "cc", "dd");
|
||||||
long trackId = insertTrack("aa", "bb", "cc");
|
Track.Id trackId = insertTrack("aa", "bb", "cc");
|
||||||
|
|
||||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
SearchQuery query = new SearchQuery("a", null, null, NOW);
|
||||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||||
|
|
||||||
// Title > Description > Category.
|
// Title > Description > Category.
|
||||||
@@ -205,11 +209,11 @@ public class SearchEngineTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSearchWaypointDistance() {
|
public void testSearchWaypointDistance() {
|
||||||
// All results match text, but they're at difference distances from the user.
|
// All results match text, but they're at difference distances from the user.
|
||||||
long farFarAwayId = insertWaypoint("aa", 0.3);
|
Waypoint.Id farFarAwayId = insertWaypoint("aa", 0.3);
|
||||||
long nearId = insertWaypoint("ab", 0.1);
|
Waypoint.Id nearId = insertWaypoint("ab", 0.1);
|
||||||
long farId = insertWaypoint("ac", 0.2);
|
Waypoint.Id farId = insertWaypoint("ac", 0.2);
|
||||||
|
|
||||||
SearchQuery query = new SearchQuery("a", HERE, -1, NOW);
|
SearchQuery query = new SearchQuery("a", HERE, null, NOW);
|
||||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||||
|
|
||||||
// Distance order.
|
// Distance order.
|
||||||
@@ -218,11 +222,11 @@ public class SearchEngineTest {
|
|||||||
|
|
||||||
public void testSearchTrackRecent() {
|
public void testSearchTrackRecent() {
|
||||||
// All results match text, but they're were recorded at different times.
|
// All results match text, but they're were recorded at different times.
|
||||||
long oldestId = insertTrack("aa", 3);
|
Track.Id oldestId = insertTrack("aa", 3);
|
||||||
long recentId = insertTrack("ab", 1);
|
Track.Id recentId = insertTrack("ab", 1);
|
||||||
long oldId = insertTrack("ac", 2);
|
Track.Id oldId = insertTrack("ac", 2);
|
||||||
|
|
||||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
SearchQuery query = new SearchQuery("a", null, null, NOW);
|
||||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||||
|
|
||||||
// Reverse time order.
|
// Reverse time order.
|
||||||
@@ -232,11 +236,11 @@ public class SearchEngineTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSearchWaypointRecent() {
|
public void testSearchWaypointRecent() {
|
||||||
// All results match text, but they're were recorded at different times.
|
// All results match text, but they're were recorded at different times.
|
||||||
long oldestId = insertWaypoint("aa", 2);
|
Waypoint.Id oldestId = insertWaypoint("aa", 2);
|
||||||
long recentId = insertWaypoint("ab", 0);
|
Waypoint.Id recentId = insertWaypoint("ab", 0);
|
||||||
long oldId = insertWaypoint("ac", 1);
|
Waypoint.Id oldId = insertWaypoint("ac", 1);
|
||||||
|
|
||||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
SearchQuery query = new SearchQuery("a", null, null, NOW);
|
||||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||||
|
|
||||||
// Reverse time order.
|
// Reverse time order.
|
||||||
@@ -246,8 +250,8 @@ public class SearchEngineTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSearchCurrentTrack() {
|
public void testSearchCurrentTrack() {
|
||||||
// All results match text, but one of them is the current track.
|
// All results match text, but one of them is the current track.
|
||||||
long currentId = insertTrack("ab", 1);
|
Track.Id currentId = insertTrack("ab", 1);
|
||||||
long otherId = insertTrack("aa", 1);
|
Track.Id otherId = insertTrack("aa", 1);
|
||||||
|
|
||||||
SearchQuery query = new SearchQuery("a", null, currentId, NOW);
|
SearchQuery query = new SearchQuery("a", null, currentId, NOW);
|
||||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||||
@@ -259,24 +263,29 @@ public class SearchEngineTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSearchCurrentTrackWaypoint() {
|
public void testSearchCurrentTrackWaypoint() {
|
||||||
// All results match text, but one of them is in the current track.
|
// All results match text, but one of them is in the current track.
|
||||||
long otherId = insertWaypoint("aa", 1, 456);
|
Waypoint.Id otherId = insertWaypoint("aa", 1, new Track.Id(456));
|
||||||
long currentId = insertWaypoint("ab", 1, 123);
|
Waypoint.Id currentId = insertWaypoint("ab", 1, new Track.Id(123));
|
||||||
|
|
||||||
SearchQuery query = new SearchQuery("a", null, 123, NOW);
|
SearchQuery query = new SearchQuery("a", null, new Track.Id(123), NOW);
|
||||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||||
|
|
||||||
// Waypoint in current track should be promoted.
|
// Waypoint in current track should be promoted.
|
||||||
assertWaypointResults(results, currentId, otherId);
|
assertWaypointResults(results, currentId, otherId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertTrackResult(long trackId, ScoredResult result) {
|
private void assertTrackResult(Track.Id trackId, ScoredResult result) {
|
||||||
Assert.assertNotNull("Not a track", result.track);
|
Assert.assertNotNull("Not a track", result.track);
|
||||||
Assert.assertNull("Ambiguous result", result.waypoint);
|
Assert.assertNull("Ambiguous result", result.waypoint);
|
||||||
Assert.assertEquals(trackId, result.track.getId());
|
Assert.assertEquals(trackId, result.track.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertTrackResults(List<ScoredResult> results, long... trackIds) {
|
private void assertTrackResults(List<ScoredResult> results, Track.Id... trackIds) {
|
||||||
String errMsg = "Expected IDs=" + Arrays.toString(trackIds) + "; results=" + results;
|
long[] longTrackIds = new long[trackIds.length];
|
||||||
|
for (int i = 0; i < trackIds.length; i++) {
|
||||||
|
longTrackIds[i] = trackIds[i].getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
String errMsg = "Expected IDs=" + Arrays.toString(longTrackIds) + "; results=" + results;
|
||||||
Assert.assertEquals(results.size(), trackIds.length);
|
Assert.assertEquals(results.size(), trackIds.length);
|
||||||
for (int i = 0; i < results.size(); i++) {
|
for (int i = 0; i < results.size(); i++) {
|
||||||
ScoredResult result = results.get(i);
|
ScoredResult result = results.get(i);
|
||||||
@@ -286,14 +295,19 @@ public class SearchEngineTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertWaypointResult(long waypointId, ScoredResult result) {
|
private void assertWaypointResult(Waypoint.Id waypointId, ScoredResult result) {
|
||||||
Assert.assertNotNull("Not a waypoint", result.waypoint);
|
Assert.assertNotNull("Not a waypoint", result.waypoint);
|
||||||
Assert.assertNull("Ambiguous result", result.track);
|
Assert.assertNull("Ambiguous result", result.track);
|
||||||
Assert.assertEquals(waypointId, result.waypoint.getId());
|
Assert.assertEquals(waypointId, result.waypoint.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertWaypointResults(List<ScoredResult> results, long... waypointIds) {
|
private void assertWaypointResults(List<ScoredResult> results, Waypoint.Id... waypointIds) {
|
||||||
String errMsg = "Expected IDs=" + Arrays.toString(waypointIds) + "; results=" + results;
|
long[] longWaypointIds = new long[waypointIds.length];
|
||||||
|
for (int i = 0; i < waypointIds.length; i++) {
|
||||||
|
longWaypointIds[i] = waypointIds[i].getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
String errMsg = "Expected IDs=" + Arrays.toString(longWaypointIds) + "; results=" + results;
|
||||||
Assert.assertEquals(results.size(), waypointIds.length);
|
Assert.assertEquals(results.size(), waypointIds.length);
|
||||||
for (int i = 0; i < results.size(); i++) {
|
for (int i = 0; i < results.size(); i++) {
|
||||||
ScoredResult result = results.get(i);
|
ScoredResult result = results.get(i);
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ public class TestDataUtil {
|
|||||||
/**
|
/**
|
||||||
* Create a track without any trackPoints.
|
* Create a track without any trackPoints.
|
||||||
*/
|
*/
|
||||||
public static Track createTrack(long trackId) {
|
public static Track createTrack(Track.Id trackId) {
|
||||||
Track track = new Track();
|
Track track = new Track();
|
||||||
track.setId(trackId);
|
track.setId(trackId);
|
||||||
track.setName("Test: " + trackId);
|
track.setName("Test: " + trackId.getId());
|
||||||
|
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
@@ -34,18 +34,18 @@ public class TestDataUtil {
|
|||||||
* @param trackId the trackId of the track
|
* @param trackId the trackId of the track
|
||||||
* @param numPoints the trackPoints number in the track
|
* @param numPoints the trackPoints number in the track
|
||||||
*/
|
*/
|
||||||
public static Pair<Track, TrackPoint[]> createTrack(long trackId, int numPoints) {
|
public static Pair<Track, TrackPoint[]> createTrack(Track.Id trackId, int numPoints) {
|
||||||
Track track = createTrack(trackId);
|
Track track = createTrack(trackId);
|
||||||
|
|
||||||
TrackPoint[] trackPoints = new TrackPoint[numPoints];
|
TrackPoint[] trackPoints = new TrackPoint[numPoints];
|
||||||
for (int i = 0; i < numPoints; i++) {
|
for (int i = 0; i < numPoints; i++) {
|
||||||
trackPoints[i] = (createTrackPoint(i));
|
trackPoints[i] = createTrackPoint(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Pair<>(track, trackPoints);
|
return new Pair<>(track, trackPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Track createTrackAndInsert(ContentProviderUtils contentProviderUtils, long trackId, int numPoints) {
|
public static Track createTrackAndInsert(ContentProviderUtils contentProviderUtils, Track.Id trackId, int numPoints) {
|
||||||
Pair<Track, TrackPoint[]> pair = createTrack(trackId, numPoints);
|
Pair<Track, TrackPoint[]> pair = createTrack(trackId, numPoints);
|
||||||
|
|
||||||
insertTrackWithLocations(contentProviderUtils, pair.first, pair.second);
|
insertTrackWithLocations(contentProviderUtils, pair.first, pair.second);
|
||||||
@@ -56,17 +56,22 @@ public class TestDataUtil {
|
|||||||
/**
|
/**
|
||||||
* Creates a location.
|
* Creates a location.
|
||||||
*
|
*
|
||||||
* @param i the index to set the value of location.
|
* @param i the index for the TrackPoint.
|
||||||
* @return created location
|
|
||||||
*/
|
*/
|
||||||
public static TrackPoint createTrackPoint(int i) {
|
public static TrackPoint createTrackPoint(int i) {
|
||||||
Location location = new Location("test");
|
TrackPoint trackPoint = new TrackPoint();
|
||||||
location.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0);
|
trackPoint.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0);
|
||||||
location.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
|
trackPoint.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
|
||||||
location.setAccuracy((float) i / 100.0f);
|
trackPoint.setAccuracy((float) i / 100.0f);
|
||||||
location.setAltitude(i * ALTITUDE_INTERVAL);
|
trackPoint.setAltitude(i * ALTITUDE_INTERVAL);
|
||||||
location.setTime(i + 1);
|
trackPoint.setTime(i + 1);
|
||||||
return new TrackPoint(location);
|
trackPoint.setSpeed(5f + (i / 10));
|
||||||
|
|
||||||
|
trackPoint.setHeartRate_bpm(100f + i);
|
||||||
|
trackPoint.setCyclingCadence_rpm(200f + i);
|
||||||
|
trackPoint.setCyclingCadence_rpm(300f + i);
|
||||||
|
trackPoint.setPower(400f + i);
|
||||||
|
return trackPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,12 +93,11 @@ public class TestDataUtil {
|
|||||||
* @param location The location.
|
* @param location The location.
|
||||||
* @return the Waypoint created.
|
* @return the Waypoint created.
|
||||||
*/
|
*/
|
||||||
public static Waypoint createWaypointWithPhoto(Context context, long trackId, Location location) throws IOException {
|
public static Waypoint createWaypointWithPhoto(Context context, Track.Id trackId, Location location) throws IOException {
|
||||||
String photoUrl = "";
|
|
||||||
File dstFile = new File(FileUtils.getImageUrl(context, trackId));
|
File dstFile = new File(FileUtils.getImageUrl(context, trackId));
|
||||||
dstFile.createNewFile();
|
dstFile.createNewFile();
|
||||||
Uri photoUri = FileUtils.getUriForFile(context, dstFile);
|
Uri photoUri = FileUtils.getUriForFile(context, dstFile);
|
||||||
photoUrl = photoUri.toString();
|
String photoUrl = photoUri.toString();
|
||||||
|
|
||||||
return new Waypoint("Waypoint name", "Waypoint description", "Waypoint category", "", trackId, 0.0, 0, location, photoUrl);
|
return new Waypoint("Waypoint name", "Waypoint description", "Waypoint category", "", trackId, 0.0, 0, location, photoUrl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import android.net.Uri;
|
|||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -30,6 +29,9 @@ import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
|||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link CustomContentProvider}.
|
* Tests {@link CustomContentProvider}.
|
||||||
*
|
*
|
||||||
@@ -51,7 +53,7 @@ public class CustomContentProviderTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testOnCreate() {
|
public void testOnCreate() {
|
||||||
Assert.assertTrue(customContentProvider.onCreate(context));
|
assertTrue(customContentProvider.onCreate(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,13 +61,13 @@ public class CustomContentProviderTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetType() {
|
public void testGetType() {
|
||||||
Assert.assertEquals(TracksColumns.CONTENT_TYPE, customContentProvider.getType(TracksColumns.CONTENT_URI));
|
assertEquals(TracksColumns.CONTENT_TYPE, customContentProvider.getType(TracksColumns.CONTENT_URI));
|
||||||
Assert.assertEquals(TracksColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TracksColumns.CONTENT_URI.buildUpon(), 1).build()));
|
assertEquals(TracksColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TracksColumns.CONTENT_URI.buildUpon(), 1).build()));
|
||||||
|
|
||||||
Assert.assertEquals(TrackPointsColumns.CONTENT_TYPE, customContentProvider.getType(TrackPointsColumns.CONTENT_URI_BY_ID));
|
assertEquals(TrackPointsColumns.CONTENT_TYPE, customContentProvider.getType(TrackPointsColumns.CONTENT_URI_BY_ID));
|
||||||
Assert.assertEquals(TrackPointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TrackPointsColumns.CONTENT_URI_BY_TRACKID.buildUpon(), 1).build()));
|
assertEquals(TrackPointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TrackPointsColumns.CONTENT_URI_BY_TRACKID.buildUpon(), 1).build()));
|
||||||
|
|
||||||
Assert.assertEquals(WaypointsColumns.CONTENT_TYPE, customContentProvider.getType(WaypointsColumns.CONTENT_URI));
|
assertEquals(WaypointsColumns.CONTENT_TYPE, customContentProvider.getType(WaypointsColumns.CONTENT_URI));
|
||||||
Assert.assertEquals(WaypointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), 1).build()));
|
assertEquals(WaypointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), 1).build()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,7 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
@@ -47,6 +48,7 @@ import de.dennisguse.opentracks.content.data.Waypoint;
|
|||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.util.FileUtils;
|
import de.dennisguse.opentracks.util.FileUtils;
|
||||||
|
import de.dennisguse.opentracks.util.UUIDUtils;
|
||||||
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@@ -81,39 +83,39 @@ public class CustomContentProviderUtilsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocationIterator_noPoints() {
|
public void testLocationIterator_noPoints() {
|
||||||
testIterator(1, 0, 1, false);
|
testIterator(new Track.Id(1), 0, 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocationIterator_noBatchAscending() {
|
public void testLocationIterator_noBatchAscending() {
|
||||||
testIterator(1, 50, 100, false);
|
testIterator(new Track.Id(1), 50, 100, false);
|
||||||
testIterator(2, 50, 50, false);
|
testIterator(new Track.Id(2), 50, 50, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocationIterator_noBatchDescending() {
|
public void testLocationIterator_noBatchDescending() {
|
||||||
testIterator(1, 50, 100, true);
|
testIterator(new Track.Id(1), 50, 100, true);
|
||||||
testIterator(2, 50, 50, true);
|
testIterator(new Track.Id(2), 50, 50, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocationIterator_batchAscending() {
|
public void testLocationIterator_batchAscending() {
|
||||||
testIterator(1, 50, 11, false);
|
testIterator(new Track.Id(1), 50, 11, false);
|
||||||
testIterator(2, 50, 25, false);
|
testIterator(new Track.Id(2), 50, 25, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocationIterator_batchDescending() {
|
public void testLocationIterator_batchDescending() {
|
||||||
testIterator(1, 50, 11, true);
|
testIterator(new Track.Id(1), 50, 11, true);
|
||||||
testIterator(2, 50, 25, true);
|
testIterator(new Track.Id(2), 50, 25, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocationIterator_largeTrack() {
|
public void testLocationIterator_largeTrack() {
|
||||||
testIterator(1, 20000, 2000, false);
|
testIterator(new Track.Id(1), 20000, 2000, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testIterator(long trackId, int numPoints, int batchSize, boolean descending) {
|
private void testIterator(Track.Id trackId, int numPoints, int batchSize, boolean descending) {
|
||||||
long lastPointId = initializeTrack(trackId, numPoints);
|
long lastPointId = initializeTrack(trackId, numPoints);
|
||||||
contentProviderUtils.setDefaultCursorBatchSize(batchSize);
|
contentProviderUtils.setDefaultCursorBatchSize(batchSize);
|
||||||
List<TrackPoint> locations = new ArrayList<>(numPoints);
|
List<TrackPoint> locations = new ArrayList<>(numPoints);
|
||||||
@@ -130,10 +132,10 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long initializeTrack(long id, int numPoints) {
|
private long initializeTrack(Track.Id id, int numPoints) {
|
||||||
Track track = new Track();
|
Track track = new Track();
|
||||||
track.setId(id);
|
track.setId(id);
|
||||||
track.setName("Test: " + id);
|
track.setName("Test: " + id.getId());
|
||||||
contentProviderUtils.insertTrack(track);
|
contentProviderUtils.insertTrack(track);
|
||||||
track = contentProviderUtils.getTrack(id);
|
track = contentProviderUtils.getTrack(id);
|
||||||
Assert.assertNotNull(track);
|
Assert.assertNotNull(track);
|
||||||
@@ -171,22 +173,26 @@ public class CustomContentProviderUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateTrack() {
|
public void testCreateTrack() {
|
||||||
int startColumnIndex = 1;
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
int columnIndex = startColumnIndex;
|
|
||||||
when(cursorMock.getColumnIndexOrThrow(TracksColumns._ID)).thenReturn(columnIndex++);
|
int columnIndex = 1;
|
||||||
when(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).thenReturn(columnIndex++);
|
|
||||||
columnIndex = startColumnIndex;
|
|
||||||
// Id
|
// Id
|
||||||
when(cursorMock.isNull(columnIndex++)).thenReturn(false);
|
when(cursorMock.getColumnIndexOrThrow(TracksColumns._ID)).thenReturn(columnIndex);
|
||||||
|
when(cursorMock.isNull(columnIndex)).thenReturn(false);
|
||||||
|
when(cursorMock.getLong(columnIndex)).thenReturn(trackId.getId());
|
||||||
|
|
||||||
|
//Uuid
|
||||||
|
columnIndex++;
|
||||||
|
when(cursorMock.getColumnIndexOrThrow(TracksColumns.UUID)).thenReturn(columnIndex);
|
||||||
|
when(cursorMock.isNull(columnIndex)).thenReturn(false);
|
||||||
|
when(cursorMock.getBlob(columnIndex)).thenReturn(UUIDUtils.toBytes(UUID.randomUUID()));
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
when(cursorMock.isNull(columnIndex++)).thenReturn(false);
|
columnIndex++;
|
||||||
long trackId = System.currentTimeMillis();
|
String name = NAME_PREFIX + trackId.getId();
|
||||||
columnIndex = startColumnIndex;
|
when(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).thenReturn(columnIndex);
|
||||||
// Id
|
when(cursorMock.isNull(columnIndex)).thenReturn(false);
|
||||||
when(cursorMock.getLong(columnIndex++)).thenReturn(trackId);
|
when(cursorMock.getString(columnIndex)).thenReturn(name);
|
||||||
// Name
|
|
||||||
String name = NAME_PREFIX + trackId;
|
|
||||||
when(cursorMock.getString(columnIndex++)).thenReturn(name);
|
|
||||||
|
|
||||||
Track track = contentProviderUtils.createTrack(cursorMock);
|
Track track = contentProviderUtils.createTrack(cursorMock);
|
||||||
Assert.assertEquals(trackId, track.getId());
|
Assert.assertEquals(trackId, track.getId());
|
||||||
@@ -199,8 +205,8 @@ public class CustomContentProviderUtilsTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDeleteAllTracks() {
|
public void testDeleteAllTracks() {
|
||||||
// Insert track, points and waypoint at first.
|
// Insert track, points and waypoint at first.
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||||
contentProviderUtils.insertWaypoint(waypoint);
|
contentProviderUtils.insertWaypoint(waypoint);
|
||||||
@@ -229,7 +235,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDeleteAllTracks_withWaypointAndPhoto() throws IOException {
|
public void testDeleteAllTracks_withWaypointAndPhoto() throws IOException {
|
||||||
// Insert track, points and waypoint with photo at first.
|
// Insert track, points and waypoint with photo at first.
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
TrackPoint trackPoint = contentProviderUtils.getLastValidTrackPoint(trackId);
|
TrackPoint trackPoint = contentProviderUtils.getLastValidTrackPoint(trackId);
|
||||||
@@ -262,20 +268,23 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#deleteTrack(Context, long)}.
|
* Tests the method {@link ContentProviderUtils#deleteTrack(Context, Track.Id)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteTrack() {
|
public void testDeleteTrack() {
|
||||||
// Insert three tracks, points of two tracks and way point of one track.
|
// Insert three tracks, points of two tracks and way point of one track.
|
||||||
|
long random = System.currentTimeMillis();
|
||||||
|
Track.Id trackId1 = new Track.Id(random);
|
||||||
|
Track.Id trackId2 = new Track.Id(random + 1);
|
||||||
|
Track.Id trackId3 = new Track.Id(random + 2);
|
||||||
|
|
||||||
long trackId = System.currentTimeMillis();
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId1, 0);
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 0);
|
|
||||||
|
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 1, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId2, 10);
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 2, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId3, 10);
|
||||||
|
|
||||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId + 1));
|
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId2));
|
||||||
waypoint.setTrackId(trackId);
|
waypoint.setTrackId(trackId1);
|
||||||
contentProviderUtils.insertWaypoint(waypoint);
|
contentProviderUtils.insertWaypoint(waypoint);
|
||||||
|
|
||||||
ContentResolver contentResolver = context.getContentResolver();
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
@@ -286,7 +295,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID);
|
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID);
|
||||||
Assert.assertEquals(1, waypointCursor.getCount());
|
Assert.assertEquals(1, waypointCursor.getCount());
|
||||||
// Delete one track.
|
// Delete one track.
|
||||||
contentProviderUtils.deleteTrack(context, trackId);
|
contentProviderUtils.deleteTrack(context, trackId1);
|
||||||
// Check whether all data of a track has been deleted.
|
// Check whether all data of a track has been deleted.
|
||||||
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID);
|
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID);
|
||||||
Assert.assertEquals(2, tracksCursor.getCount());
|
Assert.assertEquals(2, tracksCursor.getCount());
|
||||||
@@ -297,26 +306,30 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#deleteTrack(Context, long)}.
|
* Tests the method {@link ContentProviderUtils#deleteTrack(Context, Track.Id)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteTrack_withWaypointPhoto() throws IOException {
|
public void testDeleteTrack_withWaypointPhoto() throws IOException {
|
||||||
// Insert three tracks.
|
// Insert three tracks.
|
||||||
long trackId = System.currentTimeMillis();
|
long random = System.currentTimeMillis();
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
Track.Id trackId1 = new Track.Id(random);
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 1, 10);
|
Track.Id trackId2 = new Track.Id(random + 1);
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 2, 10);
|
Track.Id trackId3 = new Track.Id(random + 2);
|
||||||
|
|
||||||
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId1, 10);
|
||||||
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId2, 10);
|
||||||
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId3, 10);
|
||||||
|
|
||||||
// Insert a waypoint in tracks trackId and trackId + 1.
|
// Insert a waypoint in tracks trackId and trackId + 1.
|
||||||
TrackPoint trackPoint1 = contentProviderUtils.getLastValidTrackPoint(trackId);
|
TrackPoint trackPoint1 = contentProviderUtils.getLastValidTrackPoint(trackId1);
|
||||||
Waypoint waypoint1 = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint1.getLocation());
|
Waypoint waypoint1 = TestDataUtil.createWaypointWithPhoto(context, trackId1, trackPoint1.getLocation());
|
||||||
contentProviderUtils.insertWaypoint(waypoint1);
|
contentProviderUtils.insertWaypoint(waypoint1);
|
||||||
File dir1 = FileUtils.getPhotoDir(context, trackId);
|
File dir1 = FileUtils.getPhotoDir(context, trackId1);
|
||||||
|
|
||||||
TrackPoint trackPoint2 = contentProviderUtils.getLastValidTrackPoint(trackId + 1);
|
TrackPoint trackPoint2 = contentProviderUtils.getLastValidTrackPoint(trackId2);
|
||||||
Waypoint waypoint2 = TestDataUtil.createWaypointWithPhoto(context, trackId + 1, trackPoint2.getLocation());
|
Waypoint waypoint2 = TestDataUtil.createWaypointWithPhoto(context, trackId2, trackPoint2.getLocation());
|
||||||
contentProviderUtils.insertWaypoint(waypoint2);
|
contentProviderUtils.insertWaypoint(waypoint2);
|
||||||
File dir2 = FileUtils.getPhotoDir(context, trackId + 1);
|
File dir2 = FileUtils.getPhotoDir(context, trackId2);
|
||||||
|
|
||||||
// Check.
|
// Check.
|
||||||
ContentResolver contentResolver = context.getContentResolver();
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
@@ -334,7 +347,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Assert.assertEquals(1, dir2.list().length);
|
Assert.assertEquals(1, dir2.list().length);
|
||||||
Assert.assertTrue(dir2.exists());
|
Assert.assertTrue(dir2.exists());
|
||||||
// Delete one track.
|
// Delete one track.
|
||||||
contentProviderUtils.deleteTrack(context, trackId);
|
contentProviderUtils.deleteTrack(context, trackId1);
|
||||||
// Check whether all data of a track has been deleted.
|
// Check whether all data of a track has been deleted.
|
||||||
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID);
|
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID);
|
||||||
Assert.assertEquals(2, tracksCursor.getCount());
|
Assert.assertEquals(2, tracksCursor.getCount());
|
||||||
@@ -347,17 +360,17 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#getAllTracks()}
|
* Tests the method {@link ContentProviderUtils#getTracks()}
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetAllTracks() {
|
public void testGetAllTracks() {
|
||||||
// given
|
// given
|
||||||
int initialTrackNumber = contentProviderUtils.getAllTracks().size();
|
int initialTrackNumber = contentProviderUtils.getTracks().size();
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
List<Track> allTracks = contentProviderUtils.getAllTracks();
|
List<Track> allTracks = contentProviderUtils.getTracks();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertEquals(initialTrackNumber + 1, allTracks.size());
|
Assert.assertEquals(initialTrackNumber + 1, allTracks.size());
|
||||||
@@ -369,28 +382,45 @@ public class CustomContentProviderUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetLastTrack() {
|
public void testGetLastTrack() {
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
||||||
Assert.assertEquals(trackId, contentProviderUtils.getLastTrack().getId());
|
Assert.assertEquals(trackId, contentProviderUtils.getLastTrack().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#getTrack(long)}
|
* Tests the method {@link ContentProviderUtils#getTrack(Track.Id)}
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetTrack() {
|
public void testGetTrack_by_id() {
|
||||||
long trackId = System.currentTimeMillis();
|
// given
|
||||||
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
||||||
|
|
||||||
|
// when / then
|
||||||
Assert.assertNotNull(contentProviderUtils.getTrack(trackId));
|
Assert.assertNotNull(contentProviderUtils.getTrack(trackId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the method {@link ContentProviderUtils#getTrack(Track.Id)}
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetTrack_by_uuid() {
|
||||||
|
// given
|
||||||
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
|
Track track = TestDataUtil.createTrack(trackId);
|
||||||
|
contentProviderUtils.insertTrack(track);
|
||||||
|
|
||||||
|
// when / then
|
||||||
|
Assert.assertNotNull(contentProviderUtils.getTrack(track.getUuid()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#updateTrack(Track)}
|
* Tests the method {@link ContentProviderUtils#updateTrack(Track)}
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateTrack() {
|
public void testUpdateTrack() {
|
||||||
// given
|
// given
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Track track = TestDataUtil.createTrack(trackId);
|
Track track = TestDataUtil.createTrack(trackId);
|
||||||
String nameOld = "name1";
|
String nameOld = "name1";
|
||||||
String nameNew = "name2";
|
String nameNew = "name2";
|
||||||
@@ -409,7 +439,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateContentValues_waypoint() {
|
public void testCreateContentValues_waypoint() {
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||||
|
|
||||||
// Bottom
|
// Bottom
|
||||||
@@ -435,10 +465,10 @@ public class CustomContentProviderUtilsTest {
|
|||||||
|
|
||||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(contentResolverMock);
|
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(contentResolverMock);
|
||||||
|
|
||||||
long waypointId = System.currentTimeMillis();
|
Waypoint.Id waypointId = new Waypoint.Id(System.currentTimeMillis());
|
||||||
waypoint.setId(waypointId);
|
waypoint.setId(waypointId);
|
||||||
ContentValues contentValues = contentProviderUtils.createContentValues(waypoint);
|
ContentValues contentValues = contentProviderUtils.createContentValues(waypoint);
|
||||||
Assert.assertEquals(waypointId, contentValues.get(WaypointsColumns._ID));
|
Assert.assertEquals(waypointId.getId(), contentValues.get(WaypointsColumns._ID));
|
||||||
Assert.assertEquals((int) (TestDataUtil.INITIAL_LONGITUDE * 1000000), contentValues.get(WaypointsColumns.LONGITUDE));
|
Assert.assertEquals((int) (TestDataUtil.INITIAL_LONGITUDE * 1000000), contentValues.get(WaypointsColumns.LONGITUDE));
|
||||||
Assert.assertEquals(TEST_DESC, contentValues.get(WaypointsColumns.DESCRIPTION));
|
Assert.assertEquals(TEST_DESC, contentValues.get(WaypointsColumns.DESCRIPTION));
|
||||||
}
|
}
|
||||||
@@ -472,19 +502,19 @@ public class CustomContentProviderUtilsTest {
|
|||||||
when(cursorMock.getLong(columnIndex++)).thenReturn(trackId);
|
when(cursorMock.getLong(columnIndex++)).thenReturn(trackId);
|
||||||
|
|
||||||
Waypoint waypoint = contentProviderUtils.createWaypoint(cursorMock);
|
Waypoint waypoint = contentProviderUtils.createWaypoint(cursorMock);
|
||||||
Assert.assertEquals(id, waypoint.getId());
|
Assert.assertEquals(id, waypoint.getId().getId());
|
||||||
Assert.assertEquals(name, waypoint.getName());
|
Assert.assertEquals(name, waypoint.getName());
|
||||||
Assert.assertEquals(trackId, waypoint.getTrackId());
|
Assert.assertEquals(trackId, waypoint.getTrackId().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method
|
* Tests the method
|
||||||
* {@link ContentProviderUtils#deleteWaypoint(Context, long)}
|
* {@link ContentProviderUtils#deleteWaypoint(Context, Waypoint.Id)}
|
||||||
* when there is only one waypoint in the track.
|
* when there is only one waypoint in the track.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteWaypoint_onlyOneWayPoint() {
|
public void testDeleteWaypoint_onlyOneWayPoint() {
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
// Insert at first.
|
// Insert at first.
|
||||||
@@ -497,7 +527,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1);
|
Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1);
|
||||||
|
|
||||||
// Get waypoint id that needs to delete.
|
// Get waypoint id that needs to delete.
|
||||||
long waypoint1Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1));
|
Waypoint.Id waypoint1Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1)));
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
contentProviderUtils.deleteWaypoint(context, waypoint1Id);
|
contentProviderUtils.deleteWaypoint(context, waypoint1Id);
|
||||||
@@ -507,12 +537,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method
|
* Tests the method
|
||||||
* {@link ContentProviderUtils#deleteWaypoint(Context, long)}
|
* {@link ContentProviderUtils#deleteWaypoint(Context, Waypoint.Id)}
|
||||||
* when there is only one waypoint in the track.
|
* when there is only one waypoint in the track.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteWaypoint_onlyOneWayPointWithPhotoUrl() throws IOException {
|
public void testDeleteWaypoint_onlyOneWayPointWithPhotoUrl() throws IOException {
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
// Insert at first.
|
// Insert at first.
|
||||||
@@ -524,7 +554,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1);
|
Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1);
|
||||||
|
|
||||||
// Get waypoint id that needs to delete.
|
// Get waypoint id that needs to delete.
|
||||||
long waypoint1Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1));
|
Waypoint.Id waypoint1Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1)));
|
||||||
|
|
||||||
// Check waypoint has photo and it's in the external storage.
|
// Check waypoint has photo and it's in the external storage.
|
||||||
Assert.assertTrue(waypoint1.hasPhoto());
|
Assert.assertTrue(waypoint1.hasPhoto());
|
||||||
@@ -542,11 +572,11 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#deleteWaypoint(Context, long)} when there is more than one waypoint in the track.
|
* Tests the method {@link ContentProviderUtils#deleteWaypoint(Context, Waypoint.Id)} when there is more than one waypoint in the track.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteWaypoint_hasNextWayPoint() {
|
public void testDeleteWaypoint_hasNextWayPoint() {
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
// Track track = TestDataUtil.createTrackAndInsert(trackId, 10);
|
// Track track = TestDataUtil.createTrackAndInsert(trackId, 10);
|
||||||
@@ -569,12 +599,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Waypoint waypoint1 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
Waypoint waypoint1 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||||
waypoint1.setDescription(MOCK_DESC);
|
waypoint1.setDescription(MOCK_DESC);
|
||||||
waypoint1.setTrackId(trackId);
|
waypoint1.setTrackId(trackId);
|
||||||
long waypoint1Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1));
|
Waypoint.Id waypoint1Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint1)));
|
||||||
|
|
||||||
Waypoint waypoint2 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
Waypoint waypoint2 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||||
waypoint2.setDescription(MOCK_DESC);
|
waypoint2.setDescription(MOCK_DESC);
|
||||||
waypoint2.setTrackId(trackId);
|
waypoint2.setTrackId(trackId);
|
||||||
long waypoint2Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint2));
|
Waypoint.Id waypoint2Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint2)));
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
Assert.assertNotNull(contentProviderUtils.getWaypoint(waypoint1Id));
|
Assert.assertNotNull(contentProviderUtils.getWaypoint(waypoint1Id));
|
||||||
@@ -585,11 +615,11 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#getNextWaypointNumber(long)}.
|
* Tests the method {@link ContentProviderUtils#getNextWaypointNumber(Track.Id)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetNextWaypointNumber() {
|
public void testGetNextWaypointNumber() {
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
Waypoint waypoint1 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
Waypoint waypoint1 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||||
@@ -610,17 +640,17 @@ public class CustomContentProviderUtilsTest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#insertWaypoint(Waypoint)} and
|
* Tests the method {@link ContentProviderUtils#insertWaypoint(Waypoint)} and
|
||||||
* {@link ContentProviderUtils#getWaypoint(long)}.
|
* {@link ContentProviderUtils#getWaypoint(Waypoint.Id)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testInsertAndGetWaypoint() {
|
public void testInsertAndGetWaypoint() {
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||||
waypoint.setDescription(TEST_DESC);
|
waypoint.setDescription(TEST_DESC);
|
||||||
waypoint.setTrackId(trackId);
|
waypoint.setTrackId(trackId);
|
||||||
long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint));
|
Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)));
|
||||||
|
|
||||||
Assert.assertEquals(TEST_DESC, contentProviderUtils.getWaypoint(waypointId).getDescription());
|
Assert.assertEquals(TEST_DESC, contentProviderUtils.getWaypoint(waypointId).getDescription());
|
||||||
}
|
}
|
||||||
@@ -630,14 +660,14 @@ public class CustomContentProviderUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateWaypoint() {
|
public void testUpdateWaypoint() {
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
// Insert at first.
|
// Insert at first.
|
||||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||||
waypoint.setDescription(TEST_DESC);
|
waypoint.setDescription(TEST_DESC);
|
||||||
waypoint.setTrackId(trackId);
|
waypoint.setTrackId(trackId);
|
||||||
long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint));
|
Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)));
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
waypoint = contentProviderUtils.getWaypoint(waypointId);
|
waypoint = contentProviderUtils.getWaypoint(waypointId);
|
||||||
@@ -654,7 +684,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
public void testUpdateWaypoint_withPhoto() throws IOException {
|
public void testUpdateWaypoint_withPhoto() throws IOException {
|
||||||
// tests after update waypoint with photo the photo remains in the storage.
|
// tests after update waypoint with photo the photo remains in the storage.
|
||||||
|
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
// Insert at first.
|
// Insert at first.
|
||||||
@@ -662,9 +692,9 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
||||||
waypoint.setDescription(TEST_DESC);
|
waypoint.setDescription(TEST_DESC);
|
||||||
waypoint.setTrackId(trackId);
|
waypoint.setTrackId(trackId);
|
||||||
long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint));
|
Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)));
|
||||||
|
|
||||||
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId);
|
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.getId());
|
||||||
Assert.assertTrue(dir.exists());
|
Assert.assertTrue(dir.exists());
|
||||||
Assert.assertTrue(dir.isDirectory());
|
Assert.assertTrue(dir.isDirectory());
|
||||||
Assert.assertEquals(1, dir.list().length);
|
Assert.assertEquals(1, dir.list().length);
|
||||||
@@ -690,7 +720,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
public void testUpdateWaypoint_delPhotoAndDir() throws IOException {
|
public void testUpdateWaypoint_delPhotoAndDir() throws IOException {
|
||||||
// tests after update waypoint if user deletes the photo then file photo is deleted from the storage. Also empty directory is deleted.
|
// tests after update waypoint if user deletes the photo then file photo is deleted from the storage. Also empty directory is deleted.
|
||||||
|
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
// Insert at first.
|
// Insert at first.
|
||||||
@@ -698,9 +728,9 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
||||||
waypoint.setDescription(TEST_DESC);
|
waypoint.setDescription(TEST_DESC);
|
||||||
waypoint.setTrackId(trackId);
|
waypoint.setTrackId(trackId);
|
||||||
long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint));
|
Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)));
|
||||||
|
|
||||||
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId);
|
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.getId());
|
||||||
Assert.assertTrue(dir.exists());
|
Assert.assertTrue(dir.exists());
|
||||||
Assert.assertTrue(dir.isDirectory());
|
Assert.assertTrue(dir.isDirectory());
|
||||||
Assert.assertEquals(1, dir.list().length);
|
Assert.assertEquals(1, dir.list().length);
|
||||||
@@ -725,7 +755,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
public void testUpdateWaypoint_delPhotoNotDir() throws IOException {
|
public void testUpdateWaypoint_delPhotoNotDir() throws IOException {
|
||||||
// tests after update waypoint if user deletes the photo then file photo is deleted from the storage. Directory remains if there are more photos from other waypoints.
|
// tests after update waypoint if user deletes the photo then file photo is deleted from the storage. Directory remains if there are more photos from other waypoints.
|
||||||
|
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
// Insert two waypoints with photos.
|
// Insert two waypoints with photos.
|
||||||
@@ -736,10 +766,10 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Waypoint otherWaypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
Waypoint otherWaypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
||||||
otherWaypoint.setDescription(TEST_DESC);
|
otherWaypoint.setDescription(TEST_DESC);
|
||||||
otherWaypoint.setTrackId(trackId);
|
otherWaypoint.setTrackId(trackId);
|
||||||
long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint));
|
Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)));
|
||||||
long otherWaypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(otherWaypoint));
|
contentProviderUtils.insertWaypoint(otherWaypoint);
|
||||||
|
|
||||||
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId);
|
File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.getId());
|
||||||
Assert.assertTrue(dir.exists());
|
Assert.assertTrue(dir.exists());
|
||||||
Assert.assertTrue(dir.isDirectory());
|
Assert.assertTrue(dir.isDirectory());
|
||||||
Assert.assertEquals(2, dir.list().length);
|
Assert.assertEquals(2, dir.list().length);
|
||||||
@@ -757,12 +787,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#bulkInsertTrackPoint(TrackPoint[], long)}.
|
* Tests the method {@link ContentProviderUtils#bulkInsertTrackPoint(TrackPoint[], Track.Id)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testBulkInsertTrackPoint() {
|
public void testBulkInsertTrackPoint() {
|
||||||
// given
|
// given
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||||
TestDataUtil.insertTrackWithLocations(contentProviderUtils, track.first, track.second);
|
TestDataUtil.insertTrackWithLocations(contentProviderUtils, track.first, track.second);
|
||||||
|
|
||||||
@@ -818,12 +848,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method
|
* Tests the method
|
||||||
* {@link ContentProviderUtils#insertTrackPoint(TrackPoint, long)}.
|
* {@link ContentProviderUtils#insertTrackPoint(TrackPoint, Track.Id)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testInsertTrackPoint() {
|
public void testInsertTrackPoint() {
|
||||||
// Insert track, point at first.
|
// Insert track, point at first.
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
contentProviderUtils.insertTrackPoint(TestDataUtil.createTrackPoint(22), trackId);
|
contentProviderUtils.insertTrackPoint(TestDataUtil.createTrackPoint(22), trackId);
|
||||||
@@ -833,7 +863,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testInsertAndLoadTrackPoint() {
|
public void testInsertAndLoadTrackPoint() {
|
||||||
// given
|
// given
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
TrackPoint trackPoint = TestDataUtil.createTrackPoint(5);
|
TrackPoint trackPoint = TestDataUtil.createTrackPoint(5);
|
||||||
@@ -853,12 +883,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#getLastValidTrackPoint(long)}.
|
* Tests the method {@link ContentProviderUtils#getLastValidTrackPoint(Track.Id)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetLastValidTrackPoint() {
|
public void testGetLastValidTrackPoint() {
|
||||||
// Insert track, points at first.
|
// Insert track, points at first.
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||||
|
|
||||||
TrackPoint lastTrackPoint = contentProviderUtils.getLastValidTrackPoint(trackId);
|
TrackPoint lastTrackPoint = contentProviderUtils.getLastValidTrackPoint(trackId);
|
||||||
@@ -866,12 +896,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#getTrackPointCursor(long, long, int, boolean)} in descending.
|
* Tests the method {@link ContentProviderUtils#getTrackPointCursor(Track.Id, long, int, boolean)} in descending.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetTrackPointCursor_desc() {
|
public void testGetTrackPointCursor_desc() {
|
||||||
// given
|
// given
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||||
contentProviderUtils.insertTrack(track.first);
|
contentProviderUtils.insertTrack(track.first);
|
||||||
|
|
||||||
@@ -888,12 +918,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#getTrackPointCursor(long, long, int, boolean)} in ascending.
|
* Tests the method {@link ContentProviderUtils#getTrackPointCursor(Track.Id, long, int, boolean)} in ascending.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetTrackPointCursor_asc() {
|
public void testGetTrackPointCursor_asc() {
|
||||||
// given
|
// given
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||||
contentProviderUtils.insertTrack(track.first);
|
contentProviderUtils.insertTrack(track.first);
|
||||||
|
|
||||||
@@ -910,12 +940,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#getTrackPointLocationIterator(long, long, boolean)} in descending.
|
* Tests the method {@link ContentProviderUtils#getTrackPointLocationIterator(Track.Id, long, boolean)} in descending.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetTrackPointLocationIterator_desc() {
|
public void testGetTrackPointLocationIterator_desc() {
|
||||||
// given
|
// given
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||||
contentProviderUtils.insertTrack(track.first);
|
contentProviderUtils.insertTrack(track.first);
|
||||||
|
|
||||||
@@ -939,12 +969,12 @@ public class CustomContentProviderUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the method {@link ContentProviderUtils#getTrackPointLocationIterator(long, long, boolean)} in ascending.
|
* Tests the method {@link ContentProviderUtils#getTrackPointLocationIterator(Track.Id, long, boolean)} in ascending.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetTrackPointLocationIterator_asc() {
|
public void testGetTrackPointLocationIterator_asc() {
|
||||||
// given
|
// given
|
||||||
long trackId = System.currentTimeMillis();
|
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||||
contentProviderUtils.insertTrack(track.first);
|
contentProviderUtils.insertTrack(track.first);
|
||||||
|
|
||||||
@@ -972,7 +1002,7 @@ public class CustomContentProviderUtilsTest {
|
|||||||
/**
|
/**
|
||||||
* Checks the value of a location.
|
* Checks the value of a location.
|
||||||
*
|
*
|
||||||
* @param i the index of this location which created in the method {@link TestDataUtil#createTrack(long, int)}
|
* @param i the index of this location which created in the method {@link TestDataUtil#createTrack(Track.Id, int)}
|
||||||
* @param location the location to be checked
|
* @param location the location to be checked
|
||||||
*/
|
*/
|
||||||
private void checkLocation(int i, Location location) {
|
private void checkLocation(int i, Location location) {
|
||||||
@@ -982,12 +1012,10 @@ public class CustomContentProviderUtilsTest {
|
|||||||
Assert.assertEquals(i * TestDataUtil.ALTITUDE_INTERVAL, location.getAltitude(), 0.01);
|
Assert.assertEquals(i * TestDataUtil.ALTITUDE_INTERVAL, location.getAltitude(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFormatIdListForUri() {
|
public void testFormatIdListForUri() {
|
||||||
Assert.assertEquals("", ContentProviderUtils.formatIdListForUri(new long[]{}));
|
Assert.assertEquals("", ContentProviderUtils.formatIdListForUri());
|
||||||
Assert.assertEquals("12", ContentProviderUtils.formatIdListForUri(new long[]{12}));
|
Assert.assertEquals("12", ContentProviderUtils.formatIdListForUri(new Track.Id(12)));
|
||||||
Assert.assertEquals("42,43,44", ContentProviderUtils.formatIdListForUri(new long[]{42, 43, 44}));
|
Assert.assertEquals("42,43,44", ContentProviderUtils.formatIdListForUri(new Track.Id(42), new Track.Id(43), new Track.Id(44)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,15 @@ package de.dennisguse.opentracks.content.provider;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteConstraintException;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -20,6 +22,10 @@ import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
|||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class CustomSQLiteOpenHelperTest {
|
public class CustomSQLiteOpenHelperTest {
|
||||||
|
|
||||||
@@ -36,7 +42,8 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
*
|
*
|
||||||
* @return Map(TableName, SQL)
|
* @return Map(TableName, SQL)
|
||||||
*/
|
*/
|
||||||
private static Map<String, String> getTableSQL(SQLiteDatabase db) {
|
@VisibleForTesting
|
||||||
|
public static Map<String, String> getTableSQL(SQLiteDatabase db) {
|
||||||
HashMap<String, String> tableSQL = new HashMap<>();
|
HashMap<String, String> tableSQL = new HashMap<>();
|
||||||
try (Cursor cursor = db.query("sqlite_master", new String[]{"name", "SQL"}, "name IN ('" + TracksColumns.TABLE_NAME + "', '" + TrackPointsColumns.TABLE_NAME + "', '" + WaypointsColumns.TABLE_NAME + "')", null, null, null, "name")) {
|
try (Cursor cursor = db.query("sqlite_master", new String[]{"name", "SQL"}, "name IN ('" + TracksColumns.TABLE_NAME + "', '" + TrackPointsColumns.TABLE_NAME + "', '" + WaypointsColumns.TABLE_NAME + "')", null, null, null, "name")) {
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
@@ -53,6 +60,7 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
*
|
*
|
||||||
* @return Map(tableName, SQL)
|
* @return Map(tableName, SQL)
|
||||||
*/
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
public static Map<String, String> getIndexSQL(SQLiteDatabase db) {
|
public static Map<String, String> getIndexSQL(SQLiteDatabase db) {
|
||||||
HashMap<String, String> indexSQL = new HashMap<>();
|
HashMap<String, String> indexSQL = new HashMap<>();
|
||||||
try (Cursor cursor = db.rawQuery("SELECT tbl_name, SQL FROM sqlite_master WHERE type = 'index'", null)) {
|
try (Cursor cursor = db.rawQuery("SELECT tbl_name, SQL FROM sqlite_master WHERE type = 'index'", null)) {
|
||||||
@@ -85,6 +93,7 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@After
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
context.deleteDatabase(DATABASE_NAME);
|
context.deleteDatabase(DATABASE_NAME);
|
||||||
}
|
}
|
||||||
@@ -92,36 +101,21 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
@Test
|
@Test
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
try (SQLiteDatabase db = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getWritableDatabase()) {
|
try (SQLiteDatabase db = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getWritableDatabase()) {
|
||||||
Assert.assertTrue(hasSqlCreate(db, TracksColumns.CREATE_TABLE));
|
assertTrue(hasSqlCreate(db, TracksColumns.CREATE_TABLE));
|
||||||
|
|
||||||
Assert.assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE));
|
assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE));
|
||||||
Assert.assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE_INDEX));
|
assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE_INDEX));
|
||||||
|
|
||||||
Assert.assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE));
|
assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE));
|
||||||
Assert.assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE_INDEX));
|
assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE_INDEX));
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onUpgrade_FromVersion23() {
|
public void onUpgrade_FromVersion23() {
|
||||||
// Manually create database schema with version 23 (base version)
|
createVersion23();
|
||||||
{
|
|
||||||
SQLiteDatabase dbBase = new SQLiteOpenHelper(context, DATABASE_NAME, null, 23) {
|
|
||||||
@Override
|
|
||||||
public void onCreate(SQLiteDatabase db) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
|
||||||
}
|
|
||||||
}.getWritableDatabase();
|
|
||||||
|
|
||||||
dbBase.execSQL(TRACKS_CREATE_TABLE_V23);
|
|
||||||
dbBase.execSQL(TRACKPOINTS_CREATE_TABLE_V23);
|
|
||||||
dbBase.execSQL(WAYPOINTS_CREATE_TABLE_V23);
|
|
||||||
|
|
||||||
dbBase.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open database with SQL upgrade
|
// Open database with SQL upgrade
|
||||||
Map<String, String> tableByUpgrade;
|
Map<String, String> tableByUpgrade;
|
||||||
@@ -130,10 +124,9 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
tableByUpgrade = getTableSQL(dbUpgraded);
|
tableByUpgrade = getTableSQL(dbUpgraded);
|
||||||
indicesByUpgrade = getIndexSQL(dbUpgraded);
|
indicesByUpgrade = getIndexSQL(dbUpgraded);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open database via
|
|
||||||
context.deleteDatabase(DATABASE_NAME);
|
context.deleteDatabase(DATABASE_NAME);
|
||||||
|
|
||||||
|
// Open database via creation script
|
||||||
Map<String, String> tablesByCreate;
|
Map<String, String> tablesByCreate;
|
||||||
Map<String, String> indicesByCreate;
|
Map<String, String> indicesByCreate;
|
||||||
try (SQLiteDatabase dbCreated = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getReadableDatabase()) {
|
try (SQLiteDatabase dbCreated = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getReadableDatabase()) {
|
||||||
@@ -142,17 +135,18 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// then - verify table structure
|
// then - verify table structure
|
||||||
Assert.assertEquals(3, tableByUpgrade.size());
|
assertEquals(3, tableByUpgrade.size());
|
||||||
Assert.assertEquals(tableByUpgrade.size(), tablesByCreate.size());
|
assertEquals(tableByUpgrade.size(), tablesByCreate.size());
|
||||||
|
|
||||||
Assert.assertEquals(tablesByCreate.get(TracksColumns.TABLE_NAME), tableByUpgrade.get(TracksColumns.TABLE_NAME));
|
assertEquals(tablesByCreate.get(TracksColumns.TABLE_NAME), tableByUpgrade.get(TracksColumns.TABLE_NAME));
|
||||||
Assert.assertEquals(tablesByCreate.get(TrackPointsColumns.TABLE_NAME), tableByUpgrade.get(TrackPointsColumns.TABLE_NAME));
|
assertEquals(tablesByCreate.get(TrackPointsColumns.TABLE_NAME), tableByUpgrade.get(TrackPointsColumns.TABLE_NAME));
|
||||||
Assert.assertEquals(tablesByCreate.get(WaypointsColumns.TABLE_NAME), tableByUpgrade.get(WaypointsColumns.TABLE_NAME));
|
assertEquals(tablesByCreate.get(WaypointsColumns.TABLE_NAME), tableByUpgrade.get(WaypointsColumns.TABLE_NAME));
|
||||||
|
|
||||||
// then - verify custom indices
|
// then - verify custom indices
|
||||||
Assert.assertEquals(2, indicesByCreate.size());
|
assertEquals(3, indicesByCreate.size());
|
||||||
Assert.assertEquals(indicesByUpgrade.get(TrackPointsColumns.TABLE_NAME), indicesByCreate.get(TrackPointsColumns.TABLE_NAME));
|
assertEquals(indicesByUpgrade.get(TracksColumns.TABLE_NAME), indicesByCreate.get(TracksColumns.TABLE_NAME));
|
||||||
Assert.assertEquals(indicesByUpgrade.get(WaypointsColumns.TABLE_NAME), indicesByCreate.get(WaypointsColumns.TABLE_NAME));
|
assertEquals(indicesByUpgrade.get(TrackPointsColumns.TABLE_NAME), indicesByCreate.get(TrackPointsColumns.TABLE_NAME));
|
||||||
|
assertEquals(indicesByUpgrade.get(WaypointsColumns.TABLE_NAME), indicesByCreate.get(WaypointsColumns.TABLE_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -169,11 +163,41 @@ public class CustomSQLiteOpenHelperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// then - verify table structure
|
// then - verify table structure
|
||||||
Assert.assertEquals(TRACKS_CREATE_TABLE_V23, tablesByDowngrade.get("tracks"));
|
assertEquals(TRACKS_CREATE_TABLE_V23, tablesByDowngrade.get("tracks"));
|
||||||
Assert.assertEquals(TRACKPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("trackpoints"));
|
assertEquals(TRACKPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("trackpoints"));
|
||||||
Assert.assertEquals(WAYPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("waypoints"));
|
assertEquals(WAYPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("waypoints"));
|
||||||
|
|
||||||
// then - verify custom indices
|
// then - verify custom indices
|
||||||
Assert.assertEquals(0, indicesByDowngrade.size());
|
assertEquals(0, indicesByDowngrade.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void track_uuid_unique() {
|
||||||
|
try (SQLiteDatabase db = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getWritableDatabase()) {
|
||||||
|
db.execSQL("INSERT INTO tracks (uuid) VALUES (0x00)");
|
||||||
|
db.execSQL("INSERT INTO tracks (uuid) VALUES (0x00)");
|
||||||
|
fail("unique constraint not enforced");
|
||||||
|
} catch (SQLiteConstraintException e) {
|
||||||
|
assertTrue(e.getMessage().contains("UNIQUE constraint failed: tracks.uuid"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createVersion23() {
|
||||||
|
// Manually create database schema with version 23 (base version)
|
||||||
|
SQLiteDatabase dbBase = new SQLiteOpenHelper(context, DATABASE_NAME, null, 23) {
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
}
|
||||||
|
}.getWritableDatabase();
|
||||||
|
|
||||||
|
dbBase.execSQL(TRACKS_CREATE_TABLE_V23);
|
||||||
|
dbBase.execSQL(TRACKPOINTS_CREATE_TABLE_V23);
|
||||||
|
dbBase.execSQL(WAYPOINTS_CREATE_TABLE_V23);
|
||||||
|
|
||||||
|
dbBase.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,21 +6,37 @@ import android.util.Pair;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||||
|
|
||||||
public class ShareContentProviderTest {
|
public class ShareContentProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateandParseURI() {
|
public void testCreateandParseURI_invalid() {
|
||||||
long[] trackIds = {1, 3, 5};
|
Uri uri = Uri.parse("content://de.dennisguse.opentracks.debug.content/tracks/1");
|
||||||
|
|
||||||
|
Assert.assertEquals(0, ShareContentProvider.parseURI(uri).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateandParseURI_valid() {
|
||||||
|
Set<Track.Id> trackIds = new HashSet<>();
|
||||||
|
trackIds.add(new Track.Id(1));
|
||||||
|
trackIds.add(new Track.Id(3));
|
||||||
|
trackIds.add(new Track.Id(5));
|
||||||
|
|
||||||
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(trackIds, "TrackName", TrackFileFormat.KML_ONLY_TRACK);
|
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(trackIds, "TrackName", TrackFileFormat.KML_ONLY_TRACK);
|
||||||
|
|
||||||
Assert.assertArrayEquals(trackIds, ShareContentProvider.parseURI(shareURIandMIME.first));
|
Assert.assertEquals(trackIds, ShareContentProvider.parseURI(shareURIandMIME.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateURIescapeFilename() {
|
public void testCreateURIescapeFilename() {
|
||||||
long[] trackIds = {1};
|
Set<Track.Id> trackIds = new HashSet<>();
|
||||||
|
trackIds.add(new Track.Id(1));
|
||||||
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(trackIds, "../../&1=1", TrackFileFormat.KML_ONLY_TRACK);
|
Pair<Uri, String> shareURIandMIME = ShareContentProvider.createURI(trackIds, "../../&1=1", TrackFileFormat.KML_ONLY_TRACK);
|
||||||
|
|
||||||
Assert.assertEquals(Uri.parse("content://de.dennisguse.opentracks.debug.content/tracks/kml_only_track/1/..%2F..%2F%261%3D1.kml"), shareURIandMIME.first);
|
Assert.assertEquals(Uri.parse("content://de.dennisguse.opentracks.debug.content/tracks/kml_only_track/1/..%2F..%2F%261%3D1.kml"), shareURIandMIME.first);
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ public class ChartFragmentTest {
|
|||||||
trackPoint2.setTime(trackPoint1.getTime() + 222);
|
trackPoint2.setTime(trackPoint1.getTime() + 222);
|
||||||
trackPoint2.setSpeed(130);
|
trackPoint2.setSpeed(130);
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals(130.0 * UnitConversions.MS_TO_KMH, point.getSpeed(), 0.01);
|
Assert.assertEquals(130.0 * UnitConversions.MPS_TO_KMH, point.getSpeed(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -278,7 +278,7 @@ public class ChartFragmentTest {
|
|||||||
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
||||||
trackPoint2.setSpeed(102);
|
trackPoint2.setSpeed(102);
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI, point.getSpeed(), 0.01);
|
Assert.assertEquals(102.0 * UnitConversions.MPS_TO_KMH * UnitConversions.KM_TO_MI, point.getSpeed(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -303,7 +303,7 @@ public class ChartFragmentTest {
|
|||||||
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
||||||
trackPoint2.setSpeed(102);
|
trackPoint2.setSpeed(102);
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals(HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point.getPace(), 0.01);
|
Assert.assertEquals(HOURS_PER_UNIT / (102.0 * UnitConversions.MPS_TO_KMH), point.getPace(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ import org.mockito.ArgumentCaptor;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.SimpleTimeZone;
|
import java.util.SimpleTimeZone;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
|
||||||
import de.dennisguse.opentracks.content.data.Waypoint;
|
|
||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
|
|
||||||
@@ -64,11 +64,11 @@ public abstract class AbstractTestFileTrackImporter {
|
|||||||
|
|
||||||
static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US);
|
static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US);
|
||||||
static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
|
static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
|
||||||
static final long TRACK_ID_0 = 1;
|
|
||||||
static final long TRACK_POINT_ID_0 = 1;
|
static final long TRACK_POINT_ID_0 = 1;
|
||||||
static final long TRACK_POINT_ID_1 = 2;
|
static final long TRACK_POINT_ID_1 = 2;
|
||||||
static final long TRACK_POINT_ID_3 = 4;
|
static final long TRACK_POINT_ID_3 = 4;
|
||||||
static final Uri TRACK_ID_0_URI = ContentUris.appendId(TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_0).build();
|
|
||||||
private static final long WAYPOINT_ID_0 = 1;
|
private static final long WAYPOINT_ID_0 = 1;
|
||||||
private static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build();
|
private static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build();
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ public abstract class AbstractTestFileTrackImporter {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
// We can't omit the timezones in the test, otherwise it'll use the local timezone and fail depending on where the test runner is.
|
// We can't omit the timezones in the test, otherwise it'll use the local timezone and fail depending on where the test runner is.
|
||||||
SimpleTimeZone utc = new SimpleTimeZone(0, "UTC");
|
TimeZone utc = SimpleTimeZone.getTimeZone(ZoneOffset.UTC);
|
||||||
DATE_FORMAT_0.setTimeZone(utc);
|
DATE_FORMAT_0.setTimeZone(utc);
|
||||||
DATE_FORMAT_1.setTimeZone(utc);
|
DATE_FORMAT_1.setTimeZone(utc);
|
||||||
}
|
}
|
||||||
@@ -96,11 +96,11 @@ public abstract class AbstractTestFileTrackImporter {
|
|||||||
/**
|
/**
|
||||||
* Expects the first track point to be added.
|
* Expects the first track point to be added.
|
||||||
*
|
*
|
||||||
* @param trackPoint the trackPoint
|
* @param trackPoint the trackPoint
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
* @param trackPointId the track point id
|
* @param trackPointId the track point id
|
||||||
*/
|
*/
|
||||||
protected void expectFirstTrackPoint(TrackPoint trackPoint, long trackId, long trackPointId) {
|
protected void expectFirstTrackPoint(TrackPoint trackPoint, Track.Id trackId, long trackPointId) {
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint(trackPoint != null ? (TrackPoint[]) any() : (TrackPoint[]) any(), eq(trackId))).thenReturn(1);
|
when(contentProviderUtils.bulkInsertTrackPoint(trackPoint != null ? (TrackPoint[]) any() : (TrackPoint[]) any(), eq(trackId))).thenReturn(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,10 +111,10 @@ public abstract class AbstractTestFileTrackImporter {
|
|||||||
* @param lastTrack true if it is the last track in the gpx
|
* @param lastTrack true if it is the last track in the gpx
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
protected void expectTrackUpdate(ArgumentCaptor<Track> trackCaptor, boolean lastTrack, long trackId) {
|
protected void expectTrackUpdate(ArgumentCaptor<Track> trackCaptor, boolean lastTrack, Track.Id trackId) {
|
||||||
contentProviderUtils.updateTrack(trackCaptor.capture());
|
contentProviderUtils.updateTrack(trackCaptor.capture());
|
||||||
|
|
||||||
when(contentProviderUtils.insertWaypoint((Waypoint) any())).thenReturn(WAYPOINT_ID_O_URI);
|
when(contentProviderUtils.insertWaypoint(any())).thenReturn(WAYPOINT_ID_O_URI);
|
||||||
if (lastTrack) {
|
if (lastTrack) {
|
||||||
// Return null to not add waypoints
|
// Return null to not add waypoints
|
||||||
when(contentProviderUtils.getTrack(trackId)).thenReturn(null);
|
when(contentProviderUtils.getTrack(trackId)).thenReturn(null);
|
||||||
|
|||||||
@@ -17,8 +17,10 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
@@ -27,9 +29,11 @@ import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
|||||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||||
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export a track to {@link TrackFileFormat} and verify that the import is identical.
|
* Export a track to {@link TrackFileFormat} and verify that the import is identical.
|
||||||
@@ -48,9 +52,12 @@ public class ExportImportTest {
|
|||||||
private static final String TRACK_ICON = "the track icon";
|
private static final String TRACK_ICON = "the track icon";
|
||||||
private static final String TRACK_CATEGORY = "the category";
|
private static final String TRACK_CATEGORY = "the category";
|
||||||
private static final String TRACK_DESCRIPTION = "the description";
|
private static final String TRACK_DESCRIPTION = "the description";
|
||||||
|
|
||||||
private final List<Waypoint> waypoints = new ArrayList<>();
|
private final List<Waypoint> waypoints = new ArrayList<>();
|
||||||
private long importTrackId;
|
private final List<TrackPoint> trackPoints = new ArrayList<>();
|
||||||
private final long trackId = System.currentTimeMillis();
|
|
||||||
|
private Track.Id importTrackId;
|
||||||
|
private final Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -61,6 +68,9 @@ public class ExportImportTest {
|
|||||||
contentProviderUtils.insertTrack(track.first);
|
contentProviderUtils.insertTrack(track.first);
|
||||||
contentProviderUtils.bulkInsertTrackPoint(track.second, track.first.getId());
|
contentProviderUtils.bulkInsertTrackPoint(track.second, track.first.getId());
|
||||||
|
|
||||||
|
trackPoints.clear();
|
||||||
|
trackPoints.addAll(Arrays.asList(track.second));
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
Waypoint waypoint = new Waypoint(track.second[i].getLocation());
|
Waypoint waypoint = new Waypoint(track.second[i].getLocation());
|
||||||
waypoint.setName("the waypoint " + i);
|
waypoint.setName("the waypoint " + i);
|
||||||
@@ -96,26 +106,59 @@ public class ExportImportTest {
|
|||||||
// given
|
// given
|
||||||
Track track = contentProviderUtils.getTrack(trackId);
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
|
||||||
TrackFileFormat trackFileFormat = TrackFileFormat.KML_WITH_TRACKDETAIL;
|
TrackExporter trackExporter = TrackFileFormat.KML_WITH_TRACKDETAIL.newTrackExporter(context);
|
||||||
TrackExporter trackExporter = trackFileFormat.newTrackExporter(context, new Track[]{track}, null);
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// 1. export
|
// 1. export
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
trackExporter.writeTrack(context, outputStream);
|
trackExporter.writeTrack(track, outputStream);
|
||||||
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
System.out.println(outputStream.toString());
|
|
||||||
|
|
||||||
// 2. import
|
// 2. import
|
||||||
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context, -1L);
|
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
|
||||||
|
importTrackId = trackImporter.importFile(inputStream);
|
||||||
|
|
||||||
|
// then
|
||||||
|
// 1. track
|
||||||
|
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
|
||||||
|
assertNotNull(importedTrack);
|
||||||
|
assertEquals(track.getCategory(), importedTrack.getCategory());
|
||||||
|
assertEquals(track.getDescription(), importedTrack.getDescription());
|
||||||
|
assertEquals(track.getName(), importedTrack.getName());
|
||||||
|
assertEquals(track.getIcon(), importedTrack.getIcon());
|
||||||
|
assertEquals(track.getUuid(), importedTrack.getUuid());
|
||||||
|
|
||||||
|
// 2. waypoints
|
||||||
|
assertWaypoints();
|
||||||
|
|
||||||
|
// 3. trackpoints
|
||||||
|
assertTrackpoints(false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
|
@Test
|
||||||
|
public void kml_with_trackdetail_and_sensordata() {
|
||||||
|
// given
|
||||||
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
|
||||||
|
TrackExporter trackExporter = TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.newTrackExporter(context);
|
||||||
|
|
||||||
|
// when
|
||||||
|
// 1. export
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
trackExporter.writeTrack(track, outputStream);
|
||||||
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
|
|
||||||
|
// 2. import
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
|
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
|
||||||
importTrackId = trackImporter.importFile(inputStream);
|
importTrackId = trackImporter.importFile(inputStream);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
// 1. track
|
// 1. track
|
||||||
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
|
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
|
||||||
assertNotNull(importedTrack);
|
assertNotNull(importedTrack);
|
||||||
//TODO assertEquals(track.getTrackPoints(), importedTrack.getTrackPoints());
|
|
||||||
assertEquals(track.getCategory(), importedTrack.getCategory());
|
assertEquals(track.getCategory(), importedTrack.getCategory());
|
||||||
assertEquals(track.getDescription(), importedTrack.getDescription());
|
assertEquals(track.getDescription(), importedTrack.getDescription());
|
||||||
assertEquals(track.getName(), importedTrack.getName());
|
assertEquals(track.getName(), importedTrack.getName());
|
||||||
@@ -124,14 +167,32 @@ public class ExportImportTest {
|
|||||||
// 2. waypoints
|
// 2. waypoints
|
||||||
assertWaypoints();
|
assertWaypoints();
|
||||||
|
|
||||||
//TODO Check absolute time of trackpoints
|
// 3. trackpoints
|
||||||
|
assertTrackpoints(true, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@Test
|
@Test
|
||||||
public void kml_with_trackdetail_and_sensordata() {
|
public void kml_with_trackdetail_and_sensordata_duplicate_trackUUID() {
|
||||||
// TODO
|
// given
|
||||||
Log.e(TAG, "Test not implemented.");
|
PreferencesUtils.setBoolean(context, R.string.import_prevent_reimport_key, true);
|
||||||
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
|
||||||
|
TrackExporter trackExporter = TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.newTrackExporter(context);
|
||||||
|
|
||||||
|
// when
|
||||||
|
// 1. export
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
trackExporter.writeTrack(track, outputStream);
|
||||||
|
|
||||||
|
// 2. import
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
|
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
|
||||||
|
importTrackId = trackImporter.importFile(inputStream);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
|
||||||
|
assertNull(importedTrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@@ -168,13 +229,13 @@ public class ExportImportTest {
|
|||||||
// given
|
// given
|
||||||
Track track = contentProviderUtils.getTrack(trackId);
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
|
||||||
TrackFileFormat trackFileFormat = TrackFileFormat.GPX;
|
TrackExporter trackExporter = TrackFileFormat.GPX.newTrackExporter(context);
|
||||||
TrackExporter trackExporter = trackFileFormat.newTrackExporter(context, new Track[]{track}, null);
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// 1. export
|
// 1. export
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
trackExporter.writeTrack(context, outputStream);
|
trackExporter.writeTrack(track, outputStream);
|
||||||
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
|
|
||||||
// 2. import
|
// 2. import
|
||||||
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
@@ -185,7 +246,6 @@ public class ExportImportTest {
|
|||||||
// 1. track
|
// 1. track
|
||||||
Track trackImported = contentProviderUtils.getTrack(importTrackId);
|
Track trackImported = contentProviderUtils.getTrack(importTrackId);
|
||||||
assertNotNull(trackImported);
|
assertNotNull(trackImported);
|
||||||
//TODO assertEquals(track.getTrackPoints(), trackImported.getTrackPoints());
|
|
||||||
assertEquals(track.getCategory(), trackImported.getCategory());
|
assertEquals(track.getCategory(), trackImported.getCategory());
|
||||||
assertEquals(track.getDescription(), trackImported.getDescription());
|
assertEquals(track.getDescription(), trackImported.getDescription());
|
||||||
assertEquals(track.getName(), trackImported.getName());
|
assertEquals(track.getName(), trackImported.getName());
|
||||||
@@ -196,7 +256,33 @@ public class ExportImportTest {
|
|||||||
// 2. waypoints
|
// 2. waypoints
|
||||||
assertWaypoints();
|
assertWaypoints();
|
||||||
|
|
||||||
//TODO Check absolute time of trackpoints
|
// 3. trackpoints
|
||||||
|
assertTrackpoints(false, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
|
@Test
|
||||||
|
public void gpx_duplicate_trackUUID() {
|
||||||
|
// given
|
||||||
|
PreferencesUtils.setBoolean(context, R.string.import_prevent_reimport_key, true);
|
||||||
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
|
||||||
|
TrackExporter trackExporter = TrackFileFormat.GPX.newTrackExporter(context);
|
||||||
|
|
||||||
|
// when
|
||||||
|
// 1. export
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
trackExporter.writeTrack(track, outputStream);
|
||||||
|
|
||||||
|
// 2. import
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||||
|
AbstractFileTrackImporter trackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
||||||
|
importTrackId = trackImporter.importFile(inputStream);
|
||||||
|
|
||||||
|
// then
|
||||||
|
// 1. track
|
||||||
|
Track trackImported = contentProviderUtils.getTrack(importTrackId);
|
||||||
|
assertNull(trackImported);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertWaypoints() {
|
private void assertWaypoints() {
|
||||||
@@ -217,4 +303,33 @@ public class ExportImportTest {
|
|||||||
assertEquals(waypoint.getLocation().getAltitude(), importedWaypoint.getLocation().getAltitude(), 0.001);
|
assertEquals(waypoint.getLocation().getAltitude(), importedWaypoint.getLocation().getAltitude(), 0.001);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertTrackpoints(boolean verifyPower, boolean verifyHeartrate, boolean verifyCadence) {
|
||||||
|
List<TrackPoint> importedTrackPoints = contentProviderUtils.getTrackPoints(importTrackId);
|
||||||
|
assertEquals(trackPoints.size(), importedTrackPoints.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < trackPoints.size(); i++) {
|
||||||
|
TrackPoint trackPoint = trackPoints.get(i);
|
||||||
|
TrackPoint importedTrackPoint = importedTrackPoints.get(i);
|
||||||
|
|
||||||
|
assertEquals(trackPoint.getTime(), importedTrackPoint.getTime(), 0.01);
|
||||||
|
|
||||||
|
// TODO Not exported for GPX/KML
|
||||||
|
// assertEquals(trackPoint.getAccuracy(), importedTrackPoint.getAccuracy(), 0.01);
|
||||||
|
|
||||||
|
assertEquals(trackPoint.getLatitude(), importedTrackPoint.getLatitude(), 0.001);
|
||||||
|
assertEquals(trackPoint.getLongitude(), importedTrackPoint.getLongitude(), 0.001);
|
||||||
|
assertEquals(trackPoint.getAltitude(), importedTrackPoint.getAltitude(), 0.001);
|
||||||
|
assertEquals(trackPoint.getSpeed(), importedTrackPoint.getSpeed(), 0.001);
|
||||||
|
if (verifyHeartrate) {
|
||||||
|
assertEquals(trackPoint.getHeartRate_bpm(), importedTrackPoint.getHeartRate_bpm(), 0.01);
|
||||||
|
}
|
||||||
|
if (verifyCadence) {
|
||||||
|
assertEquals(trackPoint.getCyclingCadence_rpm(), importedTrackPoint.getCyclingCadence_rpm(), 0.01);
|
||||||
|
}
|
||||||
|
if (verifyPower) {
|
||||||
|
assertEquals(trackPoint.getPower(), importedTrackPoint.getPower(), 0.01);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dennisguse.opentracks.io.file.importer;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.any;
|
|
||||||
import static org.mockito.Mockito.anyLong;
|
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
|
||||||
import static org.mockito.Mockito.eq;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link GpxFileTrackImporter}.
|
|
||||||
*
|
|
||||||
* @author Steffen Horlacher
|
|
||||||
*/
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
|
||||||
public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|
||||||
|
|
||||||
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "<gpx><trk>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
|
||||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg></trk></gpx>";
|
|
||||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "<gpx><trk>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
|
||||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg><trkseg>"
|
|
||||||
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3) + "</trkseg></trk></gpx>";
|
|
||||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX = "<gpx><trk>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
|
||||||
+ getTrackPoint(0, null) + getTrackPoint(1, null) + "</trkseg><trkseg>"
|
|
||||||
+ getTrackPoint(2, null) + getTrackPoint(3, null) + "</trkseg></trk></gpx>";
|
|
||||||
|
|
||||||
private static final String INVALID_XML_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.substring(0, VALID_ONE_TRACK_ONE_SEGMENT_GPX.length() - 50);
|
|
||||||
private static final String INVALID_LOCATION_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(Double.toString(TRACK_LATITUDE), "1000.0");
|
|
||||||
private static final String INVALID_TIME_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(TRACK_TIME_0, "invalid");
|
|
||||||
private static final String INVALID_ALTITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(Double.toString(TRACK_ELEVATION), "invalid");
|
|
||||||
private static final String INVALID_LATITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(Double.toString(TRACK_LATITUDE), "invalid");
|
|
||||||
private static final String INVALID_LONGITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(Double.toString(TRACK_LONGITUDE), "invalid");
|
|
||||||
|
|
||||||
private static String getNameAndDescription(String name, String description) {
|
|
||||||
return "<name><![CDATA[" + name + "]]></name>" + "<desc><![CDATA[" + description + "]]></desc>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getTrackPoint(int index, String time) {
|
|
||||||
String latitude = Double.toString(TRACK_LATITUDE + index);
|
|
||||||
String longitude = Double.toString(TRACK_LONGITUDE + index);
|
|
||||||
String elevation = Double.toString(TRACK_ELEVATION + index);
|
|
||||||
StringBuilder buffer = new StringBuilder();
|
|
||||||
buffer.append("<trkpt lat=\"").append(latitude).append("\" lon=\"").append(longitude).append("\"><ele>").append(elevation).append("</ele>");
|
|
||||||
if (time != null) {
|
|
||||||
buffer.append("<time>").append(time).append("</time>");
|
|
||||||
}
|
|
||||||
buffer.append("</trkpt>");
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackOneSegment() throws Exception {
|
|
||||||
// given
|
|
||||||
TrackPoint trackPoint0 = createTrackPoint(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
TrackPoint trackPoint1 = createTrackPoint(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
|
|
||||||
|
|
||||||
when(contentProviderUtils.insertTrack((Track) any())).thenReturn(TRACK_ID_0_URI);
|
|
||||||
expectFirstTrackPoint(trackPoint0, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(1);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_1);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
|
|
||||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
|
||||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
|
||||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
|
||||||
Assert.assertEquals(time1 - time0, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackTwoSegments() throws Exception {
|
|
||||||
// given
|
|
||||||
TrackPoint trackPoint0 = createTrackPoint(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
|
|
||||||
when(contentProviderUtils.insertTrack((Track) any())).thenReturn(TRACK_ID_0_URI);
|
|
||||||
expectFirstTrackPoint(trackPoint0, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(5);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
|
|
||||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
|
||||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
|
||||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
|
||||||
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
|
|
||||||
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
|
|
||||||
Assert.assertEquals(time1 - time0 + time3 - time2, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackTwoSegmentsNoTime() {
|
|
||||||
// given
|
|
||||||
when(contentProviderUtils.insertTrack((Track) any())).thenReturn(TRACK_ID_0_URI);
|
|
||||||
expectFirstTrackPoint(null, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(5);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX.getBytes());
|
|
||||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
|
||||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
Assert.assertEquals(0, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, -1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidXml() {
|
|
||||||
testInvalidGpx(INVALID_XML_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidLocation() {
|
|
||||||
testInvalidGpx(INVALID_LOCATION_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidTime() {
|
|
||||||
testInvalidGpx(INVALID_TIME_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidAltitude() {
|
|
||||||
testInvalidGpx(INVALID_ALTITUDE_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidLatitude() {
|
|
||||||
testInvalidGpx(INVALID_LATITUDE_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidLongitude() {
|
|
||||||
testInvalidGpx(INVALID_LONGITUDE_GPX);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void testInvalidGpx(String xml) {
|
|
||||||
when(contentProviderUtils.insertTrack((Track) any())).thenReturn(TRACK_ID_0_URI);
|
|
||||||
|
|
||||||
// For the following, use StubReturn since we don't care whether they are invoked or not.
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), anyLong())).thenReturn(1);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
contentProviderUtils.deleteTrack(context, TRACK_ID_0);
|
|
||||||
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
|
|
||||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
|
|
||||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
|
||||||
Assert.assertEquals(-1L, trackId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dennisguse.opentracks.io.file.importer;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.any;
|
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
|
||||||
import static org.mockito.Mockito.eq;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link KmlFileTrackImporter}.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
|
||||||
public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
|
||||||
|
|
||||||
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "<kml xmlns:gx=\"http://www.google.com/kml/ext/2.2\"><Placemark>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<gx:MultiTrack><gx:Track>"
|
|
||||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1)
|
|
||||||
+ "</gx:Track></gx:MultiTrack></Placemark></kml>";
|
|
||||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "<kml xmlns:gx=\"http://www.google.com/kml/ext/2.2\"><Placemark>"
|
|
||||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<gx:MultiTrack><gx:Track>"
|
|
||||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</gx:Track><gx:Track>"
|
|
||||||
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3)
|
|
||||||
+ "</gx:Track></gx:MultiTrack></Placemark></kml>";
|
|
||||||
|
|
||||||
private static String getNameAndDescription(String name, String description) {
|
|
||||||
return "<name><![CDATA[" + name + "]]></name><description><![CDATA[" + description
|
|
||||||
+ "]]></description>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getTrackPoint(int index, String time) {
|
|
||||||
String latitude = Double.toString(TRACK_LATITUDE + index);
|
|
||||||
String longitude = Double.toString(TRACK_LONGITUDE + index);
|
|
||||||
String altitude = Double.toString(TRACK_ELEVATION + index);
|
|
||||||
return "<when>" + time + "</when>" + "<gx:coord>" + longitude + " " + latitude + " " + altitude + "</gx:coord>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackOneSegment() throws Exception {
|
|
||||||
// given
|
|
||||||
TrackPoint trackPoint0 = createTrackPoint(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
TrackPoint trackPointl1 = createTrackPoint(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
|
|
||||||
|
|
||||||
contentProviderUtils.clearTrack(context, TRACK_ID_0);
|
|
||||||
expectFirstTrackPoint(trackPoint0, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(1);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_1);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
|
|
||||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, TRACK_ID_0, contentProviderUtils);
|
|
||||||
long trackId = kmlFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
|
||||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
|
||||||
Assert.assertEquals(time1 - time0, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOneTrackTwoSegments() throws Exception {
|
|
||||||
// given
|
|
||||||
TrackPoint trackPoint0 = createTrackPoint(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
|
|
||||||
contentProviderUtils.clearTrack(context, TRACK_ID_0);
|
|
||||||
expectFirstTrackPoint(trackPoint0, TRACK_ID_0, TRACK_POINT_ID_0);
|
|
||||||
|
|
||||||
// A flush happens at the end
|
|
||||||
when(contentProviderUtils.bulkInsertTrackPoint((TrackPoint[]) any(), eq(TRACK_ID_0))).thenReturn(5);
|
|
||||||
when(contentProviderUtils.getLastTrackPointId(TRACK_ID_0)).thenReturn(TRACK_POINT_ID_3);
|
|
||||||
when(contentProviderUtils.getTrack(PreferencesUtils.getRecordingTrackId(context))).thenReturn(null);
|
|
||||||
|
|
||||||
ArgumentCaptor<Track> trackCaptor = ArgumentCaptor.forClass(Track.class);
|
|
||||||
expectTrackUpdate(trackCaptor, true, TRACK_ID_0);
|
|
||||||
|
|
||||||
// when
|
|
||||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
|
|
||||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context, TRACK_ID_0, contentProviderUtils);
|
|
||||||
long trackId = kmlFileTrackImporter.importFile(inputStream);
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(contentProviderUtils, atLeastOnce()).updateTrack(trackCaptor.capture());
|
|
||||||
Assert.assertEquals(TRACK_ID_0, trackId);
|
|
||||||
|
|
||||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
|
||||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
|
||||||
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
|
|
||||||
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
|
|
||||||
Assert.assertEquals(time1 - time0 + time3 - time2, trackCaptor.getValue().getTrackStatistics().getTotalTime());
|
|
||||||
|
|
||||||
verifyTrack(trackCaptor.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,6 +21,8 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.JUnit4;
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.services.handlers.AdaptiveLocationListenerPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the {@link AdaptiveLocationListenerPolicy}.
|
* Tests the {@link AdaptiveLocationListenerPolicy}.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import android.content.Intent;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
@@ -33,6 +34,7 @@ import androidx.test.rule.ServiceTestRule;
|
|||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -69,10 +71,17 @@ public class TrackRecordingServiceTest {
|
|||||||
@Rule
|
@Rule
|
||||||
public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION);
|
public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION);
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void preSetUp() {
|
||||||
|
// Prepare looper for Android's message queue
|
||||||
|
if (Looper.myLooper() == null) Looper.prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private final Context context = ApplicationProvider.getApplicationContext();
|
private final Context context = ApplicationProvider.getApplicationContext();
|
||||||
private ContentProviderUtils contentProviderUtils;
|
private ContentProviderUtils contentProviderUtils;
|
||||||
|
|
||||||
private final long trackId = Math.abs(new Random().nextLong());
|
private final Track.Id trackId = new Track.Id(Math.abs(new Random().nextLong()));
|
||||||
|
|
||||||
static Intent createStartIntent(Context context) {
|
static Intent createStartIntent(Context context) {
|
||||||
return new Intent(context, TrackRecordingService.class);
|
return new Intent(context, TrackRecordingService.class);
|
||||||
@@ -125,7 +134,7 @@ public class TrackRecordingServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRecording_noTracks() throws Exception {
|
public void testRecording_noTracks() throws Exception {
|
||||||
// given
|
// given
|
||||||
List<Track> tracks = contentProviderUtils.getAllTracks();
|
List<Track> tracks = contentProviderUtils.getTracks();
|
||||||
Assert.assertTrue(tracks.isEmpty());
|
Assert.assertTrue(tracks.isEmpty());
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -136,7 +145,7 @@ public class TrackRecordingServiceTest {
|
|||||||
// then
|
// then
|
||||||
// Test if we start in no-recording mode by default.
|
// Test if we start in no-recording mode by default.
|
||||||
Assert.assertFalse(service.isRecording());
|
Assert.assertFalse(service.isRecording());
|
||||||
Assert.assertEquals(-1L, service.getRecordingTrackId());
|
Assert.assertNull(service.getRecordingTrackId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -150,7 +159,7 @@ public class TrackRecordingServiceTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertFalse(service.isRecording());
|
Assert.assertFalse(service.isRecording());
|
||||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
Assert.assertNull(service.getRecordingTrackId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -172,7 +181,7 @@ public class TrackRecordingServiceTest {
|
|||||||
// given
|
// given
|
||||||
createDummyTrack(trackId, -1L, true);
|
createDummyTrack(trackId, -1L, true);
|
||||||
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
||||||
insertLocation(service);
|
newTrackPoint(service);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
service.pauseCurrentTrack();
|
service.pauseCurrentTrack();
|
||||||
@@ -182,7 +191,7 @@ public class TrackRecordingServiceTest {
|
|||||||
|
|
||||||
//when
|
//when
|
||||||
service.resumeTrack(trackId);
|
service.resumeTrack(trackId);
|
||||||
insertLocation(service);
|
newTrackPoint(service);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertTrue(service.isRecording());
|
Assert.assertTrue(service.isRecording());
|
||||||
@@ -201,14 +210,14 @@ public class TrackRecordingServiceTest {
|
|||||||
// given
|
// given
|
||||||
createDummyTrack(trackId, -1L, true);
|
createDummyTrack(trackId, -1L, true);
|
||||||
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
||||||
insertLocation(service);
|
newTrackPoint(service);
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
Assert.assertEquals(1, contentProviderUtils.getTrackPoints(trackId).size());
|
Assert.assertEquals(1, contentProviderUtils.getTrackPoints(trackId).size());
|
||||||
|
|
||||||
// when
|
// when
|
||||||
service.resumeTrack(trackId);
|
service.resumeTrack(trackId);
|
||||||
insertLocation(service);
|
newTrackPoint(service);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertTrue(service.isRecording());
|
Assert.assertTrue(service.isRecording());
|
||||||
@@ -234,7 +243,7 @@ public class TrackRecordingServiceTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertFalse(service.isRecording());
|
Assert.assertFalse(service.isRecording());
|
||||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
Assert.assertNull(service.getRecordingTrackId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -245,13 +254,13 @@ public class TrackRecordingServiceTest {
|
|||||||
service.startNewTrack();
|
service.startNewTrack();
|
||||||
Assert.assertTrue(service.isRecording());
|
Assert.assertTrue(service.isRecording());
|
||||||
|
|
||||||
long trackId = service.getRecordingTrackId();
|
Track.Id trackId = service.getRecordingTrackId();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
long newTrackId = service.startNewTrack();
|
Track.Id newTrackId = service.startNewTrack();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, newTrackId);
|
Assert.assertNull(newTrackId);
|
||||||
|
|
||||||
Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context));
|
Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context));
|
||||||
Assert.assertEquals(trackId, service.getRecordingTrackId());
|
Assert.assertEquals(trackId, service.getRecordingTrackId());
|
||||||
@@ -270,7 +279,7 @@ public class TrackRecordingServiceTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertFalse(PreferencesUtils.isRecording(context));
|
Assert.assertFalse(PreferencesUtils.isRecording(context));
|
||||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
Assert.assertNull(service.getRecordingTrackId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -281,10 +290,10 @@ public class TrackRecordingServiceTest {
|
|||||||
Assert.assertFalse(service.isRecording());
|
Assert.assertFalse(service.isRecording());
|
||||||
|
|
||||||
// when
|
// when
|
||||||
long waypointId = service.insertWaypoint(null, null, null, null);
|
Waypoint.Id waypointId = service.insertWaypoint(null, null, null, null);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertEquals(-1L, waypointId);
|
Assert.assertNull(waypointId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -294,11 +303,11 @@ public class TrackRecordingServiceTest {
|
|||||||
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
||||||
service.startNewTrack();
|
service.startNewTrack();
|
||||||
Assert.assertTrue(service.isRecording());
|
Assert.assertTrue(service.isRecording());
|
||||||
insertLocation(service);
|
newTrackPoint(service);
|
||||||
long trackId = service.getRecordingTrackId();
|
Track.Id trackId = service.getRecordingTrackId();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
long waypointId = service.insertWaypoint(null, null, null, null);
|
Waypoint.Id waypointId = service.insertWaypoint(null, null, null, null);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
Assert.assertNotEquals(-1L, waypointId);
|
Assert.assertNotEquals(-1L, waypointId);
|
||||||
@@ -313,15 +322,15 @@ public class TrackRecordingServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addTrack(Track track, boolean isRecording) {
|
private void addTrack(Track track, boolean isRecording) {
|
||||||
Assert.assertTrue(track.getId() >= 0);
|
Assert.assertTrue(track.getId().isValid());
|
||||||
contentProviderUtils.insertTrack(track);
|
contentProviderUtils.insertTrack(track);
|
||||||
Assert.assertEquals(track.getId(), contentProviderUtils.getTrack(track.getId()).getId());
|
Assert.assertEquals(track.getId(), contentProviderUtils.getTrack(track.getId()).getId());
|
||||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key, isRecording ? track.getId() : PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
PreferencesUtils.setLong(context, R.string.recording_track_id_key, isRecording ? track.getId().getId() : PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||||
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, !isRecording);
|
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, !isRecording);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Do not use to create a track that is currently recording.
|
// NOTE: Do not use to create a track that is currently recording.
|
||||||
private void createDummyTrack(long id, long stopTime, boolean isRecording) {
|
private void createDummyTrack(Track.Id id, long stopTime, boolean isRecording) {
|
||||||
Track dummyTrack = new Track();
|
Track dummyTrack = new Track();
|
||||||
dummyTrack.setId(id);
|
dummyTrack.setId(id);
|
||||||
dummyTrack.setName("Dummy Track");
|
dummyTrack.setName("Dummy Track");
|
||||||
@@ -331,18 +340,18 @@ public class TrackRecordingServiceTest {
|
|||||||
addTrack(dummyTrack, isRecording);
|
addTrack(dummyTrack, isRecording);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void insertLocation(TrackRecordingServiceInterface trackRecordingService) throws InterruptedException {
|
private static void newTrackPoint(TrackRecordingServiceInterface trackRecordingService) throws InterruptedException {
|
||||||
insertLocation(trackRecordingService, 45.0f, 35f, 5, 10, System.currentTimeMillis());
|
newTrackPoint(trackRecordingService, 45.0f, 35f, 5, 10, System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void insertLocation(TrackRecordingServiceInterface trackRecordingService, double latitude, double longitude, float accuracy, long speed) throws InterruptedException {
|
static void newTrackPoint(TrackRecordingServiceInterface trackRecordingService, double latitude, double longitude, float accuracy, long speed) throws InterruptedException {
|
||||||
insertLocation(trackRecordingService, latitude, longitude, accuracy, speed, System.currentTimeMillis());
|
newTrackPoint(trackRecordingService, latitude, longitude, accuracy, speed, System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a location and waits for 200ms.
|
* Inserts a location and waits for 200ms.
|
||||||
*/
|
*/
|
||||||
private static void insertLocation(TrackRecordingServiceInterface trackRecordingService, double latitude, double longitude, float accuracy, long speed, long time) throws InterruptedException {
|
private static void newTrackPoint(TrackRecordingServiceInterface trackRecordingService, double latitude, double longitude, float accuracy, long speed, long time) throws InterruptedException {
|
||||||
Location location = new Location("gps");
|
Location location = new Location("gps");
|
||||||
location.setLongitude(longitude);
|
location.setLongitude(longitude);
|
||||||
location.setLatitude(latitude);
|
location.setLatitude(latitude);
|
||||||
@@ -350,7 +359,9 @@ public class TrackRecordingServiceTest {
|
|||||||
location.setSpeed(speed);
|
location.setSpeed(speed);
|
||||||
location.setTime(time);
|
location.setTime(time);
|
||||||
location.setBearing(3.0f);
|
location.setBearing(3.0f);
|
||||||
trackRecordingService.insertLocation(location);
|
TrackPoint trackPoint = new TrackPoint(location);
|
||||||
|
int prefAccuracy = PreferencesUtils.getRecordingGPSAccuracy(ApplicationProvider.getApplicationContext());
|
||||||
|
trackRecordingService.newTrackPoint(trackPoint, prefAccuracy);
|
||||||
|
|
||||||
//TODO Needed?
|
//TODO Needed?
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.util.List;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
@@ -72,14 +73,11 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
sharedPreferences.edit().clear().commit();
|
sharedPreferences.edit().clear().commit();
|
||||||
|
|
||||||
service = ((TrackRecordingServiceInterface) mServiceRule.bindService(TrackRecordingServiceTest.createStartIntent(context)));
|
service = ((TrackRecordingServiceInterface) mServiceRule.bindService(TrackRecordingServiceTest.createStartIntent(context)));
|
||||||
//Disable executorService to not insert locations from GPS via LocationManager
|
|
||||||
service.enableLocationExecutor(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
// Reset service (if some previous test failed)
|
// Reset service (if some previous test failed)
|
||||||
service.enableLocationExecutor(true);
|
|
||||||
if (service.isRecording() || service.isPaused()) {
|
if (service.isRecording() || service.isPaused()) {
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
}
|
}
|
||||||
@@ -92,15 +90,15 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
@Test
|
@Test
|
||||||
public void testOnLocationChangedAsync_movingAccurate() throws Exception {
|
public void testOnLocationChangedAsync_movingAccurate() throws Exception {
|
||||||
// given
|
// given
|
||||||
long trackId = service.startNewTrack();
|
Track.Id trackId = service.startNewTrack();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0001, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0001, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0002, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0002, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0003, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0003, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0004, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0004, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0005, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0005, 35.0, 5, 15);
|
||||||
|
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
@@ -112,42 +110,19 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
Assert.assertEquals(45.0005, trackPoints.get(5).getLatitude(), 0.01);
|
Assert.assertEquals(45.0005, trackPoints.get(5).getLatitude(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
@MediumTest
|
|
||||||
@Test
|
|
||||||
public void testOnLocationChangedAsync_movingInaccurate() throws Exception {
|
|
||||||
// given
|
|
||||||
long trackId = service.startNewTrack();
|
|
||||||
|
|
||||||
// when
|
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 15);
|
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.1, 35.0, Long.MAX_VALUE, 15);
|
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.2, 35.0, Long.MAX_VALUE, 15);
|
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.3, 35.0, Long.MAX_VALUE, 15);
|
|
||||||
TrackRecordingServiceTest.insertLocation(service, 99.0, 35.0, Long.MAX_VALUE, 15);
|
|
||||||
|
|
||||||
service.endCurrentTrack();
|
|
||||||
|
|
||||||
// then
|
|
||||||
Assert.assertFalse(service.isRecording());
|
|
||||||
|
|
||||||
List<TrackPoint> trackPoints = contentProviderUtils.getTrackPoints(trackId);
|
|
||||||
Assert.assertEquals(1, trackPoints.size());
|
|
||||||
Assert.assertEquals(45.0, trackPoints.get(0).getLatitude(), 0.01);
|
|
||||||
}
|
|
||||||
|
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testOnLocationChangedAsync_slowMovingAccurate() throws Exception {
|
public void testOnLocationChangedAsync_slowMovingAccurate() throws Exception {
|
||||||
// given
|
// given
|
||||||
long trackId = service.startNewTrack();
|
Track.Id trackId = service.startNewTrack();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.000001, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.000001, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.000002, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.000002, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.000003, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.000003, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.000004, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.000004, 35.0, 5, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.000005, 35.0, 5, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.000005, 35.0, 5, 15);
|
||||||
|
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
@@ -181,15 +156,15 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
@Test
|
@Test
|
||||||
public void testOnLocationChangedAsync_idle() throws Exception {
|
public void testOnLocationChangedAsync_idle() throws Exception {
|
||||||
// given
|
// given
|
||||||
long trackId = service.startNewTrack();
|
Track.Id trackId = service.startNewTrack();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 1, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 2, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 2, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 3, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 3, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 4, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 6, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 6, 0);
|
||||||
|
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
@@ -207,15 +182,15 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
@Test
|
@Test
|
||||||
public void testOnLocationChangedAsync_idle_withMovement() throws Exception {
|
public void testOnLocationChangedAsync_idle_withMovement() throws Exception {
|
||||||
// given
|
// given
|
||||||
long trackId = service.startNewTrack();
|
Track.Id trackId = service.startNewTrack();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 1, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 15);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 2, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 2, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 3, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 3, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 4, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 6, 15);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 6, 15);
|
||||||
|
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
@@ -235,7 +210,7 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
@Test
|
@Test
|
||||||
public void testOnLocationChangedAsync_idle_withSensorData() throws Exception {
|
public void testOnLocationChangedAsync_idle_withSensorData() throws Exception {
|
||||||
// given
|
// given
|
||||||
long trackId = service.startNewTrack();
|
Track.Id trackId = service.startNewTrack();
|
||||||
|
|
||||||
service.setRemoteSensorManager(new BluetoothRemoteSensorManager(context) {
|
service.setRemoteSensorManager(new BluetoothRemoteSensorManager(context) {
|
||||||
|
|
||||||
@@ -253,12 +228,12 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 0, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 0, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 1, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 2, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 2, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 3, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 3, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 4, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 0);
|
||||||
|
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
@@ -279,14 +254,14 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
@Test
|
@Test
|
||||||
public void testOnLocationChangedAsync_segment() throws Exception {
|
public void testOnLocationChangedAsync_segment() throws Exception {
|
||||||
// given
|
// given
|
||||||
long trackId = service.startNewTrack();
|
Track.Id trackId = service.startNewTrack();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 1, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.1, 35.0, 2, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.1, 35.0, 2, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.1, 35.0, 3, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.1, 35.0, 3, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.2, 35.0, 4, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.2, 35.0, 4, 0);
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.2, 35.0, 5, 0);
|
TrackRecordingServiceTest.newTrackPoint(service, 45.2, 35.0, 5, 0);
|
||||||
|
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
|
|
||||||
@@ -303,25 +278,4 @@ public class TrackRecordingServiceTestLocation {
|
|||||||
Assert.assertEquals(4, trackPoints.get(5).getAccuracy(), 0.01);
|
Assert.assertEquals(4, trackPoints.get(5).getAccuracy(), 0.01);
|
||||||
Assert.assertEquals(5, trackPoints.get(6).getAccuracy(), 0.01);
|
Assert.assertEquals(5, trackPoints.get(6).getAccuracy(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
@MediumTest
|
|
||||||
@Test
|
|
||||||
public void testOnLocationChangedAsync_firstTrackPointInvalid() throws Exception {
|
|
||||||
// given
|
|
||||||
long trackId = service.startNewTrack();
|
|
||||||
|
|
||||||
// when
|
|
||||||
service.insertLocation(TrackPoint.createPause().getLocation());
|
|
||||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 0, 0);
|
|
||||||
service.insertLocation(TrackPoint.createPause().getLocation());
|
|
||||||
|
|
||||||
service.endCurrentTrack();
|
|
||||||
|
|
||||||
// then
|
|
||||||
Assert.assertFalse(service.isRecording());
|
|
||||||
|
|
||||||
List<TrackPoint> trackPoints = contentProviderUtils.getTrackPoints(trackId);
|
|
||||||
Assert.assertEquals(1, trackPoints.size());
|
|
||||||
Assert.assertEquals(0, trackPoints.get(0).getAccuracy(), 0.01);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
import de.dennisguse.opentracks.content.provider.CustomContentProvider;
|
import de.dennisguse.opentracks.content.provider.CustomContentProvider;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
@@ -186,7 +187,7 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
@Test
|
@Test
|
||||||
public void testIntegration_completeRecordingSession() throws TimeoutException {
|
public void testIntegration_completeRecordingSession() throws TimeoutException {
|
||||||
List<Track> tracks = contentProviderUtils.getAllTracks();
|
List<Track> tracks = contentProviderUtils.getTracks();
|
||||||
Assert.assertTrue(tracks.isEmpty());
|
Assert.assertTrue(tracks.isEmpty());
|
||||||
fullRecordingSession();
|
fullRecordingSession();
|
||||||
}
|
}
|
||||||
@@ -196,14 +197,14 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
Assert.assertFalse(service.isRecording());
|
Assert.assertFalse(service.isRecording());
|
||||||
|
|
||||||
// Start a track.
|
// Start a track.
|
||||||
long id = service.startNewTrack();
|
Track.Id trackId = service.startNewTrack();
|
||||||
Assert.assertTrue(id >= 0);
|
Assert.assertTrue(trackId.isValid());
|
||||||
Assert.assertTrue(service.isRecording());
|
Assert.assertTrue(service.isRecording());
|
||||||
Track track = contentProviderUtils.getTrack(id);
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
Assert.assertNotNull(track);
|
Assert.assertNotNull(track);
|
||||||
Assert.assertEquals(id, track.getId());
|
Assert.assertEquals(trackId, track.getId());
|
||||||
Assert.assertEquals(id, PreferencesUtils.getRecordingTrackId(context));
|
Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context));
|
||||||
Assert.assertEquals(id, service.getRecordingTrackId());
|
Assert.assertEquals(trackId, service.getRecordingTrackId());
|
||||||
|
|
||||||
// Insert a few points, markers and statistics.
|
// Insert a few points, markers and statistics.
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
@@ -215,7 +216,9 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
location.setSpeed(10);
|
location.setSpeed(10);
|
||||||
location.setTime(startTime + i * 10000);
|
location.setTime(startTime + i * 10000);
|
||||||
location.setBearing(3.0f);
|
location.setBearing(3.0f);
|
||||||
service.insertLocation(location);
|
TrackPoint trackPoint = new TrackPoint(location);
|
||||||
|
int prefAccuracy = PreferencesUtils.getRecordingGPSAccuracy(context);
|
||||||
|
service.newTrackPoint(trackPoint, prefAccuracy);
|
||||||
|
|
||||||
if (i % 7 == 0) {
|
if (i % 7 == 0) {
|
||||||
service.insertWaypoint(null, null, null, null);
|
service.insertWaypoint(null, null, null, null);
|
||||||
@@ -225,10 +228,10 @@ public class TrackRecordingServiceTestLooper {
|
|||||||
// Stop the track. Validate if it has correct data.
|
// Stop the track. Validate if it has correct data.
|
||||||
service.endCurrentTrack();
|
service.endCurrentTrack();
|
||||||
Assert.assertFalse(service.isRecording());
|
Assert.assertFalse(service.isRecording());
|
||||||
Assert.assertEquals(-1L, service.getRecordingTrackId());
|
Assert.assertNull(service.getRecordingTrackId());
|
||||||
track = contentProviderUtils.getTrack(id);
|
track = contentProviderUtils.getTrack(trackId);
|
||||||
Assert.assertNotNull(track);
|
Assert.assertNotNull(track);
|
||||||
Assert.assertEquals(id, track.getId());
|
Assert.assertEquals(trackId, track.getId());
|
||||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||||
Assert.assertNotNull(trackStatistics);
|
Assert.assertNotNull(trackStatistics);
|
||||||
Assert.assertTrue(trackStatistics.getStartTime_ms() > 0);
|
Assert.assertTrue(trackStatistics.getStartTime_ms() > 0);
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package de.dennisguse.opentracks.services.handlers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class HandlerServerTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private HandlerServer.HandlerServerInterface server;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LocationHandler locationHandler;
|
||||||
|
|
||||||
|
private HandlerServer subject;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
subject = new HandlerServer(locationHandler, server);
|
||||||
|
subject.start(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
subject.stop(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onSharedPreferenceChanged() {
|
||||||
|
// when
|
||||||
|
subject.onSharedPreferenceChanged(null, null, null);
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(locationHandler).onSharedPreferenceChanged(null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendTrackPoint() throws InterruptedException {
|
||||||
|
// given
|
||||||
|
TrackPoint trackPoint = new TrackPoint();
|
||||||
|
int accuracy = 50;
|
||||||
|
|
||||||
|
// when
|
||||||
|
subject.sendTrackPoint(trackPoint, accuracy);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Thread.sleep(10); // Wait for executor service
|
||||||
|
verify(server).newTrackPoint(trackPoint, accuracy);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package de.dennisguse.opentracks.services.handlers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.location.Location;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.R;
|
||||||
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class LocationHandlerTest {
|
||||||
|
|
||||||
|
private final Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private HandlerServer handlerServer;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private LocationHandler locationHandler;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
// Let's use default values.
|
||||||
|
SharedPreferences sharedPreferences = PreferencesUtils.getSharedPreferences(context);
|
||||||
|
sharedPreferences.edit().clear().commit();
|
||||||
|
|
||||||
|
locationHandler.onSharedPreferenceChanged(context, PreferencesUtils.getSharedPreferences(context), context.getString(R.string.recording_gps_accuracy_key));
|
||||||
|
locationHandler.onSharedPreferenceChanged(context, PreferencesUtils.getSharedPreferences(context), context.getString(R.string.min_recording_interval_key));
|
||||||
|
locationHandler.onStart(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a valid location changed in LocationHandler -> newTrackPoint service method is called.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testOnLocationChanged_okay() {
|
||||||
|
// when
|
||||||
|
locationHandler.onLocationChanged(createLocation(45f, 35f, 3, 5, System.currentTimeMillis()));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(handlerServer, times(1)).sendTrackPoint(any(TrackPoint.class), any(Integer.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When location changed in LocationHandler with bad location -> newTrackPoint service method is not called.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testOnLocationChanged_badLocation() {
|
||||||
|
// given
|
||||||
|
float latitude = 91f;
|
||||||
|
|
||||||
|
// when
|
||||||
|
// bad latitude
|
||||||
|
locationHandler.onLocationChanged(createLocation(latitude, 35f, 3, 5, System.currentTimeMillis()));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(handlerServer, times(0)).sendTrackPoint(any(TrackPoint.class), any(Integer.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When location changed in LocationHandler with poor accuracy -> newTrackPoint service method is not called.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testOnLocationChanged_poorAccuracy() {
|
||||||
|
// given
|
||||||
|
int prefAccuracy = PreferencesUtils.getRecordingGPSAccuracy(context);
|
||||||
|
|
||||||
|
// when
|
||||||
|
// poor latitude
|
||||||
|
locationHandler.onLocationChanged(createLocation(45f, 35f, prefAccuracy + 1, 5, System.currentTimeMillis()));
|
||||||
|
|
||||||
|
// then
|
||||||
|
// no newTrackPoint called
|
||||||
|
verify(handlerServer, times(0)).sendTrackPoint(any(TrackPoint.class), any(Integer.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnLocationChanged_movingInaccurate() {
|
||||||
|
// when
|
||||||
|
locationHandler.onLocationChanged(createLocation(45.0, 35.0, 5, 15, System.currentTimeMillis()));
|
||||||
|
locationHandler.onLocationChanged(createLocation(45.1, 35.0, Long.MAX_VALUE, 15, System.currentTimeMillis()));
|
||||||
|
locationHandler.onLocationChanged(createLocation(45.2, 35.0, Long.MAX_VALUE, 15, System.currentTimeMillis()));
|
||||||
|
locationHandler.onLocationChanged(createLocation(45.3, 35.0, Long.MAX_VALUE, 15, System.currentTimeMillis()));
|
||||||
|
locationHandler.onLocationChanged(createLocation(99.0, 35.0, Long.MAX_VALUE, 15, System.currentTimeMillis()));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(handlerServer, times(1)).sendTrackPoint(any(TrackPoint.class), any(Integer.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a location with parameters and returns the Location object.
|
||||||
|
*/
|
||||||
|
private static Location createLocation(double latitude, double longitude, float accuracy, long speed, long time) {
|
||||||
|
Location location = new Location("gps");
|
||||||
|
location.setLongitude(longitude);
|
||||||
|
location.setLatitude(latitude);
|
||||||
|
location.setAccuracy(accuracy);
|
||||||
|
location.setSpeed(speed);
|
||||||
|
location.setTime(time);
|
||||||
|
location.setBearing(3.0f);
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package de.dennisguse.opentracks.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.R;
|
||||||
|
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class PreferencesUtilsTest {
|
||||||
|
|
||||||
|
private final Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ExportTrackFileFormat_ok() {
|
||||||
|
// given
|
||||||
|
SharedPreferences.Editor editor = PreferencesUtils.getSharedPreferences(context).edit();
|
||||||
|
editor.putString(context.getString(R.string.export_trackfileformat_key), TrackFileFormat.KMZ_WITH_TRACKDETAIL.name());
|
||||||
|
editor.commit();
|
||||||
|
|
||||||
|
// when
|
||||||
|
TrackFileFormat trackFileFormat = PreferencesUtils.getExportTrackFileFormat(context);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(TrackFileFormat.KMZ_WITH_TRACKDETAIL, trackFileFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ExportTrackFileFormat_invalid() {
|
||||||
|
// given
|
||||||
|
SharedPreferences.Editor editor = PreferencesUtils.getSharedPreferences(context).edit();
|
||||||
|
editor.putString(context.getString(R.string.export_trackfileformat_key), "invalid");
|
||||||
|
editor.commit();
|
||||||
|
|
||||||
|
// when
|
||||||
|
TrackFileFormat trackFileFormat = PreferencesUtils.getExportTrackFileFormat(context);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA, trackFileFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ExportTrackFileFormat_noValue() {
|
||||||
|
// given
|
||||||
|
SharedPreferences.Editor editor = PreferencesUtils.getSharedPreferences(context).edit();
|
||||||
|
editor.clear();
|
||||||
|
editor.commit();
|
||||||
|
|
||||||
|
// when
|
||||||
|
TrackFileFormat trackFileFormat = PreferencesUtils.getExportTrackFileFormat(context);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA, trackFileFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -128,6 +128,7 @@ public class StringUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetTime_timezone() {
|
public void testGetTime_timezone() {
|
||||||
|
assertGetTime("2010-05-04T03:02:01", 2010, 5, 4, 3, 2, 1, 0);
|
||||||
assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0);
|
assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0);
|
||||||
assertGetTime("2010-05-04T03:02:01+00:00", 2010, 5, 4, 3, 2, 1, 0);
|
assertGetTime("2010-05-04T03:02:01+00:00", 2010, 5, 4, 3, 2, 1, 0);
|
||||||
assertGetTime("2010-05-04T03:02:01-00:00", 2010, 5, 4, 3, 2, 1, 0);
|
assertGetTime("2010-05-04T03:02:01-00:00", 2010, 5, 4, 3, 2, 1, 0);
|
||||||
@@ -211,4 +212,16 @@ public class StringUtilsTest {
|
|||||||
|
|
||||||
Assert.assertEquals("1", StringUtils.formatDecimal(0.99, 1));
|
Assert.assertEquals("1", StringUtils.formatDecimal(0.99, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSpeedParts() {
|
||||||
|
Assert.assertEquals("4:59", StringUtils.getSpeedParts(context, 3.34, true, false).first);
|
||||||
|
Assert.assertEquals("5:00", StringUtils.getSpeedParts(context, 3.33, true, false).first);
|
||||||
|
|
||||||
|
Assert.assertEquals("11.99", StringUtils.getSpeedParts(context, 3.33, true, true).first);
|
||||||
|
Assert.assertEquals("7.45", StringUtils.getSpeedParts(context, 3.33, false, true).first);
|
||||||
|
|
||||||
|
Assert.assertEquals("min/km", StringUtils.getSpeedParts(context, 0, true, false).second);
|
||||||
|
Assert.assertEquals("min/mi", StringUtils.getSpeedParts(context, 0, false, false).second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import java.util.Date;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link TrackNameUtils}.
|
* Tests {@link TrackNameUtils}.
|
||||||
@@ -39,7 +40,7 @@ import de.dennisguse.opentracks.R;
|
|||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class TrackNameUtilsTest {
|
public class TrackNameUtilsTest {
|
||||||
|
|
||||||
private static final long TRACK_ID = 1L;
|
private static final Track.Id TRACK_ID = new Track.Id(1L);
|
||||||
private static final long START_TIME = 1288213406000L;
|
private static final long START_TIME = 1288213406000L;
|
||||||
|
|
||||||
private static final Context CONTEXT = ApplicationProvider.getApplicationContext();
|
private static final Context CONTEXT = ApplicationProvider.getApplicationContext();
|
||||||
@@ -69,6 +70,6 @@ public class TrackNameUtilsTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testTrackName_number() {
|
public void testTrackName_number() {
|
||||||
PreferencesUtils.setString(CONTEXT, R.string.track_name_key, CONTEXT.getString(R.string.settings_recording_track_name_number_value));
|
PreferencesUtils.setString(CONTEXT, R.string.track_name_key, CONTEXT.getString(R.string.settings_recording_track_name_number_value));
|
||||||
Assert.assertEquals("Track " + TRACK_ID, TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME));
|
Assert.assertEquals("Track " + TRACK_ID.getId(), TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package de.dennisguse.opentracks.util;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class UUIDUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
|
|
||||||
|
byte[] bytes = UUIDUtils.toBytes(uuid);
|
||||||
|
UUID output = UUIDUtils.fromBytes(bytes);
|
||||||
|
|
||||||
|
Assert.assertEquals(uuid, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
package de.dennisguse.opentracks.viewmodels;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.R;
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class AggregatedStatisticsTest {
|
||||||
|
|
||||||
|
private final Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TrackStatistics object.
|
||||||
|
*
|
||||||
|
* @param totalDistance distance in meters.
|
||||||
|
* @param totalTime total time in milliseconds.
|
||||||
|
* @return TrackStatistics object.
|
||||||
|
*/
|
||||||
|
private static Track createTrack(Context context, long totalDistance, long totalTime, String category) {
|
||||||
|
TrackStatistics statistics = new TrackStatistics();
|
||||||
|
statistics.setStartTime_ms(1000L); // Resulting start time
|
||||||
|
statistics.setStopTime_ms(1000L + totalTime);
|
||||||
|
statistics.setTotalTime(totalTime);
|
||||||
|
statistics.setMovingTime(totalTime);
|
||||||
|
statistics.setTotalDistance(totalDistance);
|
||||||
|
statistics.setTotalElevationGain(50.0);
|
||||||
|
statistics.setMaxSpeed(50.0); // Resulting max speed
|
||||||
|
statistics.setMaxElevation(1250.0);
|
||||||
|
statistics.setMinElevation(1200.0); // Resulting min elevation
|
||||||
|
|
||||||
|
Track track = new Track();
|
||||||
|
track.setIcon(TrackIconUtils.getIconValue(context, category));
|
||||||
|
track.setCategory(category);
|
||||||
|
track.setTrackStatistics(statistics);
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAggregate() {
|
||||||
|
// given
|
||||||
|
// 10km in 40 minutes.
|
||||||
|
long totalDistance = 10000;
|
||||||
|
long totalTime = 2400000;
|
||||||
|
String biking = context.getString(R.string.activity_type_biking);
|
||||||
|
Track track = createTrack(context, totalDistance, totalTime, biking);
|
||||||
|
|
||||||
|
// when
|
||||||
|
AggregatedStatistics aggregatedStatistics = new AggregatedStatistics();
|
||||||
|
aggregatedStatistics.aggregate(track);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(1, aggregatedStatistics.getCount());
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(biking));
|
||||||
|
Assert.assertEquals(1, aggregatedStatistics.get(biking).getCountTracks());
|
||||||
|
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAggregate_mountainBiking() {
|
||||||
|
// given
|
||||||
|
// 10km in 40 minutes.
|
||||||
|
long totalDistance = 10000;
|
||||||
|
long totalTime = 2400000;
|
||||||
|
String mountainBiking = context.getString(R.string.activity_type_mountain_biking);
|
||||||
|
Track track = createTrack(context, totalDistance, totalTime, mountainBiking);
|
||||||
|
|
||||||
|
// when
|
||||||
|
AggregatedStatistics aggregatedStatistics = new AggregatedStatistics();
|
||||||
|
aggregatedStatistics.aggregate(track);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(mountainBiking));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAggregate_trailRunning() {
|
||||||
|
// given
|
||||||
|
// 10km in 40 minutes.
|
||||||
|
long totalDistance = 10000;
|
||||||
|
long totalTime = 2400000;
|
||||||
|
String trailRunning = context.getString(R.string.activity_type_trail_running);
|
||||||
|
Track track = createTrack(context, totalDistance, totalTime, trailRunning);
|
||||||
|
|
||||||
|
// when
|
||||||
|
AggregatedStatistics aggregatedStatistics = new AggregatedStatistics();
|
||||||
|
aggregatedStatistics.aggregate(track);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(trailRunning));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAggregate_twoBikingTracks() {
|
||||||
|
// given
|
||||||
|
// 10km in 40 minutes.
|
||||||
|
long totalDistance = 10000;
|
||||||
|
long totalTime = 2400000;
|
||||||
|
String biking = context.getString(R.string.activity_type_biking);
|
||||||
|
Track[] tracks = new Track[2];
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
tracks[i] = createTrack(context, totalDistance, totalTime, biking);
|
||||||
|
}
|
||||||
|
|
||||||
|
// when
|
||||||
|
AggregatedStatistics aggregatedStatistics = new AggregatedStatistics();
|
||||||
|
aggregatedStatistics.aggregate(tracks[0]); // biking activity 1.
|
||||||
|
aggregatedStatistics.aggregate(tracks[1]); // biking activity 2.
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(1, aggregatedStatistics.getCount());
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(biking));
|
||||||
|
Assert.assertEquals(2, aggregatedStatistics.get(biking).getCountTracks());
|
||||||
|
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance * 2, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime * 2L, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAggregate_threeDifferentTracks() {
|
||||||
|
// given
|
||||||
|
// 10km in 40 minutes.
|
||||||
|
long totalDistance = 10000;
|
||||||
|
|
||||||
|
String biking = context.getString(R.string.activity_type_biking);
|
||||||
|
String running = context.getString(R.string.activity_type_running);
|
||||||
|
String walking = context.getString(R.string.activity_type_walking);
|
||||||
|
long totalTime = 2400000;
|
||||||
|
Track[] tracks = new Track[]{
|
||||||
|
createTrack(context, totalDistance, totalTime, biking),
|
||||||
|
createTrack(context, totalDistance, totalTime, running),
|
||||||
|
createTrack(context, totalDistance, totalTime, walking)
|
||||||
|
};
|
||||||
|
|
||||||
|
// when
|
||||||
|
AggregatedStatistics aggregatedStatistics = new AggregatedStatistics();
|
||||||
|
aggregatedStatistics.aggregate(tracks[0]); // biking activity 1.
|
||||||
|
aggregatedStatistics.aggregate(tracks[1]); // biking activity 2.
|
||||||
|
aggregatedStatistics.aggregate(tracks[2]); // biking activity 3.
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(3, aggregatedStatistics.getCount());
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(biking));
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(running));
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(walking));
|
||||||
|
Assert.assertEquals(1, aggregatedStatistics.get(biking).getCountTracks());
|
||||||
|
Assert.assertEquals(1, aggregatedStatistics.get(running).getCountTracks());
|
||||||
|
Assert.assertEquals(1, aggregatedStatistics.get(walking).getCountTracks());
|
||||||
|
|
||||||
|
{
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(running).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(walking).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAggregate_severalTracksWithSeveralActivities() {
|
||||||
|
// given
|
||||||
|
// 10km in 40 minutes.
|
||||||
|
long totalDistance = 10000;
|
||||||
|
long totalTime = 2400000;
|
||||||
|
String biking = context.getString(R.string.activity_type_biking);
|
||||||
|
String running = context.getString(R.string.activity_type_running);
|
||||||
|
String walking = context.getString(R.string.activity_type_walking);
|
||||||
|
String driving = context.getString(R.string.activity_type_driving);
|
||||||
|
Track[] tracks = new Track[]{
|
||||||
|
createTrack(context, totalDistance, totalTime, biking),
|
||||||
|
createTrack(context, totalDistance, totalTime, running),
|
||||||
|
createTrack(context, totalDistance, totalTime, walking),
|
||||||
|
createTrack(context, totalDistance, totalTime, biking),
|
||||||
|
createTrack(context, totalDistance, totalTime, running),
|
||||||
|
createTrack(context, totalDistance, totalTime, walking),
|
||||||
|
createTrack(context, totalDistance, totalTime, biking),
|
||||||
|
createTrack(context, totalDistance, totalTime, biking),
|
||||||
|
createTrack(context, totalDistance, totalTime, biking),
|
||||||
|
createTrack(context, totalDistance, totalTime, driving),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// when
|
||||||
|
AggregatedStatistics aggregatedStatistics = new AggregatedStatistics();
|
||||||
|
for (Track track : tracks) {
|
||||||
|
aggregatedStatistics.aggregate(track);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
// 4 sports.
|
||||||
|
Assert.assertEquals(4, aggregatedStatistics.getCount());
|
||||||
|
|
||||||
|
// There is a map for every sport.
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(biking));
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(running));
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(walking));
|
||||||
|
Assert.assertNotNull(aggregatedStatistics.get(driving));
|
||||||
|
|
||||||
|
// Number of tracks by sport.
|
||||||
|
Assert.assertEquals(5, aggregatedStatistics.get(biking).getCountTracks()); // Biking.
|
||||||
|
Assert.assertEquals(2, aggregatedStatistics.get(running).getCountTracks()); // Running.
|
||||||
|
Assert.assertEquals(2, aggregatedStatistics.get(walking).getCountTracks()); // Walking.
|
||||||
|
Assert.assertEquals(1, aggregatedStatistics.get(driving).getCountTracks()); // Driving.
|
||||||
|
|
||||||
|
// Biking.
|
||||||
|
{
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance * 5, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime * 5, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Running.
|
||||||
|
{
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(running).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance * 2, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime * 2, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walking.
|
||||||
|
{
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(walking).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance * 2, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime * 2, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Driving.
|
||||||
|
{
|
||||||
|
TrackStatistics statistics2 = aggregatedStatistics.get(driving).getTrackStatistics();
|
||||||
|
Assert.assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||||
|
Assert.assertEquals(totalTime, statistics2.getMovingTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_logo_color_108dp" />
|
||||||
|
</adaptive-icon>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#8F0000</color>
|
||||||
|
</resources>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
Copyright 2013 Google Inc.
|
Copyright 2010 Google Inc.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -13,7 +13,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
<resources>
|
||||||
<item android:drawable="@drawable/ic_button_stop_pressed" android:state_pressed="true" />
|
<string name="app_name">OpenTracks (Debug)</string>
|
||||||
<item android:drawable="@drawable/ic_button_stop" />
|
</resources>
|
||||||
</selector>
|
|
||||||
@@ -14,48 +14,102 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="de.dennisguse.opentracks"
|
package="de.dennisguse.opentracks"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
<!-- Permission to initialize services -->
|
|
||||||
|
<supports-screens
|
||||||
|
android:anyDensity="true"
|
||||||
|
android:largeScreens="true"
|
||||||
|
android:normalScreens="true"
|
||||||
|
android:smallScreens="true"
|
||||||
|
android:xlargeScreens="true" />
|
||||||
|
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.location.gps"
|
||||||
|
android:required="true" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.android.hardware.bluetooth_le"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.camera"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.sensor.compass"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.touchscreen"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".Startup"
|
android:name=".Startup"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:hasFragileUserData="true"
|
android:hasFragileUserData="true"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:icon="${applicationLogo}"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="${applicationName}"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/ThemeCustom">
|
android:theme="@style/ThemeCustom">
|
||||||
|
|
||||||
<!-- Activities -->
|
|
||||||
<activity android:name=".AboutActivity" />
|
<activity android:name=".AboutActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".TrackDeleteActivity"
|
android:name=".TrackDeleteActivity"
|
||||||
android:theme="@style/ThemeCustomTransparent" />
|
android:theme="@style/TrackDeleteActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".HelpActivity"
|
android:name=".HelpActivity"
|
||||||
android:label="@string/menu_help" />
|
android:label="@string/menu_help" />
|
||||||
|
|
||||||
|
<activity android:name=".io.file.importer.DirectoryChooserActivity$ImportDirectoryChooserActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".io.file.importer.ImportActivity"
|
android:name=".io.file.importer.ImportActivity"
|
||||||
android:theme="@style/ThemeCustomTransparent">
|
android:theme="@style/ThemeCustomTransparentActivity">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.ATTACH_DATA" />
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="application/vnd.google-earth.kmz" />
|
||||||
|
<data
|
||||||
|
android:scheme="content"
|
||||||
|
android:host="*"
|
||||||
|
android:pathPattern="*kmz" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
<data android:mimeType="application/gpx" />
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="application/vnd.google-earth.kml+xml" />
|
||||||
|
<data
|
||||||
|
android:scheme="content"
|
||||||
|
android:host="*"
|
||||||
|
android:pathPattern="*kml" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<data android:mimeType="application/gpx+xml" />
|
<data android:mimeType="application/gpx+xml" />
|
||||||
<data android:mimeType="application/vnd.google-earth.gpx" />
|
<data
|
||||||
<data android:mimeType="application/vnd.google-earth.gpx+xml" />
|
android:scheme="content"
|
||||||
<data android:scheme="file" />
|
android:host="*"
|
||||||
|
android:pathPattern="*gpx" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".MarkerDetailActivity" />
|
<activity android:name=".MarkerDetailActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="de.dennisguse.opentracks.MarkerDetails"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".MarkerEditActivity" />
|
<activity android:name=".MarkerEditActivity" />
|
||||||
|
|
||||||
@@ -78,9 +132,9 @@ limitations under the License.
|
|||||||
android:resource="@xml/searchable" />
|
android:resource="@xml/searchable" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity android:name=".TrackRecordedActivity" />
|
||||||
android:name=".TrackDetailActivity"
|
|
||||||
android:screenOrientation="userPortrait" />
|
<activity android:name=".TrackRecordingActivity" />
|
||||||
|
|
||||||
<activity android:name=".TrackEditActivity" />
|
<activity android:name=".TrackEditActivity" />
|
||||||
|
|
||||||
@@ -94,12 +148,29 @@ limitations under the License.
|
|||||||
android:value=".SearchListActivity" />
|
android:value=".SearchListActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name=".AggregatedStatisticsActivity" />
|
||||||
|
|
||||||
|
<activity android:name=".io.file.importer.DirectoryChooserActivity$ExportDirectoryChooserActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".io.file.exporter.ExportActivity"
|
android:name=".io.file.exporter.ExportActivity"
|
||||||
android:theme="@style/ThemeCustomTransparent" />
|
android:theme="@style/ThemeCustomTransparentActivity" />
|
||||||
|
|
||||||
<activity android:name=".settings.SettingsActivity" />
|
<activity android:name=".settings.SettingsActivity" />
|
||||||
|
|
||||||
|
<activity android:name=".ShowOnMapProxyActivity$KMZ">
|
||||||
|
<intent-filter android:label="@string/open_track_as_KMZ">
|
||||||
|
<action android:name="Intent.OpenTracks-Dashboard" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name=".ShowOnMapProxyActivity$GPX">
|
||||||
|
<intent-filter android:label="@string/open_track_as_GPX">
|
||||||
|
<action android:name="Intent.OpenTracks-Dashboard" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".content.provider.ShareContentProvider"
|
android:name=".content.provider.ShareContentProvider"
|
||||||
android:authorities="${applicationId}.content"
|
android:authorities="${applicationId}.content"
|
||||||
@@ -124,32 +195,4 @@ limitations under the License.
|
|||||||
android:icon="@drawable/ic_logo_color_24dp"
|
android:icon="@drawable/ic_logo_color_24dp"
|
||||||
android:label="@string/recording_service" />
|
android:label="@string/recording_service" />
|
||||||
</application>
|
</application>
|
||||||
<supports-screens
|
|
||||||
android:anyDensity="true"
|
|
||||||
android:largeScreens="true"
|
|
||||||
android:normalScreens="true"
|
|
||||||
android:smallScreens="true"
|
|
||||||
android:xlargeScreens="true" />
|
|
||||||
<!-- Permissions to record locations -->
|
|
||||||
<uses-feature
|
|
||||||
android:name="android.hardware.location.gps"
|
|
||||||
android:required="true" />
|
|
||||||
<uses-feature
|
|
||||||
android:name="android.hardware.android.hardware.bluetooth_le"
|
|
||||||
android:required="false" />
|
|
||||||
<uses-feature
|
|
||||||
android:name="android.hardware.camera"
|
|
||||||
android:required="false" />
|
|
||||||
<uses-feature
|
|
||||||
android:name="android.hardware.sensor.compass"
|
|
||||||
android:required="false" />
|
|
||||||
<uses-feature
|
|
||||||
android:name="android.hardware.touchscreen"
|
|
||||||
android:required="false" />
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.widget.TextView;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.util.SystemUtils;
|
import de.dennisguse.opentracks.util.SystemUtils;
|
||||||
|
import de.dennisguse.opentracks.util.ViewUtils;
|
||||||
|
|
||||||
public class AboutActivity extends AbstractActivity {
|
public class AboutActivity extends AbstractActivity {
|
||||||
|
|
||||||
@@ -27,6 +28,8 @@ public class AboutActivity extends AbstractActivity {
|
|||||||
|
|
||||||
TextView textURL = findViewById(R.id.about_app_url);
|
TextView textURL = findViewById(R.id.about_app_url);
|
||||||
textURL.setText(getString(R.string.about_url, getString(R.string.app_web_url)));
|
textURL.setText(getString(R.string.about_url, getString(R.string.app_web_url)));
|
||||||
|
|
||||||
|
ViewUtils.makeClickableLinks(findViewById(android.R.id.content));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getLayoutResId() {
|
protected int getLayoutResId() {
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ package de.dennisguse.opentracks;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
||||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment.ConfirmDeleteCaller;
|
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment.ConfirmDeleteCaller;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
@@ -26,7 +30,7 @@ import de.dennisguse.opentracks.util.PreferencesUtils;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract class for the following common tasks across
|
* An abstract class for the following common tasks across
|
||||||
* {@link TrackListActivity}, {@link TrackDetailActivity}, and
|
* {@link TrackListActivity}, {@link TrackRecordedActivity}, and
|
||||||
* {@link SearchListActivity}:
|
* {@link SearchListActivity}:
|
||||||
* <p>
|
* <p>
|
||||||
* - share track <br>
|
* - share track <br>
|
||||||
@@ -55,30 +59,29 @@ public abstract class AbstractListActivity extends AbstractActivity implements C
|
|||||||
*
|
*
|
||||||
* @param trackIds the track ids
|
* @param trackIds the track ids
|
||||||
*/
|
*/
|
||||||
protected void deleteTracks(long[] trackIds) {
|
protected void deleteTracks(Track.Id... trackIds) {
|
||||||
ConfirmDeleteDialogFragment.showDialog(getSupportFragmentManager(), trackIds);
|
ConfirmDeleteDialogFragment.showDialog(getSupportFragmentManager(), trackIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfirmDeleteDone(long[] trackIds) {
|
public void onConfirmDeleteDone(Track.Id... trackIds) {
|
||||||
boolean stopRecording = false;
|
boolean stopRecording = false;
|
||||||
if (trackIds.length == 1 && trackIds[0] == -1L) {
|
|
||||||
stopRecording = true;
|
Track.Id recordingTrackId = PreferencesUtils.getRecordingTrackId(this);
|
||||||
} else {
|
for (Track.Id trackId : trackIds) {
|
||||||
long recordingTrackId = PreferencesUtils.getRecordingTrackId(this);
|
if (trackId.equals(recordingTrackId)) {
|
||||||
for (long trackId : trackIds) {
|
stopRecording = true;
|
||||||
if (trackId == recordingTrackId) {
|
break;
|
||||||
stopRecording = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stopRecording) {
|
if (stopRecording) {
|
||||||
getTrackRecordingServiceConnection().stopRecording(this, false);
|
getTrackRecordingServiceConnection().stopRecording(this, false);
|
||||||
}
|
}
|
||||||
Intent intent = IntentUtils.newIntent(this, TrackDeleteActivity.class);
|
Intent intent = IntentUtils.newIntent(this, TrackDeleteActivity.class);
|
||||||
intent.putExtra(TrackDeleteActivity.EXTRA_TRACK_IDS, trackIds);
|
intent.putParcelableArrayListExtra(TrackDeleteActivity.EXTRA_TRACK_IDS, new ArrayList<>(Arrays.asList(trackIds)));
|
||||||
startActivityForResult(intent, DELETE_REQUEST_CODE);
|
startActivityForResult(intent, DELETE_REQUEST_CODE);
|
||||||
|
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.adapters.AggregatedStatisticsAdapter;
|
||||||
|
import de.dennisguse.opentracks.viewmodels.AggregatedStatisticsModel;
|
||||||
|
|
||||||
|
public class AggregatedStatisticsActivity extends AbstractActivity {
|
||||||
|
|
||||||
|
private ListView listView;
|
||||||
|
private AggregatedStatisticsAdapter adapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
listView = findViewById(R.id.aggregated_stats_list);
|
||||||
|
listView.setEmptyView(findViewById(R.id.aggregated_stats_empty_view));
|
||||||
|
|
||||||
|
final AggregatedStatisticsModel viewModel = new ViewModelProvider(this).get(AggregatedStatisticsModel.class);
|
||||||
|
viewModel.getAggregatedStats().observe(this, aggregatedStatistics -> {
|
||||||
|
if (aggregatedStatistics != null) {
|
||||||
|
adapter = new AggregatedStatisticsAdapter(getApplicationContext(), aggregatedStatistics);
|
||||||
|
listView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getLayoutResId() {
|
||||||
|
return R.layout.aggregated_stats;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
package de.dennisguse.opentracks;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Google Inc.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Async Task to delete tracks.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
class DeleteAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
|
||||||
|
|
||||||
private final long[] trackIds;
|
|
||||||
private final Context context;
|
|
||||||
private TrackDeleteActivity deleteActivity;
|
|
||||||
// true if the AsyncTask has completed
|
|
||||||
private boolean completed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an AsyncTask.
|
|
||||||
*
|
|
||||||
* @param deleteActivity the activity currently associated with this task
|
|
||||||
* @param trackIds the track ids to delete. To delete all, set to size 1 with
|
|
||||||
* trackIds[0] == -1L
|
|
||||||
*/
|
|
||||||
public DeleteAsyncTask(TrackDeleteActivity deleteActivity, long[] trackIds) {
|
|
||||||
this.deleteActivity = deleteActivity;
|
|
||||||
this.trackIds = trackIds;
|
|
||||||
context = deleteActivity.getApplicationContext();
|
|
||||||
completed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the current activity associated with this AyncTask.
|
|
||||||
*
|
|
||||||
* @param deleteActivity the current activity, can be null
|
|
||||||
*/
|
|
||||||
public void setActivity(TrackDeleteActivity deleteActivity) {
|
|
||||||
this.deleteActivity = deleteActivity;
|
|
||||||
if (completed && deleteActivity != null) {
|
|
||||||
deleteActivity.onAsyncTaskCompleted();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
if (deleteActivity != null) {
|
|
||||||
deleteActivity.showProgressDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... params) {
|
|
||||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
|
|
||||||
|
|
||||||
if (trackIds.length == 1 && trackIds[0] == -1L) {
|
|
||||||
contentProviderUtils.deleteAllTracks(context);
|
|
||||||
} else {
|
|
||||||
for (long id : trackIds) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
contentProviderUtils.deleteTrack(context, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
completed = true;
|
|
||||||
if (deleteActivity != null) {
|
|
||||||
deleteActivity.onAsyncTaskCompleted();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,19 @@
|
|||||||
package de.dennisguse.opentracks;
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.util.ViewUtils;
|
||||||
|
|
||||||
public class HelpActivity extends AbstractActivity {
|
public class HelpActivity extends AbstractActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
ViewUtils.makeClickableLinks(findViewById(android.R.id.content));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getLayoutResId() {
|
protected int getLayoutResId() {
|
||||||
return R.layout.help;
|
return R.layout.help;
|
||||||
|
|||||||
@@ -48,32 +48,33 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark
|
|||||||
|
|
||||||
private static final String TAG = MarkerDetailActivity.class.getSimpleName();
|
private static final String TAG = MarkerDetailActivity.class.getSimpleName();
|
||||||
|
|
||||||
private List<Long> markerIds;
|
private List<Waypoint.Id> waypointIds;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle bundle) {
|
protected void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
long markerId = getIntent().getLongExtra(EXTRA_MARKER_ID, -1L);
|
Waypoint.Id waypointId = getIntent().getParcelableExtra(EXTRA_MARKER_ID);
|
||||||
if (markerId == -1L) {
|
if (waypointId == null) {
|
||||||
Log.d(TAG, "invalid marker id");
|
Log.d(TAG, "invalid marker id");
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
|
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
|
||||||
Waypoint waypoint = contentProviderUtils.getWaypoint(markerId);
|
Waypoint waypoint = contentProviderUtils.getWaypoint(waypointId);
|
||||||
|
|
||||||
markerIds = new ArrayList<>();
|
waypointIds = new ArrayList<>();
|
||||||
int markerIndex = -1;
|
int markerIndex = -1;
|
||||||
|
|
||||||
try (Cursor cursor = contentProviderUtils.getWaypointCursor(waypoint.getTrackId(), -1L, -1)) {
|
//TODO Load only waypointIds, not the whole waypoint
|
||||||
|
try (Cursor cursor = contentProviderUtils.getWaypointCursor(waypoint.getTrackId(), null, -1)) {
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
for (int i = 0; i < cursor.getCount(); i++) {
|
for (int i = 0; i < cursor.getCount(); i++) {
|
||||||
Waypoint currentMarker = contentProviderUtils.createWaypoint(cursor);
|
Waypoint currentMarker = contentProviderUtils.createWaypoint(cursor);
|
||||||
markerIds.add(currentMarker.getId());
|
waypointIds.add(currentMarker.getId());
|
||||||
if (currentMarker.getId() == markerId) {
|
if (waypointId.equals(currentMarker.getId())) {
|
||||||
markerIndex = markerIds.size() - 1;
|
markerIndex = waypointIds.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.moveToNext();
|
cursor.moveToNext();
|
||||||
@@ -109,12 +110,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeleteMarkerDone() {
|
public void onDeleteMarkerDone() {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(this::finish);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,13 +121,13 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark
|
|||||||
private class MarkerDetailPagerAdapter extends FragmentStatePagerAdapter {
|
private class MarkerDetailPagerAdapter extends FragmentStatePagerAdapter {
|
||||||
|
|
||||||
MarkerDetailPagerAdapter(FragmentManager fragmentManager) {
|
MarkerDetailPagerAdapter(FragmentManager fragmentManager) {
|
||||||
super(fragmentManager);
|
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public Fragment getItem(int position) {
|
public Fragment getItem(int position) {
|
||||||
return MarkerDetailFragment.newInstance(markerIds.get(position));
|
return MarkerDetailFragment.newInstance(waypointIds.get(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -142,7 +138,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return markerIds.size();
|
return waypointIds.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,6 @@ import android.util.Pair;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.AutoCompleteTextView;
|
import android.widget.AutoCompleteTextView;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@@ -43,6 +42,7 @@ import java.io.File;
|
|||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.Waypoint;
|
import de.dennisguse.opentracks.content.data.Waypoint;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
@@ -59,13 +59,14 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
public static final String EXTRA_TRACK_ID = "track_id";
|
public static final String EXTRA_TRACK_ID = "track_id";
|
||||||
public static final String EXTRA_MARKER_ID = "marker_id";
|
public static final String EXTRA_MARKER_ID = "marker_id";
|
||||||
|
|
||||||
|
private static final String BUNDLE_PHOTO_URI = "photo_uri";
|
||||||
|
|
||||||
private static final int CAMERA_REQUEST_CODE = 5;
|
private static final int CAMERA_REQUEST_CODE = 5;
|
||||||
private static final int GALLERY_IMG_REQUEST_CODE = 7;
|
private static final int GALLERY_IMG_REQUEST_CODE = 7;
|
||||||
|
|
||||||
private static final String TAG = MarkerEditActivity.class.getSimpleName();
|
private static final String TAG = MarkerEditActivity.class.getSimpleName();
|
||||||
private long trackId;
|
private Track.Id trackId;
|
||||||
private long markerId;
|
private TrackRecordingServiceConnection trackRecordingServiceConnection = new TrackRecordingServiceConnection();
|
||||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
|
||||||
private Waypoint waypoint;
|
private Waypoint waypoint;
|
||||||
|
|
||||||
private MenuItem insertPhotoMenuItem;
|
private MenuItem insertPhotoMenuItem;
|
||||||
@@ -80,15 +81,13 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
private EditText waypointDescription;
|
private EditText waypointDescription;
|
||||||
private ImageView waypointPhoto;
|
private ImageView waypointPhoto;
|
||||||
private ImageView waypointDeletePhotoBtn;
|
private ImageView waypointDeletePhotoBtn;
|
||||||
private Button done;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle bundle) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L);
|
trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID);
|
||||||
markerId = getIntent().getLongExtra(EXTRA_MARKER_ID, -1L);
|
Waypoint.Id waypointId = getIntent().getParcelableExtra(EXTRA_MARKER_ID);
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(null);
|
|
||||||
|
|
||||||
hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
|
hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
|
||||||
|
|
||||||
@@ -101,26 +100,67 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
waypointPhoto = findViewById(R.id.marker_edit_waypoint_photo);
|
waypointPhoto = findViewById(R.id.marker_edit_waypoint_photo);
|
||||||
|
|
||||||
waypointDeletePhotoBtn = findViewById(R.id.marker_edit_waypoint_photo_delete);
|
waypointDeletePhotoBtn = findViewById(R.id.marker_edit_waypoint_photo_delete);
|
||||||
waypointDeletePhotoBtn.setOnClickListener(new OnClickListener() {
|
waypointDeletePhotoBtn.setOnClickListener(v -> {
|
||||||
@Override
|
if (waypoint != null && waypoint.hasPhoto()) {
|
||||||
public void onClick(View v) {
|
waypoint.setPhotoUrl(null);
|
||||||
if (waypoint != null && waypoint.hasPhoto())
|
|
||||||
waypoint.setPhotoUrl(null);
|
|
||||||
waypointPhoto.setImageBitmap(null);
|
|
||||||
photoUri = null;
|
|
||||||
hideAndShowOptions();
|
|
||||||
}
|
}
|
||||||
|
waypointPhoto.setImageBitmap(null);
|
||||||
|
photoUri = null;
|
||||||
|
hideAndShowOptions();
|
||||||
});
|
});
|
||||||
|
|
||||||
Button cancel = findViewById(R.id.marker_edit_cancel);
|
Button cancel = findViewById(R.id.marker_edit_cancel);
|
||||||
cancel.setOnClickListener(new OnClickListener() {
|
cancel.setOnClickListener(v -> finish());
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
final boolean isNewMarker = waypointId == null;
|
||||||
finish();
|
|
||||||
|
setTitle(isNewMarker ? R.string.menu_insert_marker : R.string.menu_edit);
|
||||||
|
Button done = findViewById(R.id.marker_edit_done);
|
||||||
|
done.setText(isNewMarker ? R.string.generic_add : R.string.generic_save);
|
||||||
|
done.setOnClickListener(v -> {
|
||||||
|
if (isNewMarker) {
|
||||||
|
addMarker();
|
||||||
|
} else {
|
||||||
|
saveMarker();
|
||||||
}
|
}
|
||||||
|
finish();
|
||||||
});
|
});
|
||||||
done = findViewById(R.id.marker_edit_done);
|
|
||||||
updateUiByMarkerId();
|
if (isNewMarker) {
|
||||||
|
int nextWaypointNumber = trackId == null ? -1 : new ContentProviderUtils(this).getNextWaypointNumber(trackId);
|
||||||
|
if (nextWaypointNumber == -1) {
|
||||||
|
nextWaypointNumber = 0;
|
||||||
|
}
|
||||||
|
waypointName.setText(getString(R.string.marker_name_format, nextWaypointNumber));
|
||||||
|
waypointName.selectAll();
|
||||||
|
waypointMarkerType.setText("");
|
||||||
|
waypointDescription.setText("");
|
||||||
|
} else {
|
||||||
|
waypoint = new ContentProviderUtils(this).getWaypoint(waypointId);
|
||||||
|
if (waypoint == null) {
|
||||||
|
Log.d(TAG, "waypoint is null");
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
waypointName.setText(waypoint.getName());
|
||||||
|
waypointMarkerType.setText(waypoint.getCategory());
|
||||||
|
waypointDescription.setText(waypoint.getDescription());
|
||||||
|
if (waypoint.hasPhoto()) {
|
||||||
|
photoUri = waypoint.getPhotoURI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
photoUri = savedInstanceState.getParcelable(BUNDLE_PHOTO_URI);
|
||||||
|
if (waypoint != null) {
|
||||||
|
waypoint.setPhotoUrl(photoUri != null ? photoUri.toString() : null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (photoUri != null) {
|
||||||
|
setWaypointImageView(photoUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideAndShowOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -129,6 +169,12 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
trackRecordingServiceConnection.startConnection(this);
|
trackRecordingServiceConnection.startConnection(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
outState.putParcelable(BUNDLE_PHOTO_URI, photoUri);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
@@ -198,54 +244,6 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the UI based on the marker id.
|
|
||||||
*/
|
|
||||||
private void updateUiByMarkerId() {
|
|
||||||
final boolean newMarker = markerId == -1L;
|
|
||||||
|
|
||||||
setTitle(newMarker ? R.string.menu_insert_marker : R.string.menu_edit);
|
|
||||||
done.setText(newMarker ? R.string.generic_add : R.string.generic_save);
|
|
||||||
done.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (newMarker) {
|
|
||||||
addMarker();
|
|
||||||
} else {
|
|
||||||
saveMarker();
|
|
||||||
}
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (newMarker) {
|
|
||||||
int nextWaypointNumber = trackId == -1L ? -1 : new ContentProviderUtils(this).getNextWaypointNumber(trackId);
|
|
||||||
if (nextWaypointNumber == -1) {
|
|
||||||
nextWaypointNumber = 0;
|
|
||||||
}
|
|
||||||
waypointName.setText(getString(R.string.marker_name_format, nextWaypointNumber));
|
|
||||||
waypointName.selectAll();
|
|
||||||
waypointMarkerType.setText("");
|
|
||||||
waypointDescription.setText("");
|
|
||||||
} else {
|
|
||||||
waypoint = new ContentProviderUtils(this).getWaypoint(markerId);
|
|
||||||
if (waypoint == null) {
|
|
||||||
Log.d(TAG, "waypoint is null");
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
waypointName.setText(waypoint.getName());
|
|
||||||
waypointMarkerType.setText(waypoint.getCategory());
|
|
||||||
waypointDescription.setText(waypoint.getDescription());
|
|
||||||
if (waypoint.hasPhoto()) {
|
|
||||||
photoUri = waypoint.getPhotoURI();
|
|
||||||
setWaypointImageView(photoUri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hideAndShowOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks and hide/shows all buttons/options about marker photo options.
|
* Checks and hide/shows all buttons/options about marker photo options.
|
||||||
*
|
*
|
||||||
@@ -263,8 +261,8 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
/**
|
/**
|
||||||
* Returns the trackId. If trackId == -1 then get it from waypoint object.
|
* Returns the trackId. If trackId == -1 then get it from waypoint object.
|
||||||
*/
|
*/
|
||||||
private long getTrackId() {
|
private Track.Id getTrackId() {
|
||||||
return trackId == -1 ? waypoint.getTrackId() : trackId;
|
return trackId == null ? waypoint.getTrackId() : trackId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -272,13 +270,13 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
*
|
*
|
||||||
* @param uri the uri photo.
|
* @param uri the uri photo.
|
||||||
*/
|
*/
|
||||||
private void setWaypointImageView(Uri uri) {
|
private void setWaypointImageView(@NonNull Uri uri) {
|
||||||
try (ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "r")) {
|
try (ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "r")) {
|
||||||
FileDescriptor fd = pfd.getFileDescriptor();
|
FileDescriptor fd = pfd.getFileDescriptor();
|
||||||
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
|
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
|
||||||
waypointPhoto.setImageBitmap(bitmap);
|
waypointPhoto.setImageBitmap(bitmap);
|
||||||
hideAndShowOptions();
|
hideAndShowOptions();
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, e.getMessage());
|
Log.e(TAG, e.getMessage());
|
||||||
Toast.makeText(this, R.string.marker_add_photo_canceled, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.marker_add_photo_canceled, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
@@ -295,9 +293,6 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
startActivityForResult(intent, GALLERY_IMG_REQUEST_CODE);
|
startActivityForResult(intent, GALLERY_IMG_REQUEST_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a marker.
|
|
||||||
*/
|
|
||||||
private void addMarker() {
|
private void addMarker() {
|
||||||
trackRecordingServiceConnection.addMarker(this,
|
trackRecordingServiceConnection.addMarker(this,
|
||||||
waypointName.getText().toString(),
|
waypointName.getText().toString(),
|
||||||
@@ -306,9 +301,6 @@ public class MarkerEditActivity extends AbstractActivity {
|
|||||||
photoUri != null ? photoUri.toString() : null);
|
photoUri != null ? photoUri.toString() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves a marker.
|
|
||||||
*/
|
|
||||||
private void saveMarker() {
|
private void saveMarker() {
|
||||||
waypoint.setName(waypointName.getText().toString());
|
waypoint.setName(waypointName.getText().toString());
|
||||||
waypoint.setCategory(waypointMarkerType.getText().toString());
|
waypoint.setCategory(waypointMarkerType.getText().toString());
|
||||||
|
|||||||
@@ -26,18 +26,16 @@ import android.view.KeyEvent;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
||||||
import androidx.loader.app.LoaderManager;
|
import androidx.loader.app.LoaderManager;
|
||||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||||
import androidx.loader.content.CursorLoader;
|
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
|
import de.dennisguse.opentracks.content.data.Waypoint;
|
||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment;
|
import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment;
|
||||||
@@ -59,16 +57,11 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
|
|
||||||
private static final String TAG = MarkerListActivity.class.getSimpleName();
|
private static final String TAG = MarkerListActivity.class.getSimpleName();
|
||||||
|
|
||||||
private static final String[] PROJECTION = new String[]{WaypointsColumns._ID,
|
|
||||||
WaypointsColumns.NAME, WaypointsColumns.DESCRIPTION, WaypointsColumns.CATEGORY,
|
|
||||||
WaypointsColumns.TIME, WaypointsColumns.PHOTOURL,
|
|
||||||
WaypointsColumns.LATITUDE, WaypointsColumns.LONGITUDE};
|
|
||||||
|
|
||||||
private ContentProviderUtils contentProviderUtils;
|
private ContentProviderUtils contentProviderUtils;
|
||||||
|
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
private Track.Id recordingTrackId;
|
||||||
private boolean recordingTrackPaused;
|
private boolean recordingTrackPaused;
|
||||||
|
|
||||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||||
@@ -82,12 +75,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(MarkerListActivity.this);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(MarkerListActivity.this);
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(MarkerListActivity.this::invalidateOptionsMenu);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
MarkerListActivity.this.invalidateOptionsMenu();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -124,23 +112,20 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
|
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
|
||||||
long trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L);
|
Track.Id trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID);
|
||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||||
|
|
||||||
contentProviderUtils = new ContentProviderUtils(this);
|
contentProviderUtils = new ContentProviderUtils(this);
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||||
|
|
||||||
track = trackId != -1L ? contentProviderUtils.getTrack(trackId) : null;
|
track = trackId != null ? contentProviderUtils.getTrack(trackId) : null;
|
||||||
|
|
||||||
listView = findViewById(R.id.marker_list);
|
listView = findViewById(R.id.marker_list);
|
||||||
listView.setEmptyView(findViewById(R.id.marker_list_empty));
|
listView.setEmptyView(findViewById(R.id.marker_list_empty));
|
||||||
listView.setOnItemClickListener(new OnItemClickListener() {
|
listView.setOnItemClickListener((parent, view, position, id) -> {
|
||||||
@Override
|
Intent intent = IntentUtils.newIntent(MarkerListActivity.this, MarkerDetailActivity.class)
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
.putExtra(MarkerDetailActivity.EXTRA_MARKER_ID, new Waypoint.Id(id));
|
||||||
Intent intent = IntentUtils.newIntent(MarkerListActivity.this, MarkerDetailActivity.class)
|
startActivity(intent);
|
||||||
.putExtra(MarkerDetailActivity.EXTRA_MARKER_ID, id);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) {
|
resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) {
|
||||||
@Override
|
@Override
|
||||||
@@ -173,14 +158,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||||
if (track != null) {
|
return ContentProviderUtils.getWaypointsLoader(MarkerListActivity.this, track != null ? track.getId() : null);
|
||||||
return new CursorLoader(MarkerListActivity.this, WaypointsColumns.CONTENT_URI, PROJECTION,
|
|
||||||
WaypointsColumns.TRACKID + "=?",
|
|
||||||
new String[]{String.valueOf(track.getId())}, null);
|
|
||||||
} else {
|
|
||||||
return new CursorLoader(MarkerListActivity.this, WaypointsColumns.CONTENT_URI, PROJECTION,
|
|
||||||
null, null, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -233,7 +211,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
insertMarkerMenuItem.setVisible(track != null && track.getId() == recordingTrackId && !recordingTrackPaused);
|
insertMarkerMenuItem.setVisible(track != null && track.getId().equals(recordingTrackId) && !recordingTrackPaused);
|
||||||
return super.onPrepareOptionsMenu(menu);
|
return super.onPrepareOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,34 +229,38 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
/**
|
/**
|
||||||
* Handles a context item selection.
|
* Handles a context item selection.
|
||||||
*
|
*
|
||||||
* @param itemId the menu item id
|
* @param itemId the menu item id
|
||||||
* @param markerIds the marker ids
|
* @param longWaypointIds the marker ids
|
||||||
* @return true if handled.
|
* @return true if handled.
|
||||||
*/
|
*/
|
||||||
private boolean handleContextItem(int itemId, long[] markerIds) {
|
private boolean handleContextItem(int itemId, long... longWaypointIds) {
|
||||||
|
Waypoint.Id[] waypointIds = new Waypoint.Id[longWaypointIds.length];
|
||||||
|
for (int i = 0; i < longWaypointIds.length; i++) {
|
||||||
|
waypointIds[i] = new Waypoint.Id(longWaypointIds[i]);
|
||||||
|
}
|
||||||
|
|
||||||
Intent intent;
|
Intent intent;
|
||||||
switch (itemId) {
|
switch (itemId) {
|
||||||
case R.id.list_context_menu_show_on_map:
|
case R.id.list_context_menu_show_on_map:
|
||||||
if (markerIds.length == 1) {
|
if (waypointIds.length == 1) {
|
||||||
IntentUtils.showCoordinateOnMap(this, contentProviderUtils.getWaypoint(markerIds[0]));
|
IntentUtils.showCoordinateOnMap(this, contentProviderUtils.getWaypoint(waypointIds[0]));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_edit:
|
case R.id.list_context_menu_edit:
|
||||||
if (markerIds.length == 1) {
|
if (waypointIds.length == 1) {
|
||||||
intent = IntentUtils.newIntent(this, MarkerEditActivity.class)
|
intent = IntentUtils.newIntent(this, MarkerEditActivity.class)
|
||||||
.putExtra(MarkerEditActivity.EXTRA_MARKER_ID, markerIds[0]);
|
.putExtra(MarkerEditActivity.EXTRA_MARKER_ID, waypointIds[0]);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_delete:
|
case R.id.list_context_menu_delete:
|
||||||
if (markerIds.length > 1 && markerIds.length == listView.getCount()) {
|
if (waypointIds.length > 1 && waypointIds.length == listView.getCount()) {
|
||||||
markerIds = new long[]{-1L};
|
waypointIds = null;
|
||||||
}
|
}
|
||||||
DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), markerIds);
|
DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), waypointIds);
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_select_all:
|
case R.id.list_context_menu_select_all:
|
||||||
int size = listView.getCount();
|
for (int i = 0; i < listView.getCount(); i++) {
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
listView.setItemChecked(i, true);
|
listView.setItemChecked(i, true);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ import android.view.KeyEvent;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
@@ -99,7 +97,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
|
|
||||||
private boolean metricUnits = true;
|
private boolean metricUnits = true;
|
||||||
|
|
||||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
private Track.Id recordingTrackId;
|
||||||
|
|
||||||
private boolean recordingTrackPaused;
|
private boolean recordingTrackPaused;
|
||||||
|
|
||||||
@@ -153,12 +151,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(SearchListActivity.this);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(SearchListActivity.this);
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(() -> arrayAdapter.notifyDataSetChanged());
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
arrayAdapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -172,7 +165,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
|
|
||||||
contentProviderUtils = new ContentProviderUtils(this);
|
contentProviderUtils = new ContentProviderUtils(this);
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(null);
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection();
|
||||||
searchEngine = new SearchEngine(contentProviderUtils);
|
searchEngine = new SearchEngine(contentProviderUtils);
|
||||||
|
|
||||||
arrayAdapter = new ArrayAdapter<Map<String, Object>>(this, R.layout.list_item, R.id.list_item_name) {
|
arrayAdapter = new ArrayAdapter<Map<String, Object>>(this, R.layout.list_item, R.id.list_item_name) {
|
||||||
@@ -208,20 +201,17 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
ListView listView = findViewById(R.id.search_list);
|
ListView listView = findViewById(R.id.search_list);
|
||||||
listView.setAdapter(arrayAdapter);
|
listView.setAdapter(arrayAdapter);
|
||||||
listView.setEmptyView(findViewById(R.id.search_list_empty));
|
listView.setEmptyView(findViewById(R.id.search_list_empty));
|
||||||
listView.setOnItemClickListener(new OnItemClickListener() {
|
listView.setOnItemClickListener((parent, view, position, id) -> {
|
||||||
@Override
|
Map<String, Object> item = arrayAdapter.getItem(position);
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
Track.Id trackId = (Track.Id) item.get(TRACK_ID_FIELD);
|
||||||
Map<String, Object> item = arrayAdapter.getItem(position);
|
Long markerId = (Long) item.get(MARKER_ID_FIELD);
|
||||||
Long trackId = (Long) item.get(TRACK_ID_FIELD);
|
Intent intent = IntentUtils.newIntent(SearchListActivity.this, TrackRecordedActivity.class);
|
||||||
Long markerId = (Long) item.get(MARKER_ID_FIELD);
|
if (markerId != null) {
|
||||||
Intent intent = IntentUtils.newIntent(SearchListActivity.this, TrackDetailActivity.class);
|
intent = intent.putExtra(TrackRecordedActivity.EXTRA_MARKER_ID, markerId);
|
||||||
if (markerId != null) {
|
} else {
|
||||||
intent = intent.putExtra(TrackDetailActivity.EXTRA_MARKER_ID, markerId);
|
intent = intent.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId);
|
||||||
} else {
|
|
||||||
intent = intent.putExtra(TrackDetailActivity.EXTRA_TRACK_ID, trackId);
|
|
||||||
}
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
}
|
||||||
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
|
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
|
||||||
handleIntent(getIntent());
|
handleIntent(getIntent());
|
||||||
@@ -280,22 +270,22 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Map<String, Object> item = arrayAdapter.getItem(positions[0]);
|
Map<String, Object> item = arrayAdapter.getItem(positions[0]);
|
||||||
Long trackId = (Long) item.get(TRACK_ID_FIELD);
|
Track.Id trackId = (Track.Id) item.get(TRACK_ID_FIELD);
|
||||||
Long markerId = (Long) item.get(MARKER_ID_FIELD);
|
Waypoint.Id waypointId = (Waypoint.Id) item.get(MARKER_ID_FIELD);
|
||||||
Intent intent;
|
Intent intent;
|
||||||
switch (itemId) {
|
switch (itemId) {
|
||||||
case R.id.list_context_menu_show_on_map:
|
case R.id.list_context_menu_show_on_map:
|
||||||
IntentUtils.showCoordinateOnMap(this, (double) item.get(MARKER_LATITUDE_FIELD), (double) item.get(MARKER_LONGITUDE_FIELD), item.get(NAME_FIELD) + "");
|
IntentUtils.showCoordinateOnMap(this, (double) item.get(MARKER_LATITUDE_FIELD), (double) item.get(MARKER_LONGITUDE_FIELD), item.get(NAME_FIELD) + "");
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_share:
|
case R.id.list_context_menu_share:
|
||||||
intent = IntentUtils.newShareFileIntent(this, new long[]{trackId});
|
intent = IntentUtils.newShareFileIntent(this, trackId);
|
||||||
intent = Intent.createChooser(intent, null);
|
intent = Intent.createChooser(intent, null);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_edit:
|
case R.id.list_context_menu_edit:
|
||||||
if (markerId != null) {
|
if (waypointId != null) {
|
||||||
intent = IntentUtils.newIntent(this, MarkerEditActivity.class)
|
intent = IntentUtils.newIntent(this, MarkerEditActivity.class)
|
||||||
.putExtra(MarkerEditActivity.EXTRA_MARKER_ID, markerId);
|
.putExtra(MarkerEditActivity.EXTRA_MARKER_ID, waypointId);
|
||||||
} else {
|
} else {
|
||||||
intent = IntentUtils.newIntent(this, TrackEditActivity.class)
|
intent = IntentUtils.newIntent(this, TrackEditActivity.class)
|
||||||
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
||||||
@@ -306,10 +296,10 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
finish();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_delete:
|
case R.id.list_context_menu_delete:
|
||||||
if (markerId != null) {
|
if (waypointId != null) {
|
||||||
DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), new long[]{markerId});
|
DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), waypointId);
|
||||||
} else {
|
} else {
|
||||||
deleteTracks(new long[]{trackId});
|
deleteTracks(trackId);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@@ -341,17 +331,14 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
* @param textQuery the query
|
* @param textQuery the query
|
||||||
*/
|
*/
|
||||||
private void doSearch(String textQuery) {
|
private void doSearch(String textQuery) {
|
||||||
SearchQuery query = new SearchQuery(textQuery, null, -1L, System.currentTimeMillis());
|
SearchQuery query = new SearchQuery(textQuery, null, null, System.currentTimeMillis());
|
||||||
SortedSet<ScoredResult> scoredResults = searchEngine.search(query);
|
SortedSet<ScoredResult> scoredResults = searchEngine.search(query);
|
||||||
final List<Map<String, Object>> displayResults = prepareResultsforDisplay(scoredResults);
|
final List<Map<String, Object>> displayResults = prepareResultsforDisplay(scoredResults);
|
||||||
|
|
||||||
// Use the UI thread to display the results
|
// Use the UI thread to display the results
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(() -> {
|
||||||
@Override
|
arrayAdapter.clear();
|
||||||
public void run() {
|
arrayAdapter.addAll(displayResults);
|
||||||
arrayAdapter.clear();
|
|
||||||
arrayAdapter.addAll(displayResults);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,8 +372,8 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
|
|
||||||
//TODO: It may be more appropriate to obtain the track name as a join in the retrieval phase of the searchable.
|
//TODO: It may be more appropriate to obtain the track name as a join in the retrieval phase of the searchable.
|
||||||
String trackName = null;
|
String trackName = null;
|
||||||
long trackId = waypoint.getTrackId();
|
Track.Id trackId = waypoint.getTrackId();
|
||||||
if (trackId != -1L) {
|
if (!trackId.isValid()) {
|
||||||
Track track = contentProviderUtils.getTrack(trackId);
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
if (track != null) {
|
if (track != null) {
|
||||||
trackName = track.getName();
|
trackName = track.getName();
|
||||||
@@ -448,12 +435,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeleteMarkerDone() {
|
public void onDeleteMarkerDone() {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(() -> handleIntent(getIntent()));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
handleIntent(getIntent());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -463,11 +445,6 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDeleted() {
|
protected void onDeleted() {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(() -> handleIntent(getIntent()));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
handleIntent(getIntent());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
|
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
||||||
|
import de.dennisguse.opentracks.content.provider.ShareContentProvider;
|
||||||
|
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||||
|
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to convert IntentDashboardUtils.startDashboard-requests into {@link TrackFileFormat}.
|
||||||
|
*/
|
||||||
|
public abstract class ShowOnMapProxyActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private final TrackFileFormat trackFileFormat;
|
||||||
|
|
||||||
|
protected ShowOnMapProxyActivity(TrackFileFormat trackFileFormat) {
|
||||||
|
this.trackFileFormat = trackFileFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
Set<Track.Id> trackIds = IntentDashboardUtils.extractTrackIdsFromIntent(getIntent());
|
||||||
|
|
||||||
|
showTrackTrackfileFormat(this, trackFileFormat, trackIds);
|
||||||
|
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send intent to show tracks on a map (needs an another app) as KMZ.
|
||||||
|
*
|
||||||
|
* @param context the context
|
||||||
|
* @param trackIds the track ids
|
||||||
|
*/
|
||||||
|
private static void showTrackTrackfileFormat(Context context, TrackFileFormat trackFileFormat, Set<Track.Id> trackIds) {
|
||||||
|
if (trackIds.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
intent.putExtra(TrackPointsColumns.TRACKID, trackIds.toArray(new Track.Id[0])[0]);
|
||||||
|
Pair<Uri, String> uriAndMime = ShareContentProvider.createURI(trackIds, "SharingTrack", trackFileFormat);
|
||||||
|
intent.setDataAndType(uriAndMime.first, uriAndMime.second);
|
||||||
|
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
|
||||||
|
context.startActivity(Intent.createChooser(intent, context.getString(R.string.open_track_as_trackfileformat, trackFileFormat.getExtension())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class KMZ extends ShowOnMapProxyActivity {
|
||||||
|
public KMZ() {
|
||||||
|
super(TrackFileFormat.KMZ_WITH_TRACKDETAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GPX extends ShowOnMapProxyActivity {
|
||||||
|
public GPX() {
|
||||||
|
super(TrackFileFormat.GPX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import android.app.Application;
|
|||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,7 +27,16 @@ public class Startup extends Application {
|
|||||||
|
|
||||||
//Set default values of preferences on first start.
|
//Set default values of preferences on first start.
|
||||||
PreferencesUtils.resetPreferences(this, false);
|
PreferencesUtils.resetPreferences(this, false);
|
||||||
|
if (PreferencesUtils.getString(this, R.string.stats_units_key, "").equals("")) {
|
||||||
|
String statsUnits = getString(Locale.US.equals(Locale.getDefault()) ? R.string.stats_units_imperial : R.string.stats_units_metric);
|
||||||
|
PreferencesUtils.setString(this, R.string.stats_units_key, statsUnits);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Workaround to reset recordingTrackId on app startup as the TrackRecordingService (likely) crashed.
|
||||||
|
if (PreferencesUtils.isRecording(this)) {
|
||||||
|
Log.e(TAG, "Reset recordingTrackId; likely the TrackRecordingService crashed.");
|
||||||
|
PreferencesUtils.setLong(this, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
//In debug builds: show thread and VM warnings.
|
//In debug builds: show thread and VM warnings.
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.TrackDataHub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for communication between activities that use {@link de.dennisguse.opentracks.content.TrackDataHub} and their fragments that need thi data hub.
|
||||||
|
*/
|
||||||
|
public interface TrackActivityDataHubInterface {
|
||||||
|
TrackDataHub getTrackDataHub();
|
||||||
|
}
|
||||||
@@ -16,15 +16,24 @@
|
|||||||
|
|
||||||
package de.dennisguse.opentracks;
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||||
|
import de.dennisguse.opentracks.util.ActivityUtils;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
import de.dennisguse.opentracks.util.UnitConversions;
|
import de.dennisguse.opentracks.util.UnitConversions;
|
||||||
|
|
||||||
@@ -46,12 +55,12 @@ public class TrackController {
|
|||||||
private final ImageButton recordImageButton;
|
private final ImageButton recordImageButton;
|
||||||
private final ImageButton stopImageButton;
|
private final ImageButton stopImageButton;
|
||||||
private final boolean alwaysShow;
|
private final boolean alwaysShow;
|
||||||
|
private ButtonDelay buttonDelay;
|
||||||
|
|
||||||
private boolean isRecording;
|
private boolean isRecording;
|
||||||
private boolean isPaused;
|
private boolean isPaused;
|
||||||
private long totalTime = 0;
|
private long totalTime = 0;
|
||||||
|
|
||||||
// the timestamp for the toal time
|
|
||||||
private long totalTimeTimestamp = 0;
|
private long totalTimeTimestamp = 0;
|
||||||
|
|
||||||
private boolean isResumed = false;
|
private boolean isResumed = false;
|
||||||
@@ -66,6 +75,7 @@ public class TrackController {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
TrackController(Activity activity, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean alwaysShow, OnClickListener recordListener, OnClickListener stopListener) {
|
TrackController(Activity activity, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean alwaysShow, OnClickListener recordListener, OnClickListener stopListener) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
this.trackRecordingServiceConnection = trackRecordingServiceConnection;
|
this.trackRecordingServiceConnection = trackRecordingServiceConnection;
|
||||||
@@ -76,10 +86,91 @@ public class TrackController {
|
|||||||
totalTimeTextView = activity.findViewById(R.id.track_controller_total_time);
|
totalTimeTextView = activity.findViewById(R.id.track_controller_total_time);
|
||||||
|
|
||||||
recordImageButton = activity.findViewById(R.id.track_controller_record);
|
recordImageButton = activity.findViewById(R.id.track_controller_record);
|
||||||
recordImageButton.setOnClickListener(recordListener);
|
recordImageButton.setOnTouchListener((view, motionEvent) -> onRecordTouch(activity, recordListener, motionEvent));
|
||||||
|
|
||||||
stopImageButton = activity.findViewById(R.id.track_controller_stop);
|
stopImageButton = activity.findViewById(R.id.track_controller_stop);
|
||||||
stopImageButton.setOnClickListener(stopListener);
|
stopImageButton.setOnTouchListener((view, motionEvent) -> onStopTouch(activity, stopListener, motionEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onRecordTouch(final Activity activity, final OnClickListener recordListener, final MotionEvent motionEvent) {
|
||||||
|
if (isRecording && !isPaused) {
|
||||||
|
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
|
buttonDelay = new ButtonDelay(activity, recordImageButton, R.drawable.ic_button_pause_anim, R.string.hold_to_pause, recordListener);
|
||||||
|
new Thread(buttonDelay).start();
|
||||||
|
return true;
|
||||||
|
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP ) {
|
||||||
|
recordImageButton.setImageResource(R.drawable.ic_button_pause);
|
||||||
|
if (buttonDelay != null) {
|
||||||
|
buttonDelay.canceled = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
|
recordListener.onClick(null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onStopTouch(final Activity activity, final OnClickListener stopListener, final MotionEvent motionEvent) {
|
||||||
|
if (isRecording) {
|
||||||
|
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
|
buttonDelay = new ButtonDelay(activity, stopImageButton, R.drawable.ic_button_stop_anim, R.string.hold_to_stop, stopListener);
|
||||||
|
new Thread(buttonDelay).start();
|
||||||
|
return true;
|
||||||
|
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP ) {
|
||||||
|
stopImageButton.setImageResource(R.drawable.ic_button_stop);
|
||||||
|
if (buttonDelay != null) {
|
||||||
|
buttonDelay.canceled = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ButtonDelay implements Runnable {
|
||||||
|
|
||||||
|
private boolean canceled = false;
|
||||||
|
|
||||||
|
private final ImageButton imageButton;
|
||||||
|
private final Activity activity;
|
||||||
|
private final OnClickListener clickListener;
|
||||||
|
private final int delayMillis;
|
||||||
|
private final Drawable drawable;
|
||||||
|
private final int delayMessageId;
|
||||||
|
|
||||||
|
private ButtonDelay(final Activity activity, final ImageButton imageButton, final int animDrawableId, final int delayMessageId, final OnClickListener clickListener) {
|
||||||
|
this.activity = activity;
|
||||||
|
this.clickListener = clickListener;
|
||||||
|
this.delayMillis = activity.getResources().getInteger(R.integer.buttonDelayMillis);
|
||||||
|
this.imageButton = imageButton;
|
||||||
|
this.drawable = ContextCompat.getDrawable(activity, animDrawableId);
|
||||||
|
this.delayMessageId = delayMessageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
activity.runOnUiThread(()->{
|
||||||
|
imageButton.setImageDrawable(drawable);
|
||||||
|
if (drawable instanceof AnimatedVectorDrawable) {
|
||||||
|
((AnimatedVectorDrawable) drawable).start();
|
||||||
|
}
|
||||||
|
ActivityUtils.vibrate(activity, 150);
|
||||||
|
ActivityUtils.toast(activity, delayMessageId, Toast.LENGTH_SHORT, Gravity.TOP);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(delayMillis);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
if (!canceled) {
|
||||||
|
activity.runOnUiThread(()-> {
|
||||||
|
clickListener.onClick(null);
|
||||||
|
ActivityUtils.vibrate(activity, 1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(boolean recording, boolean paused) {
|
public void update(boolean recording, boolean paused) {
|
||||||
@@ -96,10 +187,10 @@ public class TrackController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
recordImageButton.setImageResource(isRecording && !isPaused ? R.drawable.button_pause : R.drawable.button_record);
|
recordImageButton.setImageResource(isRecording && !isPaused ? R.drawable.ic_button_pause : R.drawable.button_record);
|
||||||
recordImageButton.setContentDescription(activity.getString(isRecording && !isPaused ? R.string.image_pause : R.string.image_record));
|
recordImageButton.setContentDescription(activity.getString(isRecording && !isPaused ? R.string.image_pause : R.string.image_record));
|
||||||
|
|
||||||
stopImageButton.setImageResource(isRecording ? R.drawable.button_stop : R.drawable.ic_button_stop_disabled);
|
stopImageButton.setImageResource(isRecording ? R.drawable.ic_button_stop : R.drawable.ic_button_stop_disabled);
|
||||||
stopImageButton.setEnabled(isRecording);
|
stopImageButton.setEnabled(isRecording);
|
||||||
|
|
||||||
statusTextView.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
statusTextView.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
|||||||
@@ -16,26 +16,29 @@
|
|||||||
|
|
||||||
package de.dennisguse.opentracks;
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.util.DialogUtils;
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
|
import de.dennisguse.opentracks.util.SystemUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity for delete tracks.
|
* An activity for deleting tracks.
|
||||||
*
|
*
|
||||||
* @author Jimmy Shih
|
* @author Jimmy Shih
|
||||||
*/
|
*/
|
||||||
public class TrackDeleteActivity extends Activity {
|
public class TrackDeleteActivity extends AbstractActivity {
|
||||||
|
|
||||||
public static final String EXTRA_TRACK_IDS = "track_ids";
|
public static final String EXTRA_TRACK_IDS = "track_ids";
|
||||||
|
|
||||||
private static final int DIALOG_PROGRESS_ID = 0;
|
private List<Track.Id> trackIds;
|
||||||
|
|
||||||
private DeleteAsyncTask deleteAsyncTask;
|
private Thread deleteThread;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -44,53 +47,48 @@ public class TrackDeleteActivity extends Activity {
|
|||||||
setResult(RESULT_CANCELED);
|
setResult(RESULT_CANCELED);
|
||||||
|
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
long[] trackIds = intent.getLongArrayExtra(EXTRA_TRACK_IDS);
|
trackIds = intent.getParcelableArrayListExtra(EXTRA_TRACK_IDS);
|
||||||
|
deleteThread = new Thread(() -> {
|
||||||
|
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(TrackDeleteActivity.this);
|
||||||
|
|
||||||
Object retained = getLastNonConfigurationInstance();
|
PowerManager.WakeLock wakeLock = SystemUtils.acquireWakeLock(TrackDeleteActivity.this, null);
|
||||||
if (retained instanceof DeleteAsyncTask) {
|
|
||||||
deleteAsyncTask = (DeleteAsyncTask) retained;
|
for (Track.Id id : trackIds) {
|
||||||
deleteAsyncTask.setActivity(this);
|
if (Thread.interrupted()) {
|
||||||
} else {
|
break;
|
||||||
deleteAsyncTask = new DeleteAsyncTask(this, trackIds);
|
}
|
||||||
deleteAsyncTask.execute();
|
contentProviderUtils.deleteTrack(TrackDeleteActivity.this, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wakeLock = SystemUtils.releaseWakeLock(wakeLock);
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
runOnUiThread(TrackDeleteActivity.this::onAsyncTaskCompleted);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object onRetainNonConfigurationInstance() {
|
protected void onStart() {
|
||||||
deleteAsyncTask.setActivity(null);
|
super.onStart();
|
||||||
return deleteAsyncTask;
|
deleteThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Dialog onCreateDialog(int id) {
|
protected void onStop() {
|
||||||
if (id != DIALOG_PROGRESS_ID) {
|
super.onStop();
|
||||||
return null;
|
deleteThread.interrupt();
|
||||||
}
|
}
|
||||||
return DialogUtils.createSpinnerProgressDialog(
|
|
||||||
this, R.string.track_delete_progress_message, new DialogInterface.OnCancelListener() {
|
@Override
|
||||||
@Override
|
protected int getLayoutResId() {
|
||||||
public void onCancel(DialogInterface dialog) {
|
return R.layout.track_delete;
|
||||||
deleteAsyncTask.cancel(true);
|
|
||||||
dialog.dismiss();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes when the associated AsyncTask completes.
|
|
||||||
*/
|
|
||||||
public void onAsyncTaskCompleted() {
|
public void onAsyncTaskCompleted() {
|
||||||
removeDialog(DIALOG_PROGRESS_ID);
|
findViewById(R.id.progressbar).setVisibility(View.INVISIBLE);
|
||||||
setResult(RESULT_OK);
|
setResult(RESULT_OK);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the progress dialog.
|
|
||||||
*/
|
|
||||||
public void showProgressDialog() {
|
|
||||||
showDialog(DIALOG_PROGRESS_ID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import android.util.Log;
|
|||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.AutoCompleteTextView;
|
import android.widget.AutoCompleteTextView;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@@ -65,9 +64,9 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
|
|||||||
protected void onCreate(Bundle bundle) {
|
protected void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(null);
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection();
|
||||||
long trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L);
|
Track.Id trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID);
|
||||||
if (trackId == -1L) {
|
if (!trackId.isValid()) {
|
||||||
Log.e(TAG, "invalid trackId");
|
Log.e(TAG, "invalid trackId");
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
@@ -89,20 +88,12 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
|
|||||||
|
|
||||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.activity_types, android.R.layout.simple_dropdown_item_1line);
|
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.activity_types, android.R.layout.simple_dropdown_item_1line);
|
||||||
activityType.setAdapter(adapter);
|
activityType.setAdapter(adapter);
|
||||||
activityType.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
activityType.setOnItemClickListener((parent, view, position, id) -> setActivityTypeIcon(TrackIconUtils.getIconValue(
|
||||||
@Override
|
TrackEditActivity.this, (String) activityType.getAdapter().getItem(position))));
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
activityType.setOnFocusChangeListener((v, hasFocus) -> {
|
||||||
|
if (!hasFocus) {
|
||||||
setActivityTypeIcon(TrackIconUtils.getIconValue(
|
setActivityTypeIcon(TrackIconUtils.getIconValue(
|
||||||
TrackEditActivity.this, (String) activityType.getAdapter().getItem(position)));
|
TrackEditActivity.this, activityType.getText().toString()));
|
||||||
}
|
|
||||||
});
|
|
||||||
activityType.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View v, boolean hasFocus) {
|
|
||||||
if (!hasFocus) {
|
|
||||||
setActivityTypeIcon(TrackIconUtils.getIconValue(
|
|
||||||
TrackEditActivity.this, activityType.getText().toString()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -116,37 +107,28 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
|
|||||||
|
|
||||||
activityTypeIcon = findViewById(R.id.track_edit_activity_type_icon);
|
activityTypeIcon = findViewById(R.id.track_edit_activity_type_icon);
|
||||||
activityTypeIcon.setAdapter(TrackIconUtils.getIconSpinnerAdapter(this, iconValue));
|
activityTypeIcon.setAdapter(TrackIconUtils.getIconSpinnerAdapter(this, iconValue));
|
||||||
activityTypeIcon.setOnTouchListener(new View.OnTouchListener() {
|
activityTypeIcon.setOnTouchListener((v, event) -> {
|
||||||
@Override
|
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), activityType.getText().toString());
|
||||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
|
||||||
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), activityType.getText().toString());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
activityTypeIcon.setOnKeyListener(new View.OnKeyListener() {
|
activityTypeIcon.setOnKeyListener((v, keyCode, event) -> {
|
||||||
@Override
|
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
|
||||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), activityType.getText().toString());
|
||||||
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
|
|
||||||
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), activityType.getText().toString());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
description = findViewById(R.id.track_edit_description);
|
description = findViewById(R.id.track_edit_description);
|
||||||
description.setText(track.getDescription());
|
description.setText(track.getDescription());
|
||||||
|
|
||||||
Button saveButton = findViewById(R.id.track_edit_save);
|
Button saveButton = findViewById(R.id.track_edit_save);
|
||||||
saveButton.setOnClickListener(new View.OnClickListener() {
|
saveButton.setOnClickListener(v -> {
|
||||||
@Override
|
TrackUtils.updateTrack(TrackEditActivity.this, track, nameEditText.getText().toString(),
|
||||||
public void onClick(View v) {
|
activityType.getText().toString(), description.getText().toString(),
|
||||||
TrackUtils.updateTrack(TrackEditActivity.this, track, nameEditText.getText().toString(),
|
contentProviderUtils);
|
||||||
activityType.getText().toString(), description.getText().toString(),
|
finish();
|
||||||
contentProviderUtils);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Button cancel = findViewById(R.id.track_edit_cancel);
|
Button cancel = findViewById(R.id.track_edit_cancel);
|
||||||
@@ -155,12 +137,7 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
|
|||||||
cancel.setVisibility(View.GONE);
|
cancel.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
setTitle(R.string.menu_edit);
|
setTitle(R.string.menu_edit);
|
||||||
cancel.setOnClickListener(new View.OnClickListener() {
|
cancel.setOnClickListener(v -> finish());
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
cancel.setVisibility(View.VISIBLE);
|
cancel.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.content.SharedPreferences;
|
|||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -33,8 +34,6 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@@ -44,25 +43,23 @@ import androidx.core.app.ActivityCompat;
|
|||||||
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
||||||
import androidx.loader.app.LoaderManager;
|
import androidx.loader.app.LoaderManager;
|
||||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||||
import androidx.loader.content.CursorLoader;
|
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
|
|
||||||
import java.util.Locale;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||||
|
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
import de.dennisguse.opentracks.util.ActivityUtils;
|
import de.dennisguse.opentracks.util.ActivityUtils;
|
||||||
|
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||||
import de.dennisguse.opentracks.util.IntentUtils;
|
import de.dennisguse.opentracks.util.IntentUtils;
|
||||||
import de.dennisguse.opentracks.util.ListItemUtils;
|
import de.dennisguse.opentracks.util.ListItemUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.ServiceUtils;
|
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity displaying a list of tracks.
|
* An activity displaying a list of tracks.
|
||||||
@@ -73,10 +70,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
|
|
||||||
private static final String TAG = TrackListActivity.class.getSimpleName();
|
private static final String TAG = TrackListActivity.class.getSimpleName();
|
||||||
|
|
||||||
private static final String[] PROJECTION = new String[]{TracksColumns._ID, TracksColumns.NAME,
|
|
||||||
TracksColumns.DESCRIPTION, TracksColumns.CATEGORY, TracksColumns.STARTTIME,
|
|
||||||
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON};
|
|
||||||
|
|
||||||
// The following are set in onCreate
|
// The following are set in onCreate
|
||||||
private ContentProviderUtils contentProviderUtils;
|
private ContentProviderUtils contentProviderUtils;
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
@@ -84,12 +77,12 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
private TrackController trackController;
|
private TrackController trackController;
|
||||||
private ListView listView;
|
private ListView listView;
|
||||||
private ResourceCursorAdapter resourceCursorAdapter;
|
private ResourceCursorAdapter resourceCursorAdapter;
|
||||||
|
private GpsStatusValue gpsStatusValue;
|
||||||
|
|
||||||
private final LoaderCallbacks<Cursor> loaderCallbacks = new LoaderCallbacks<Cursor>() {
|
private final LoaderCallbacks<Cursor> loaderCallbacks = new LoaderCallbacks<Cursor>() {
|
||||||
@Override
|
@Override
|
||||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||||
return new CursorLoader(TrackListActivity.this, TracksColumns.CONTENT_URI, PROJECTION, null,
|
return ContentProviderUtils.getTracksCursorLoader(TrackListActivity.this);
|
||||||
null, TrackUtils.TRACK_SORT_ORDER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -105,7 +98,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
private boolean metricUnits = true;
|
private boolean metricUnits = true;
|
||||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
private Track.Id recordingTrackId = null;
|
||||||
|
|
||||||
// Callback when an item is selected in the contextual action mode
|
// Callback when an item is selected in the contextual action mode
|
||||||
private final ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() {
|
private final ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() {
|
||||||
@@ -126,8 +119,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
|
|
||||||
private boolean recordingTrackPaused;
|
private boolean recordingTrackPaused;
|
||||||
|
|
||||||
private final OnSharedPreferenceChangeListener
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||||
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
if (PreferencesUtils.isKey(TrackListActivity.this, R.string.stats_units_key, key)) {
|
if (PreferencesUtils.isKey(TrackListActivity.this, R.string.stats_units_key, key)) {
|
||||||
@@ -143,14 +135,11 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackListActivity.this);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackListActivity.this);
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(() -> {
|
||||||
@Override
|
TrackListActivity.this.invalidateOptionsMenu();
|
||||||
public void run() {
|
LoaderManager.getInstance(TrackListActivity.this).restartLoader(0, null, loaderCallbacks);
|
||||||
TrackListActivity.this.invalidateOptionsMenu();
|
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
||||||
LoaderManager.getInstance(TrackListActivity.this).restartLoader(0, null, loaderCallbacks);
|
trackController.update(isRecording, recordingTrackPaused);
|
||||||
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
|
||||||
trackController.update(isRecording, recordingTrackPaused);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,35 +157,37 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private boolean startGps = false; // true to start gps
|
|
||||||
|
|
||||||
// Callback when the trackRecordingServiceConnection binding changes.
|
// Callback when the trackRecordingServiceConnection binding changes.
|
||||||
private final Runnable bindChangedCallback = new Runnable() {
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
/*
|
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
||||||
* After binding changes (e.g., becomes available), update the total time in trackController.
|
|
||||||
*/
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
trackController.update(PreferencesUtils.isRecording(recordingTrackId), recordingTrackPaused);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!startGps) {
|
// After binding changes (e.g., becomes available), update the total time in trackController.
|
||||||
return;
|
runOnUiThread(() -> trackController.update(isRecording, recordingTrackPaused));
|
||||||
}
|
|
||||||
|
|
||||||
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
Log.d(TAG, "service not available to start gps or a new recording");
|
Log.d(TAG, "service not available to start gps or a new recording");
|
||||||
|
gpsStatusValue = GpsStatusValue.GPS_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (startGps) {
|
|
||||||
service.startGps();
|
// Get GPS status and listen GPS status changes.
|
||||||
startGps = false;
|
gpsStatusValue = service.getGpsStatus();
|
||||||
|
updateGpsMenuItem(true, isRecording);
|
||||||
|
service.addListener(newStatus -> {
|
||||||
|
gpsStatusValue = newStatus;
|
||||||
|
updateGpsMenuItem(true, isRecording);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isGpsStarted()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
service.startGps();
|
||||||
|
gpsStatusValue = GpsStatusValue.GPS_ENABLED;
|
||||||
|
updateGpsMenuItem(true, isRecording);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -205,8 +196,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
if (!PreferencesUtils.isRecording(recordingTrackId)) {
|
if (!PreferencesUtils.isRecording(recordingTrackId)) {
|
||||||
// Not recording -> Recording
|
// Not recording -> Recording
|
||||||
updateMenuItems(false, true);
|
updateMenuItems(false, true);
|
||||||
Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class)
|
Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class);
|
||||||
.putExtra(TrackDetailActivity.EXTRA_RECORDING_REQUEST, true);
|
|
||||||
startActivity(newIntent);
|
startActivity(newIntent);
|
||||||
} else if (recordingTrackPaused) {
|
} else if (recordingTrackPaused) {
|
||||||
// Paused -> Resume
|
// Paused -> Resume
|
||||||
@@ -226,6 +216,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
gpsStatusValue = GpsStatusValue.GPS_NONE;
|
||||||
|
|
||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||||
|
|
||||||
contentProviderUtils = new ContentProviderUtils(this);
|
contentProviderUtils = new ContentProviderUtils(this);
|
||||||
@@ -239,23 +231,23 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
// Show trackController when search dialog is dismissed
|
// Show trackController when search dialog is dismissed
|
||||||
SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
|
SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
|
||||||
if (searchManager != null) {
|
if (searchManager != null) {
|
||||||
searchManager.setOnDismissListener(new SearchManager.OnDismissListener() {
|
searchManager.setOnDismissListener(() -> trackController.show());
|
||||||
@Override
|
|
||||||
public void onDismiss() {
|
|
||||||
trackController.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listView = findViewById(R.id.track_list);
|
listView = findViewById(R.id.track_list);
|
||||||
listView.setEmptyView(findViewById(R.id.track_list_empty_view));
|
listView.setEmptyView(findViewById(R.id.track_list_empty_view));
|
||||||
listView.setOnItemClickListener(new OnItemClickListener() {
|
listView.setOnItemClickListener((parent, view, position, trackId) -> {
|
||||||
@Override
|
Intent newIntent;
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
if (trackId == recordingTrackId.getId()) {
|
||||||
Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class)
|
// Is recording -> open record activity.
|
||||||
.putExtra(TrackDetailActivity.EXTRA_TRACK_ID, id);
|
newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class)
|
||||||
startActivity(newIntent);
|
.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, new Track.Id(trackId));
|
||||||
|
} else {
|
||||||
|
// Not recording -> open detail activity.
|
||||||
|
newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordedActivity.class)
|
||||||
|
.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, new Track.Id(trackId));
|
||||||
}
|
}
|
||||||
|
startActivity(newIntent);
|
||||||
});
|
});
|
||||||
|
|
||||||
resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) {
|
resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) {
|
||||||
@@ -270,7 +262,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
int categoryIndex = cursor.getColumnIndex(TracksColumns.CATEGORY);
|
int categoryIndex = cursor.getColumnIndex(TracksColumns.CATEGORY);
|
||||||
int descriptionIndex = cursor.getColumnIndex(TracksColumns.DESCRIPTION);
|
int descriptionIndex = cursor.getColumnIndex(TracksColumns.DESCRIPTION);
|
||||||
|
|
||||||
long trackId = cursor.getLong(idIndex);
|
Track.Id trackId = new Track.Id(cursor.getLong(idIndex));
|
||||||
boolean isRecording = trackId == recordingTrackId;
|
boolean isRecording = trackId == recordingTrackId;
|
||||||
String icon = cursor.getString(iconIndex);
|
String icon = cursor.getString(iconIndex);
|
||||||
int iconId = TrackIconUtils.getIconDrawable(icon);
|
int iconId = TrackIconUtils.getIconDrawable(icon);
|
||||||
@@ -292,7 +284,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
|
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
|
||||||
|
|
||||||
LoaderManager.getInstance(this).initLoader(0, null, loaderCallbacks);
|
LoaderManager.getInstance(this).initLoader(0, null, loaderCallbacks);
|
||||||
showStartupDialogs();
|
|
||||||
|
requestGPSPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -359,7 +352,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
boolean isGpsStarted = ServiceUtils.isTrackRecordingServiceRunning(this);
|
boolean isGpsStarted = isGpsStarted();
|
||||||
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
||||||
updateMenuItems(isGpsStarted, isRecording);
|
updateMenuItems(isGpsStarted, isRecording);
|
||||||
|
|
||||||
@@ -379,10 +372,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
|
intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
} else {
|
} else {
|
||||||
startGps = !ServiceUtils.isTrackRecordingServiceRunning(this);
|
|
||||||
|
|
||||||
// Invoke trackRecordingService
|
// Invoke trackRecordingService
|
||||||
if (startGps) {
|
if (!isGpsStarted()) {
|
||||||
trackRecordingServiceConnection.startAndBind(this);
|
trackRecordingServiceConnection.startAndBind(this);
|
||||||
bindChangedCallback.run();
|
bindChangedCallback.run();
|
||||||
} else {
|
} else {
|
||||||
@@ -397,6 +388,10 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
this.invalidateOptionsMenu();
|
this.invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.track_list_aggregated_stats:
|
||||||
|
intent = IntentUtils.newIntent(this, AggregatedStatisticsActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
case R.id.track_list_markers:
|
case R.id.track_list_markers:
|
||||||
intent = IntentUtils.newIntent(this, MarkerListActivity.class);
|
intent = IntentUtils.newIntent(this, MarkerListActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
@@ -434,17 +429,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean isGpsStarted() {
|
||||||
* Shows start up dialogs.
|
return gpsStatusValue != GpsStatusValue.GPS_NONE && gpsStatusValue != GpsStatusValue.GPS_DISABLED;
|
||||||
*/
|
|
||||||
private void showStartupDialogs() {
|
|
||||||
// If stats_units_key is undefined, set it
|
|
||||||
if (PreferencesUtils.getString(this, R.string.stats_units_key, "").equals("")) {
|
|
||||||
String statsUnits = getString(Locale.US.equals(Locale.getDefault()) ? R.string.stats_units_imperial : R.string.stats_units_metric);
|
|
||||||
PreferencesUtils.setString(this, R.string.stats_units_key, statsUnits);
|
|
||||||
}
|
|
||||||
|
|
||||||
requestGPSPermissions();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestGPSPermissions() {
|
private void requestGPSPermissions() {
|
||||||
@@ -454,17 +440,30 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the menu items.
|
* Updates the menu items with not fixed icon for gps option.
|
||||||
*
|
*
|
||||||
* @param isGpsStarted true if gps is started
|
* @param isGpsStarted true if gps is started
|
||||||
* @param isRecording true if recording
|
* @param isRecording true if recording
|
||||||
*/
|
*/
|
||||||
private void updateMenuItems(boolean isGpsStarted, boolean isRecording) {
|
private void updateMenuItems(boolean isGpsStarted, boolean isRecording) {
|
||||||
|
updateGpsMenuItem(isGpsStarted, isRecording);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the menu items with the icon specified.
|
||||||
|
*
|
||||||
|
* @param isGpsStarted true if gps is started
|
||||||
|
* @param isRecording true if recording
|
||||||
|
*/
|
||||||
|
private void updateGpsMenuItem(boolean isGpsStarted, boolean isRecording) {
|
||||||
if (startGpsMenuItem != null) {
|
if (startGpsMenuItem != null) {
|
||||||
startGpsMenuItem.setVisible(!isRecording);
|
startGpsMenuItem.setVisible(!isRecording);
|
||||||
if (!isRecording) {
|
if (!isRecording) {
|
||||||
startGpsMenuItem.setTitle(isGpsStarted ? R.string.menu_stop_gps : R.string.menu_start_gps);
|
startGpsMenuItem.setTitle(isGpsStarted ? R.string.menu_stop_gps : R.string.menu_start_gps);
|
||||||
startGpsMenuItem.setIcon(isGpsStarted ? R.drawable.ic_gps_fixed_24dp : R.drawable.ic_gps_off_24dp);
|
startGpsMenuItem.setIcon(isGpsStarted ? gpsStatusValue.icon : R.drawable.ic_gps_off_24dp);
|
||||||
|
if (startGpsMenuItem.getIcon() instanceof AnimatedVectorDrawable) {
|
||||||
|
((AnimatedVectorDrawable) startGpsMenuItem.getIcon()).start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -472,15 +471,20 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
/**
|
/**
|
||||||
* Handles a context item selection.
|
* Handles a context item selection.
|
||||||
*
|
*
|
||||||
* @param itemId the menu item id
|
* @param itemId the menu item id
|
||||||
* @param trackIds the track ids
|
* @param longTrackIds the track ids
|
||||||
* @return true if handled.
|
* @return true if handled.
|
||||||
*/
|
*/
|
||||||
private boolean handleContextItem(int itemId, long[] trackIds) {
|
private boolean handleContextItem(int itemId, long... longTrackIds) {
|
||||||
|
Track.Id[] trackIds = new Track.Id[longTrackIds.length];
|
||||||
|
for (int i = 0; i < longTrackIds.length; i++) {
|
||||||
|
trackIds[i] = new Track.Id(longTrackIds[i]);
|
||||||
|
}
|
||||||
|
|
||||||
Intent intent;
|
Intent intent;
|
||||||
switch (itemId) {
|
switch (itemId) {
|
||||||
case R.id.list_context_menu_show_on_map:
|
case R.id.list_context_menu_show_on_map:
|
||||||
IntentUtils.showTrackOnMap(this, trackIds);
|
IntentDashboardUtils.startDashboard(this, false, trackIds);
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_share:
|
case R.id.list_context_menu_share:
|
||||||
intent = IntentUtils.newShareFileIntent(this, trackIds);
|
intent = IntentUtils.newShareFileIntent(this, trackIds);
|
||||||
@@ -493,9 +497,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_delete:
|
case R.id.list_context_menu_delete:
|
||||||
if (trackIds.length > 1 && trackIds.length == listView.getCount()) {
|
|
||||||
trackIds = new long[]{-1L};
|
|
||||||
}
|
|
||||||
deleteTracks(trackIds);
|
deleteTracks(trackIds);
|
||||||
return true;
|
return true;
|
||||||
case R.id.list_context_menu_select_all:
|
case R.id.list_context_menu_select_all:
|
||||||
|
|||||||
@@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentPagerAdapter;
|
||||||
|
import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.TrackDataHub;
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
|
import de.dennisguse.opentracks.content.data.Waypoint;
|
||||||
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
|
import de.dennisguse.opentracks.fragments.ChartFragment;
|
||||||
|
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
||||||
|
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
||||||
|
import de.dennisguse.opentracks.fragments.StatisticsRecordedFragment;
|
||||||
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
|
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||||
|
import de.dennisguse.opentracks.util.IntentUtils;
|
||||||
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
|
import de.dennisguse.opentracks.util.TrackUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An activity to show the track detail, record a new track or resumes an existing one.
|
||||||
|
*
|
||||||
|
* @author Leif Hendrik Wilden
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public class TrackRecordedActivity extends AbstractListActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, ConfirmDeleteDialogFragment.ConfirmDeleteCaller, TrackActivityDataHubInterface {
|
||||||
|
|
||||||
|
public static final String EXTRA_TRACK_ID = "track_id";
|
||||||
|
public static final String EXTRA_MARKER_ID = "marker_id";
|
||||||
|
|
||||||
|
private static final String TAG = TrackRecordedActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final String CURRENT_TAB_TAG_KEY = "current_tab_tag_key";
|
||||||
|
|
||||||
|
// The following are set in onCreate.
|
||||||
|
private ContentProviderUtils contentProviderUtils;
|
||||||
|
private TrackDataHub trackDataHub;
|
||||||
|
private ViewPager pager;
|
||||||
|
|
||||||
|
// From intent.
|
||||||
|
private Track.Id trackId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
contentProviderUtils = new ContentProviderUtils(this);
|
||||||
|
handleIntent(getIntent());
|
||||||
|
|
||||||
|
trackDataHub = new TrackDataHub(this);
|
||||||
|
|
||||||
|
FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager(), 1) {
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int position) {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
return new StatisticsRecordedFragment();
|
||||||
|
case 1:
|
||||||
|
return ChartFragment.newInstance(false);
|
||||||
|
case 2:
|
||||||
|
return ChartFragment.newInstance(true);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("There isn't Fragment associated with the position: " + position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getPageTitle(int position) {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
return getString(R.string.track_detail_stats_tab);
|
||||||
|
case 1:
|
||||||
|
return getString(R.string.settings_chart_by_time);
|
||||||
|
case 2:
|
||||||
|
return getString(R.string.settings_chart_by_distance);
|
||||||
|
}
|
||||||
|
return "Unknown Tab";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pager = findViewById(R.id.track_detail_activity_view_pager);
|
||||||
|
pager.setAdapter(adapter);
|
||||||
|
TabLayout tabs = findViewById(R.id.track_detail_activity_tablayout);
|
||||||
|
tabs.setupWithViewPager(pager);
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
pager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
trackDataHub.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
// Update UI
|
||||||
|
this.invalidateOptionsMenu();
|
||||||
|
|
||||||
|
if (trackId.isValid()) {
|
||||||
|
trackDataHub.loadTrack(trackId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
trackDataHub.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
outState.putInt(CURRENT_TAB_TAG_KEY, pager.getCurrentItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getLayoutResId() {
|
||||||
|
return R.layout.track_detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewIntent(Intent intent) {
|
||||||
|
super.onNewIntent(intent);
|
||||||
|
setIntent(intent);
|
||||||
|
handleIntent(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.track_detail, menu);
|
||||||
|
return super.onCreateOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
|
menu.findItem(R.id.track_detail_markers).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||||
|
menu.findItem(R.id.track_detail_resume_track).setVisible(!PreferencesUtils.isRecording(this));
|
||||||
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
setTitle(track != null ? track.getName() : "");
|
||||||
|
return super.onPrepareOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
Intent intent;
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.track_detail_share:
|
||||||
|
intent = IntentUtils.newShareFileIntent(this, trackId);
|
||||||
|
intent = Intent.createChooser(intent, null);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
case R.id.track_detail_menu_show_on_map:
|
||||||
|
IntentDashboardUtils.startDashboard(this, false, trackId);
|
||||||
|
return true;
|
||||||
|
case R.id.track_detail_markers:
|
||||||
|
intent = IntentUtils.newIntent(this, MarkerListActivity.class)
|
||||||
|
.putExtra(MarkerListActivity.EXTRA_TRACK_ID, trackId);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
case R.id.track_detail_edit:
|
||||||
|
intent = IntentUtils.newIntent(this, TrackEditActivity.class)
|
||||||
|
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
case R.id.track_detail_delete:
|
||||||
|
deleteTracks(trackId);
|
||||||
|
return true;
|
||||||
|
case R.id.track_detail_resume_track:
|
||||||
|
Intent newIntent = IntentUtils.newIntent(TrackRecordedActivity.this, TrackRecordingActivity.class)
|
||||||
|
.putExtra(TrackRecordingActivity.EXTRA_TRACK_ID, trackId);
|
||||||
|
startActivity(newIntent);
|
||||||
|
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
case R.id.track_detail_settings:
|
||||||
|
intent = IntentUtils.newIntent(this, SettingsActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() {
|
||||||
|
// Not needed.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDeleted() {
|
||||||
|
runOnUiThread(this::finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link TrackDataHub}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TrackDataHub getTrackDataHub() {
|
||||||
|
return trackDataHub;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleIntent(Intent intent) {
|
||||||
|
trackId = intent.getParcelableExtra(EXTRA_TRACK_ID);
|
||||||
|
|
||||||
|
Waypoint.Id waypointId = intent.getParcelableExtra(EXTRA_MARKER_ID);
|
||||||
|
if (waypointId != null) {
|
||||||
|
// Use the trackId from the marker
|
||||||
|
Waypoint waypoint = contentProviderUtils.getWaypoint(waypointId);
|
||||||
|
if (waypoint == null) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
trackId = waypoint.getTrackId();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trackId == null) {
|
||||||
|
Log.e(TAG, "TrackDetailActivity needs EXTRA_TRACK_ID.");
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void chooseActivityType(String category) {
|
||||||
|
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), category);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChooseActivityTypeDone(String iconValue) {
|
||||||
|
Track track = contentProviderUtils.getTrack(trackId);
|
||||||
|
String category = getString(TrackIconUtils.getIconActivityType(iconValue));
|
||||||
|
TrackUtils.updateTrack(this, track, null, category, null, contentProviderUtils);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2008 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dennisguse.opentracks;
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -27,10 +11,10 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentPagerAdapter;
|
import androidx.fragment.app.FragmentPagerAdapter;
|
||||||
import androidx.viewpager.widget.ViewPager;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
@@ -38,15 +22,14 @@ import com.google.android.material.tabs.TabLayout;
|
|||||||
|
|
||||||
import de.dennisguse.opentracks.content.TrackDataHub;
|
import de.dennisguse.opentracks.content.TrackDataHub;
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.Waypoint;
|
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
import de.dennisguse.opentracks.fragments.ChartFragment;
|
import de.dennisguse.opentracks.fragments.ChartFragment;
|
||||||
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
||||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment;
|
||||||
import de.dennisguse.opentracks.fragments.StatsFragment;
|
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
|
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||||
import de.dennisguse.opentracks.util.IntentUtils;
|
import de.dennisguse.opentracks.util.IntentUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
@@ -58,13 +41,13 @@ import de.dennisguse.opentracks.util.TrackUtils;
|
|||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
* @author Rodrigo Damazio
|
* @author Rodrigo Damazio
|
||||||
*/
|
*/
|
||||||
public class TrackDetailActivity extends AbstractListActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, ConfirmDeleteDialogFragment.ConfirmDeleteCaller {
|
//NOTE: This activity does NOT react to preference changes of R.string.recording_track_id_key.
|
||||||
|
//This mode of communication should be removed anyhow.
|
||||||
|
public class TrackRecordingActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, TrackActivityDataHubInterface {
|
||||||
|
|
||||||
public static final String EXTRA_TRACK_ID = "track_id";
|
public static final String EXTRA_TRACK_ID = "track_id";
|
||||||
public static final String EXTRA_MARKER_ID = "marker_id";
|
|
||||||
public static final String EXTRA_RECORDING_REQUEST = "request_recording";
|
|
||||||
|
|
||||||
private static final String TAG = TrackDetailActivity.class.getSimpleName();
|
private static final String TAG = TrackRecordingActivity.class.getSimpleName();
|
||||||
|
|
||||||
private static final String CURRENT_TAB_TAG_KEY = "current_tab_tag_key";
|
private static final String CURRENT_TAB_TAG_KEY = "current_tab_tag_key";
|
||||||
|
|
||||||
@@ -76,57 +59,37 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
private ViewPager pager;
|
private ViewPager pager;
|
||||||
private TrackController trackController;
|
private TrackController trackController;
|
||||||
|
|
||||||
// From intent
|
// Initialized from Intent; if a new track recording is started, a new TrackId will be provided by TrackRecordingService
|
||||||
private long trackId;
|
private Track.Id trackId;
|
||||||
|
|
||||||
private boolean isRecordingRequest = false;
|
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
|
||||||
private boolean recordingTrackPaused;
|
private boolean recordingTrackPaused;
|
||||||
|
|
||||||
private final Runnable bindChangedCallback = new Runnable() {
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// After binding changes (is available), update the total time in trackController.
|
// After binding changes (is available), update the total time in trackController.
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(() -> trackController.update(true, recordingTrackPaused));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
trackController.update(isRecording(), recordingTrackPaused);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (recordingTrackId == -1L) {
|
|
||||||
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
|
||||||
if (service == null) {
|
|
||||||
Log.d(TAG, "could not get TrackRecordingService");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isRecordingRequest) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
|
if (service == null) {
|
||||||
|
Log.d(TAG, "could not get TrackRecordingService");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!service.isRecording()) {
|
||||||
// Starts or resumes a track.
|
// Starts or resumes a track.
|
||||||
int msg;
|
if (trackId == null) {
|
||||||
if (trackId == -1L) {
|
|
||||||
// trackId isn't initialized -> leads a new recording.
|
// trackId isn't initialized -> leads a new recording.
|
||||||
trackId = service.startNewTrack();
|
trackId = service.startNewTrack();
|
||||||
recordingTrackId = trackId;
|
|
||||||
msg = R.string.track_detail_record_success;
|
|
||||||
} else {
|
} else {
|
||||||
// trackId is initialized -> resumes the track.
|
// trackId is initialized -> resumes the track.
|
||||||
recordingTrackId = trackId;
|
|
||||||
service.resumeTrack(trackId);
|
service.resumeTrack(trackId);
|
||||||
msg = R.string.track_detail_resume_success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A recording track is on.
|
// A recording track is on.
|
||||||
Toast.makeText(TrackDetailActivity.this, msg, Toast.LENGTH_SHORT).show();
|
|
||||||
trackDataHub.loadTrack(trackId);
|
trackDataHub.loadTrack(trackId);
|
||||||
trackController.update(true, false);
|
trackController.update(true, false);
|
||||||
trackController.onResume(true, recordingTrackPaused);
|
trackController.onResume(true, recordingTrackPaused);
|
||||||
|
|
||||||
isRecordingRequest = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -134,43 +97,34 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.recording_track_id_key, key)) {
|
if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.recording_track_paused_key, key)) {
|
||||||
recordingTrackId = PreferencesUtils.getRecordingTrackId(TrackDetailActivity.this);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackRecordingActivity.this);
|
||||||
setLockscreenPolicy();
|
setLockscreenPolicy();
|
||||||
setScreenOnPolicy();
|
setScreenOnPolicy();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.recording_track_paused_key, key)) {
|
if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.stats_show_on_lockscreen_while_recording_key, key)) {
|
||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackDetailActivity.this);
|
|
||||||
setLockscreenPolicy();
|
|
||||||
setScreenOnPolicy();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.stats_show_on_lockscreen_while_recording_key, key)) {
|
|
||||||
setLockscreenPolicy();
|
setLockscreenPolicy();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.stats_keep_screen_on_while_recording_key, key)) {
|
if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.stats_keep_screen_on_while_recording_key, key)) {
|
||||||
setScreenOnPolicy();
|
setScreenOnPolicy();
|
||||||
}
|
}
|
||||||
|
if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.stats_fullscreen_while_recording_key, key)) {
|
||||||
|
setFullscreenPolicy();
|
||||||
|
}
|
||||||
|
|
||||||
if (key == null) return;
|
if (key == null) return;
|
||||||
|
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(() -> {
|
||||||
@Override
|
TrackRecordingActivity.this.invalidateOptionsMenu();
|
||||||
public void run() {
|
trackController.update(true, recordingTrackPaused);
|
||||||
TrackDetailActivity.this.invalidateOptionsMenu();
|
|
||||||
boolean isRecording = isRecording();
|
|
||||||
trackController.update(isRecording, recordingTrackPaused);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private MenuItem insertMarkerMenuItem;
|
private MenuItem insertMarkerMenuItem;
|
||||||
private MenuItem markerListMenuItem;
|
private MenuItem markerListMenuItem;
|
||||||
private MenuItem shareMenuItem;
|
|
||||||
private MenuItem resumeMenuItem;
|
|
||||||
|
|
||||||
private final OnClickListener recordListener = new OnClickListener() {
|
private final OnClickListener recordListener = new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -192,58 +146,41 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
private final OnClickListener stopListener = new OnClickListener() {
|
private final OnClickListener stopListener = new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
trackRecordingServiceConnection.stopRecording(TrackDetailActivity.this, true);
|
trackRecordingServiceConnection.stopRecording(TrackRecordingActivity.this, true);
|
||||||
|
Intent newIntent = IntentUtils.newIntent(TrackRecordingActivity.this, TrackRecordedActivity.class)
|
||||||
|
.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId);
|
||||||
|
startActivity(newIntent);
|
||||||
|
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||||
updateMenuItems(true);
|
updateMenuItems(true);
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
|
||||||
|
|
||||||
contentProviderUtils = new ContentProviderUtils(this);
|
contentProviderUtils = new ContentProviderUtils(this);
|
||||||
handleIntent(getIntent());
|
|
||||||
|
|
||||||
|
trackId = null;
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
//Activity was recreated.
|
||||||
|
trackId = savedInstanceState.getParcelable(EXTRA_TRACK_ID);
|
||||||
|
} else {
|
||||||
|
trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID);
|
||||||
|
if (trackId != null && contentProviderUtils.getTrack(trackId) == null) {
|
||||||
|
Log.w(TAG, "TrackId does not exists; cannot continue the recording.");
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||||
|
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
||||||
trackDataHub = new TrackDataHub(this);
|
trackDataHub = new TrackDataHub(this);
|
||||||
|
|
||||||
FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager(), 1) {
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public Fragment getItem(int position) {
|
|
||||||
switch (position) {
|
|
||||||
case 1:
|
|
||||||
return ChartFragment.newInstance(false);
|
|
||||||
case 2:
|
|
||||||
return ChartFragment.newInstance(true);
|
|
||||||
default: //0
|
|
||||||
return new StatsFragment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CharSequence getPageTitle(int position) {
|
|
||||||
switch (position) {
|
|
||||||
case 0:
|
|
||||||
return getString(R.string.track_detail_stats_tab);
|
|
||||||
case 1:
|
|
||||||
return getString(R.string.settings_chart_by_time);
|
|
||||||
case 2:
|
|
||||||
return getString(R.string.settings_chart_by_distance);
|
|
||||||
}
|
|
||||||
return "Unknown Tab";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
pager = findViewById(R.id.track_detail_activity_view_pager);
|
pager = findViewById(R.id.track_detail_activity_view_pager);
|
||||||
pager.setAdapter(adapter);
|
pager.setAdapter(new CustomFragmentPagerAdapter(getSupportFragmentManager(), 1));
|
||||||
TabLayout tabs = findViewById(R.id.track_detail_activity_tablayout);
|
TabLayout tabs = findViewById(R.id.track_detail_activity_tablayout);
|
||||||
tabs.setupWithViewPager(pager);
|
tabs.setupWithViewPager(pager);
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
@@ -257,12 +194,12 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
public void onAttachedToWindow() {
|
public void onAttachedToWindow() {
|
||||||
setLockscreenPolicy();
|
setLockscreenPolicy();
|
||||||
setScreenOnPolicy();
|
setScreenOnPolicy();
|
||||||
|
setFullscreenPolicy();
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLockscreenPolicy() {
|
private void setLockscreenPolicy() {
|
||||||
boolean showOnLockScreen = PreferencesUtils.shouldShowStatsOnLockscreen(TrackDetailActivity.this)
|
boolean showOnLockScreen = PreferencesUtils.shouldShowStatsOnLockscreen(TrackRecordingActivity.this);
|
||||||
&& PreferencesUtils.isRecording(this);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||||
setShowWhenLocked(showOnLockScreen);
|
setShowWhenLocked(showOnLockScreen);
|
||||||
@@ -274,8 +211,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setScreenOnPolicy() {
|
private void setScreenOnPolicy() {
|
||||||
boolean keepScreenOn = PreferencesUtils.shouldKeepScreenOn(TrackDetailActivity.this)
|
boolean keepScreenOn = PreferencesUtils.shouldKeepScreenOn(TrackRecordingActivity.this);
|
||||||
&& PreferencesUtils.isRecording(this);
|
|
||||||
|
|
||||||
if (keepScreenOn) {
|
if (keepScreenOn) {
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
@@ -284,6 +220,16 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setFullscreenPolicy() {
|
||||||
|
boolean keepScreenOn = PreferencesUtils.shouldUseFullscreen(TrackRecordingActivity.this);
|
||||||
|
|
||||||
|
if (keepScreenOn) {
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||||
|
} else {
|
||||||
|
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
@@ -302,12 +248,25 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
// Update UI
|
// Update UI
|
||||||
this.invalidateOptionsMenu();
|
this.invalidateOptionsMenu();
|
||||||
|
|
||||||
if (trackId != -1L) {
|
if (trackId != null) {
|
||||||
trackDataHub.loadTrack(trackId);
|
trackDataHub.loadTrack(trackId);
|
||||||
trackController.onResume(isRecording(), recordingTrackPaused);
|
trackController.onResume(true, recordingTrackPaused);
|
||||||
} else {
|
|
||||||
startRecording();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the binding has happened, then invoke the callback to start a new recording.
|
||||||
|
* If the binding hasn't happened, then invoking the callback will have no effect.
|
||||||
|
* But when the binding occurs, the callback will get invoked.
|
||||||
|
*/
|
||||||
|
trackRecordingServiceConnection.startAndBind(this);
|
||||||
|
bindChangedCallback.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
outState.putInt(CURRENT_TAB_TAG_KEY, pager.getCurrentItem());
|
||||||
|
outState.putParcelable(EXTRA_TRACK_ID, trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -324,32 +283,17 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
trackDataHub.stop();
|
trackDataHub.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
outState.putInt(CURRENT_TAB_TAG_KEY, pager.getCurrentItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getLayoutResId() {
|
protected int getLayoutResId() {
|
||||||
return R.layout.track_detail;
|
return R.layout.track_record;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNewIntent(Intent intent) {
|
|
||||||
super.onNewIntent(intent);
|
|
||||||
setIntent(intent);
|
|
||||||
handleIntent(intent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.track_detail, menu);
|
getMenuInflater().inflate(R.menu.track_record, menu);
|
||||||
|
|
||||||
insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
|
insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
|
||||||
shareMenuItem = menu.findItem(R.id.track_detail_share);
|
|
||||||
markerListMenuItem = menu.findItem(R.id.track_detail_markers);
|
markerListMenuItem = menu.findItem(R.id.track_detail_markers);
|
||||||
resumeMenuItem = menu.findItem(R.id.track_detail_resume_track);
|
|
||||||
|
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
@@ -370,13 +314,8 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
.putExtra(MarkerEditActivity.EXTRA_TRACK_ID, trackId);
|
.putExtra(MarkerEditActivity.EXTRA_TRACK_ID, trackId);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.track_detail_share:
|
|
||||||
intent = IntentUtils.newShareFileIntent(this, new long[]{trackId});
|
|
||||||
intent = Intent.createChooser(intent, null);
|
|
||||||
startActivity(intent);
|
|
||||||
return true;
|
|
||||||
case R.id.track_detail_menu_show_on_map:
|
case R.id.track_detail_menu_show_on_map:
|
||||||
IntentUtils.showTrackOnMap(this, new long[]{trackId});
|
IntentDashboardUtils.startDashboard(this, true, trackId);
|
||||||
return true;
|
return true;
|
||||||
case R.id.track_detail_markers:
|
case R.id.track_detail_markers:
|
||||||
intent = IntentUtils.newIntent(this, MarkerListActivity.class)
|
intent = IntentUtils.newIntent(this, MarkerListActivity.class)
|
||||||
@@ -388,13 +327,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.track_detail_delete:
|
|
||||||
deleteTracks(new long[]{trackId});
|
|
||||||
return true;
|
|
||||||
case R.id.track_detail_resume_track:
|
|
||||||
isRecordingRequest = true;
|
|
||||||
startRecording();
|
|
||||||
return true;
|
|
||||||
case R.id.track_detail_settings:
|
case R.id.track_detail_settings:
|
||||||
intent = IntentUtils.newIntent(this, SettingsActivity.class);
|
intent = IntentUtils.newIntent(this, SettingsActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
@@ -404,81 +336,21 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() {
|
|
||||||
return trackRecordingServiceConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDeleted() {
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link TrackDataHub}.
|
* Gets the {@link TrackDataHub}.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public TrackDataHub getTrackDataHub() {
|
public TrackDataHub getTrackDataHub() {
|
||||||
return trackDataHub;
|
return trackDataHub;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleIntent(Intent intent) {
|
|
||||||
trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L);
|
|
||||||
isRecordingRequest = intent.getBooleanExtra(EXTRA_RECORDING_REQUEST, false);
|
|
||||||
long markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L);
|
|
||||||
if (markerId != -1L) {
|
|
||||||
// Use the trackId from the marker
|
|
||||||
Waypoint waypoint = contentProviderUtils.getWaypoint(markerId);
|
|
||||||
if (waypoint == null) {
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
trackId = waypoint.getTrackId();
|
|
||||||
if (trackId == -1L) {
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trackId == -1L) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Track track = contentProviderUtils.getTrack(trackId);
|
|
||||||
if (track == null) {
|
|
||||||
// Use the last track if markerId is not set
|
|
||||||
if (markerId == -1L) {
|
|
||||||
track = contentProviderUtils.getLastTrack();
|
|
||||||
if (track != null) {
|
|
||||||
trackId = track.getId();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the menu items.
|
* Updates the menu items.
|
||||||
*/
|
*/
|
||||||
private void updateMenuItems(boolean isPaused) {
|
private void updateMenuItems(boolean isPaused) {
|
||||||
insertMarkerMenuItem.setVisible(isRecording() && !isPaused);
|
insertMarkerMenuItem.setVisible(!isPaused);
|
||||||
shareMenuItem.setVisible(!isRecording());
|
markerListMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||||
markerListMenuItem.setShowAsAction(isRecording() ? MenuItem.SHOW_AS_ACTION_NEVER : MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
setTitle(getString(isPaused ? R.string.generic_paused : R.string.generic_recording));
|
||||||
String title;
|
|
||||||
if (isRecording()) {
|
|
||||||
title = getString(isPaused ? R.string.generic_paused : R.string.generic_recording);
|
|
||||||
resumeMenuItem.setVisible(false);
|
|
||||||
} else {
|
|
||||||
Track track = contentProviderUtils.getTrack(trackId);
|
|
||||||
title = track != null ? track.getName() : "";
|
|
||||||
// Only visible if there aren't other tracks that is recording.
|
|
||||||
resumeMenuItem.setVisible(recordingTrackId == -1L);
|
|
||||||
}
|
|
||||||
setTitle(title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void chooseActivityType(String category) {
|
public void chooseActivityType(String category) {
|
||||||
@@ -492,18 +364,44 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
TrackUtils.updateTrack(this, track, null, category, null, contentProviderUtils);
|
TrackUtils.updateTrack(this, track, null, category, null, contentProviderUtils);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isRecording() {
|
private class CustomFragmentPagerAdapter extends FragmentPagerAdapter {
|
||||||
return trackId == recordingTrackId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startRecording() {
|
public CustomFragmentPagerAdapter(@NonNull FragmentManager fm, int behavior) {
|
||||||
trackRecordingServiceConnection.startAndBind(this);
|
super(fm, behavior);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* If the binding has happened, then invoke the callback to start a new recording.
|
public int getCount() {
|
||||||
* If the binding hasn't happened, then invoking the callback will have no effect.
|
return 3;
|
||||||
* But when the binding occurs, the callback will get invoked.
|
}
|
||||||
*/
|
|
||||||
bindChangedCallback.run();
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int position) {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
return new StatisticsRecordingFragment();
|
||||||
|
case 1:
|
||||||
|
return ChartFragment.newInstance(false);
|
||||||
|
case 2:
|
||||||
|
return ChartFragment.newInstance(true);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("There isn't Fragment associated with the position: " + position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getPageTitle(int position) {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
return getString(R.string.track_detail_stats_tab);
|
||||||
|
case 1:
|
||||||
|
return getString(R.string.settings_chart_by_time);
|
||||||
|
case 2:
|
||||||
|
return getString(R.string.settings_chart_by_distance);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("There isn't Fragment associated with the position: " + position);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
package de.dennisguse.opentracks.adapters;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Pair;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.R;
|
||||||
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
|
import de.dennisguse.opentracks.viewmodels.AggregatedStatistics;
|
||||||
|
|
||||||
|
public class AggregatedStatisticsAdapter extends BaseAdapter {
|
||||||
|
|
||||||
|
private final AggregatedStatistics aggregatedStatistics;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
public AggregatedStatisticsAdapter(Context context, AggregatedStatistics aggregatedStatistics) {
|
||||||
|
this.context = context;
|
||||||
|
this.aggregatedStatistics = aggregatedStatistics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
if (aggregatedStatistics != null) {
|
||||||
|
return aggregatedStatistics.getCount();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AggregatedStatistics.AggregatedStatistic getItem(int position) {
|
||||||
|
return aggregatedStatistics.getItem(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
// Not important because data are not database register but cooked data.
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
AggregatedStatistics.AggregatedStatistic aggregatedStats = getItem(position);
|
||||||
|
ViewHolder viewHolder;
|
||||||
|
|
||||||
|
if (isSpeedSport(position)) {
|
||||||
|
viewHolder = new ViewSpeedHolder();
|
||||||
|
} else {
|
||||||
|
viewHolder = new ViewPaceHolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
convertView = LayoutInflater.from(context).inflate(R.layout.aggregated_stats_list_item, parent, false);
|
||||||
|
viewHolder.setValues(convertView, getIcon(position), getName(position), aggregatedStats);
|
||||||
|
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSpeedSport(int position) {
|
||||||
|
String category = aggregatedStatistics.getSportName(position);
|
||||||
|
return TrackIconUtils.isSpeedIcon(context, category);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIcon(int position) {
|
||||||
|
String iconValue = TrackIconUtils.getIconValue(context, aggregatedStatistics.getSportName(position));
|
||||||
|
return TrackIconUtils.getIconDrawable(iconValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getName(int position) {
|
||||||
|
return aggregatedStatistics.getSportName(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ViewHolder {
|
||||||
|
protected ImageView sportIcon;
|
||||||
|
protected TextView typeLabel;
|
||||||
|
protected TextView numTracks;
|
||||||
|
protected TextView distance;
|
||||||
|
protected TextView distanceUnit;
|
||||||
|
protected TextView time;
|
||||||
|
protected boolean metricsUnits;
|
||||||
|
protected boolean reportSpeed;
|
||||||
|
|
||||||
|
public void setValues(View view, int iconDrawable, String name, AggregatedStatistics.AggregatedStatistic aggregatedStats) {
|
||||||
|
reportSpeed = PreferencesUtils.isReportSpeed(context, name);
|
||||||
|
metricsUnits = PreferencesUtils.isMetricUnits(context);
|
||||||
|
|
||||||
|
sportIcon = view.findViewById(R.id.aggregated_stats_sport_icon);
|
||||||
|
typeLabel = view.findViewById(R.id.aggregated_stats_type_label);
|
||||||
|
numTracks = view.findViewById(R.id.aggregated_stats_num_tracks);
|
||||||
|
distance = view.findViewById(R.id.aggregated_stats_distance);
|
||||||
|
distanceUnit = view.findViewById(R.id.aggregated_stats_distance_unit);
|
||||||
|
time = view.findViewById(R.id.aggregated_stats_time);
|
||||||
|
|
||||||
|
sportIcon.setImageResource(iconDrawable);
|
||||||
|
typeLabel.setText(name);
|
||||||
|
numTracks.setText(StringUtils.valueInParentheses(String.valueOf(aggregatedStats.getCountTracks())));
|
||||||
|
|
||||||
|
Pair<String, String> parts = StringUtils.getDistanceParts(context, aggregatedStats.getTrackStatistics().getTotalDistance(), metricsUnits);
|
||||||
|
distance.setText(parts.first);
|
||||||
|
distanceUnit.setText(parts.second);
|
||||||
|
|
||||||
|
time.setText(StringUtils.formatElapsedTime(aggregatedStats.getTrackStatistics().getMovingTime()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ViewSpeedHolder extends ViewHolder {
|
||||||
|
private TextView avgSpeed;
|
||||||
|
private TextView avgSpeedUnit;
|
||||||
|
private TextView avgSpeedLabel;
|
||||||
|
private TextView maxSpeed;
|
||||||
|
private TextView maxSpeedUnit;
|
||||||
|
private TextView maxSpeedLabel;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValues(View view, int iconDrawable, String name, AggregatedStatistics.AggregatedStatistic aggregatedStats) {
|
||||||
|
super.setValues(view, iconDrawable, name, aggregatedStats);
|
||||||
|
|
||||||
|
avgSpeed = view.findViewById(R.id.aggregated_stats_avg_rate);
|
||||||
|
avgSpeedUnit = view.findViewById(R.id.aggregated_stats_avg_rate_unit);
|
||||||
|
avgSpeedLabel = view.findViewById(R.id.aggregated_stats_avg_rate_label);
|
||||||
|
maxSpeed = view.findViewById(R.id.aggregated_stats_max_rate);
|
||||||
|
maxSpeedUnit = view.findViewById(R.id.aggregated_stats_max_rate_unit);
|
||||||
|
maxSpeedLabel = view.findViewById(R.id.aggregated_stats_max_rate_label);
|
||||||
|
|
||||||
|
{
|
||||||
|
Pair<String, String> parts = StringUtils.getSpeedParts(context, aggregatedStats.getTrackStatistics().getAverageMovingSpeed(), metricsUnits, reportSpeed);
|
||||||
|
avgSpeed.setText(parts.first);
|
||||||
|
avgSpeedUnit.setText(parts.second);
|
||||||
|
avgSpeedLabel.setText(context.getString(R.string.stats_average_moving_speed));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Pair<String, String> parts = StringUtils.getSpeedParts(context, aggregatedStats.getTrackStatistics().getMaxSpeed(), metricsUnits, reportSpeed);
|
||||||
|
maxSpeed.setText(parts.first);
|
||||||
|
maxSpeedUnit.setText(parts.second);
|
||||||
|
maxSpeedLabel.setText(context.getString(R.string.stats_max_speed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ViewPaceHolder extends ViewHolder {
|
||||||
|
private TextView avgPace;
|
||||||
|
private TextView avgPaceUnit;
|
||||||
|
private TextView avgPaceLabel;
|
||||||
|
private TextView maxPace;
|
||||||
|
private TextView maxPaceUnit;
|
||||||
|
private TextView maxPaceLabel;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValues(View view, int iconDrawable, String name, AggregatedStatistics.AggregatedStatistic aggregatedStats) {
|
||||||
|
super.setValues(view, iconDrawable, name, aggregatedStats);
|
||||||
|
|
||||||
|
avgPace = view.findViewById(R.id.aggregated_stats_avg_rate);
|
||||||
|
avgPaceUnit = view.findViewById(R.id.aggregated_stats_avg_rate_unit);
|
||||||
|
avgPaceLabel = view.findViewById(R.id.aggregated_stats_avg_rate_label);
|
||||||
|
|
||||||
|
maxPace = view.findViewById(R.id.aggregated_stats_max_rate);
|
||||||
|
maxPaceUnit = view.findViewById(R.id.aggregated_stats_max_rate_unit);
|
||||||
|
maxPaceLabel = view.findViewById(R.id.aggregated_stats_max_rate_label);
|
||||||
|
|
||||||
|
{
|
||||||
|
Pair<String, String> parts = StringUtils.getSpeedParts(context, aggregatedStats.getTrackStatistics().getAverageMovingSpeed(), metricsUnits, reportSpeed);
|
||||||
|
avgPace.setText(parts.first);
|
||||||
|
avgPaceUnit.setText(parts.second);
|
||||||
|
avgPaceLabel.setText(R.string.stats_average_moving_pace);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Pair<String, String> parts = StringUtils.getSpeedParts(context, aggregatedStats.getTrackStatistics().getMaxSpeed(), metricsUnits, reportSpeed);
|
||||||
|
maxPace.setText(parts.first);
|
||||||
|
maxPaceUnit.setText(parts.second);
|
||||||
|
maxPaceLabel.setText(R.string.stats_fastest_pace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,7 +43,7 @@ public class ChartPoint {
|
|||||||
elevation *= UnitConversions.M_TO_FT;
|
elevation *= UnitConversions.M_TO_FT;
|
||||||
}
|
}
|
||||||
|
|
||||||
speed = trackStatisticsUpdater.getSmoothedSpeed() * UnitConversions.MS_TO_KMH;
|
speed = trackStatisticsUpdater.getSmoothedSpeed() * UnitConversions.MPS_TO_KMH;
|
||||||
if (!metricUnits) {
|
if (!metricUnits) {
|
||||||
speed *= UnitConversions.KM_TO_MI;
|
speed *= UnitConversions.KM_TO_MI;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public class DescriptionGenerator {
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void writeSpeed(double speed, StringBuilder builder, int resId, String lineBreak) {
|
void writeSpeed(double speed, StringBuilder builder, int resId, String lineBreak) {
|
||||||
double speedInKmHr = speed * UnitConversions.MS_TO_KMH;
|
double speedInKmHr = speed * UnitConversions.MPS_TO_KMH;
|
||||||
double speedInMiHr = speedInKmHr * UnitConversions.KM_TO_MI;
|
double speedInMiHr = speedInKmHr * UnitConversions.KM_TO_MI;
|
||||||
builder.append(context.getString(resId, speedInKmHr, speedInMiHr));
|
builder.append(context.getString(resId, speedInKmHr, speedInMiHr));
|
||||||
builder.append(lineBreak);
|
builder.append(lineBreak);
|
||||||
|
|||||||
@@ -108,28 +108,25 @@ public class SearchEngine {
|
|||||||
/**
|
/**
|
||||||
* Comparator for scored results.
|
* Comparator for scored results.
|
||||||
*/
|
*/
|
||||||
private static final Comparator<ScoredResult> SCORED_RESULT_COMPARATOR = new Comparator<ScoredResult>() {
|
private static final Comparator<ScoredResult> SCORED_RESULT_COMPARATOR = (r1, r2) -> {
|
||||||
@Override
|
// Score ordering.
|
||||||
public int compare(ScoredResult r1, ScoredResult r2) {
|
int scoreDiff = Double.compare(r2.score, r1.score);
|
||||||
// Score ordering.
|
if (scoreDiff != 0) {
|
||||||
int scoreDiff = Double.compare(r2.score, r1.score);
|
return scoreDiff;
|
||||||
if (scoreDiff != 0) {
|
|
||||||
return scoreDiff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make tracks come before waypoints.
|
|
||||||
if (r1.waypoint != null && r2.track != null) {
|
|
||||||
return 1;
|
|
||||||
} else if (r1.track != null && r2.waypoint != null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, use arbitrary ordering, by ID.
|
|
||||||
long id1 = r1.track != null ? r1.track.getId() : r1.waypoint.getId();
|
|
||||||
long id2 = r2.track != null ? r2.track.getId() : r2.waypoint.getId();
|
|
||||||
long idDiff = id2 - id1;
|
|
||||||
return Long.signum(idDiff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make tracks come before waypoints.
|
||||||
|
if (r1.waypoint != null && r2.track != null) {
|
||||||
|
return 1;
|
||||||
|
} else if (r1.track != null && r2.waypoint != null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, use arbitrary ordering, by ID.
|
||||||
|
long id1 = r1.track != null ? r1.track.getId().getId() : r1.waypoint.getId().getId();
|
||||||
|
long id2 = r2.track != null ? r2.track.getId().getId() : r2.waypoint.getId().getId();
|
||||||
|
long idDiff = id2 - id1;
|
||||||
|
return Long.signum(idDiff);
|
||||||
};
|
};
|
||||||
|
|
||||||
private final ContentProviderUtils providerUtils;
|
private final ContentProviderUtils providerUtils;
|
||||||
@@ -293,7 +290,7 @@ public class SearchEngine {
|
|||||||
score *= getTimeBoost(query, location.getTime());
|
score *= getTimeBoost(query, location.getTime());
|
||||||
|
|
||||||
// Score waypoints in the currently-selected track higher (searching inside the current track).
|
// Score waypoints in the currently-selected track higher (searching inside the current track).
|
||||||
if (query.currentTrackId != -1 && waypoint.getTrackId() == query.currentTrackId) {
|
if (waypoint.getTrackId() != null && waypoint.getTrackId().equals(query.currentTrackId)) {
|
||||||
score *= CURRENT_TRACK_WAYPOINT_PROMOTION;
|
score *= CURRENT_TRACK_WAYPOINT_PROMOTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,10 +382,10 @@ public class SearchEngine {
|
|||||||
public static class SearchQuery {
|
public static class SearchQuery {
|
||||||
final String textQuery;
|
final String textQuery;
|
||||||
final Location currentLocation;
|
final Location currentLocation;
|
||||||
final long currentTrackId;
|
final Track.Id currentTrackId;
|
||||||
final long currentTimestamp;
|
final long currentTimestamp;
|
||||||
|
|
||||||
public SearchQuery(String textQuery, Location currentLocation, long currentTrackId, long currentTimestamp) {
|
public SearchQuery(String textQuery, Location currentLocation, Track.Id currentTrackId, long currentTimestamp) {
|
||||||
this.textQuery = textQuery.toLowerCase(Locale.getDefault());
|
this.textQuery = textQuery.toLowerCase(Locale.getDefault());
|
||||||
this.currentLocation = currentLocation;
|
this.currentLocation = currentLocation;
|
||||||
this.currentTrackId = currentTrackId;
|
this.currentTrackId = currentTrackId;
|
||||||
@@ -420,8 +417,8 @@ public class SearchEngine {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ScoredResult ["
|
return "ScoredResult ["
|
||||||
+ (track != null ? ("trackId=" + track.getId() + ", ") : "")
|
+ (track != null ? ("trackId=" + track.getId().getId() + ", ") : "")
|
||||||
+ (waypoint != null ? ("wptId=" + waypoint.getId() + ", ") : "")
|
+ (waypoint != null ? ("wptId=" + waypoint.getId().getId() + ", ") : "")
|
||||||
+ "score=" + score + "]";
|
+ "score=" + score + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.os.Handler;
|
|||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -78,8 +79,8 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
|||||||
private Handler handler;
|
private Handler handler;
|
||||||
|
|
||||||
// Preference values
|
// Preference values
|
||||||
private long selectedTrackId;
|
private Track.Id selectedTrackId;
|
||||||
private long recordingTrackId;
|
private Track.Id recordingTrackId;
|
||||||
private boolean recordingTrackPaused;
|
private boolean recordingTrackPaused;
|
||||||
|
|
||||||
// Track points sampling state
|
// Track points sampling state
|
||||||
@@ -144,12 +145,9 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
|||||||
|
|
||||||
PreferencesUtils.register(context, this);
|
PreferencesUtils.register(context, this);
|
||||||
onSharedPreferenceChanged(null, null);
|
onSharedPreferenceChanged(null, null);
|
||||||
runInHandlerThread(new Runnable() {
|
runInHandlerThread(() -> {
|
||||||
@Override
|
if (started) {
|
||||||
public void run() {
|
loadDataForAll();
|
||||||
if (started) {
|
|
||||||
loadDataForAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -177,17 +175,14 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
|||||||
handler = null;
|
handler = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadTrack(final long trackId) {
|
public void loadTrack(final @NonNull Track.Id trackId) {
|
||||||
runInHandlerThread(new Runnable() {
|
runInHandlerThread(() -> {
|
||||||
@Override
|
if (trackId.equals(selectedTrackId)) {
|
||||||
public void run() {
|
Log.i(TAG, "Not reloading track " + trackId.getId());
|
||||||
if (trackId == selectedTrackId) {
|
return;
|
||||||
Log.i(TAG, "Not reloading track " + trackId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
selectedTrackId = trackId;
|
|
||||||
loadDataForAll();
|
|
||||||
}
|
}
|
||||||
|
selectedTrackId = trackId;
|
||||||
|
loadDataForAll();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,13 +192,10 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
|||||||
* @param trackDataListener the track data listener
|
* @param trackDataListener the track data listener
|
||||||
*/
|
*/
|
||||||
public void registerTrackDataListener(final TrackDataListener trackDataListener, final boolean tracksTable, final boolean waypointsTable, final boolean trackPointsTable_SampleIn, final boolean trackPointsTable_SampleOut) {
|
public void registerTrackDataListener(final TrackDataListener trackDataListener, final boolean tracksTable, final boolean waypointsTable, final boolean trackPointsTable_SampleIn, final boolean trackPointsTable_SampleOut) {
|
||||||
runInHandlerThread(new Runnable() {
|
runInHandlerThread(() -> {
|
||||||
@Override
|
trackDataManager.registerTrackDataListener(trackDataListener, tracksTable, waypointsTable, trackPointsTable_SampleIn, trackPointsTable_SampleOut);
|
||||||
public void run() {
|
if (started) {
|
||||||
trackDataManager.registerTrackDataListener(trackDataListener, tracksTable, waypointsTable, trackPointsTable_SampleIn, trackPointsTable_SampleOut);
|
loadDataForListener(trackDataListener);
|
||||||
if (started) {
|
|
||||||
loadDataForListener(trackDataListener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -214,39 +206,31 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
|||||||
* @param trackDataListener the track data listener
|
* @param trackDataListener the track data listener
|
||||||
*/
|
*/
|
||||||
public void unregisterTrackDataListener(final TrackDataListener trackDataListener) {
|
public void unregisterTrackDataListener(final TrackDataListener trackDataListener) {
|
||||||
runInHandlerThread(new Runnable() {
|
runInHandlerThread(() -> trackDataManager.unregisterTrackDataListener(trackDataListener));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
trackDataManager.unregisterTrackDataListener(trackDataListener);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the selected track is recording.
|
* Returns true if the selected track is recording.
|
||||||
*/
|
*/
|
||||||
public boolean isSelectedTrackRecording() {
|
public boolean isSelectedTrackRecording() {
|
||||||
return selectedTrackId == recordingTrackId && PreferencesUtils.isRecording(recordingTrackId);
|
return selectedTrackId != null && selectedTrackId.equals(recordingTrackId) && PreferencesUtils.isRecording(recordingTrackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the selected track is paused.
|
* Returns true if the selected track is paused.
|
||||||
*/
|
*/
|
||||||
public boolean isSelectedTrackPaused() {
|
public boolean isSelectedTrackPaused() {
|
||||||
return selectedTrackId == recordingTrackId && recordingTrackPaused;
|
return selectedTrackId != null && selectedTrackId.equals(recordingTrackId) && recordingTrackPaused;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, final String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, final String key) {
|
||||||
runInHandlerThread(new Runnable() {
|
runInHandlerThread(() -> {
|
||||||
@Override
|
if (PreferencesUtils.isKey(context, R.string.recording_track_id_key, key)) {
|
||||||
public void run() {
|
recordingTrackId = PreferencesUtils.getRecordingTrackId(context);
|
||||||
if (PreferencesUtils.isKey(context, R.string.recording_track_id_key, key)) {
|
}
|
||||||
recordingTrackId = PreferencesUtils.getRecordingTrackId(context);
|
if (PreferencesUtils.isKey(context, R.string.recording_track_paused_key, key)) {
|
||||||
}
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(context);
|
||||||
if (PreferencesUtils.isKey(context, R.string.recording_track_paused_key, key)) {
|
|
||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -289,7 +273,7 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
|||||||
if (isOnlyListener) {
|
if (isOnlyListener) {
|
||||||
resetSamplingState();
|
resetSamplingState();
|
||||||
}
|
}
|
||||||
Set<TrackDataListener> sampledOutListeners = hasSampledOut ? trackDataListeners : Collections.<TrackDataListener>emptySet();
|
Set<TrackDataListener> sampledOutListeners = hasSampledOut ? trackDataListeners : Collections.emptySet();
|
||||||
notifyTrackPointsTableUpdate(isOnlyListener, trackDataListeners, sampledOutListeners);
|
notifyTrackPointsTableUpdate(isOnlyListener, trackDataListeners, sampledOutListeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +312,7 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
|||||||
trackDataListener.clearWaypoints();
|
trackDataListener.clearWaypoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Cursor cursor = contentProviderUtils.getWaypointCursor(selectedTrackId, -1L, MAX_DISPLAYED_WAYPOINTS)) {
|
try (Cursor cursor = contentProviderUtils.getWaypointCursor(selectedTrackId, null, MAX_DISPLAYED_WAYPOINTS)) {
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
Waypoint waypoint = contentProviderUtils.createWaypoint(cursor);
|
Waypoint waypoint = contentProviderUtils.createWaypoint(cursor);
|
||||||
@@ -373,6 +357,11 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
|||||||
long localLastSeenTrackPointIdId = updateSamplingState ? lastSeenTrackPointId : -1L;
|
long localLastSeenTrackPointIdId = updateSamplingState ? lastSeenTrackPointId : -1L;
|
||||||
long maxPointId = updateSamplingState ? -1L : lastSeenTrackPointId;
|
long maxPointId = updateSamplingState ? -1L : lastSeenTrackPointId;
|
||||||
|
|
||||||
|
if (selectedTrackId == null) {
|
||||||
|
Log.w(TAG, "This should not happen, but it does"); //TODO
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
long lastTrackPointId = contentProviderUtils.getLastTrackPointId(selectedTrackId);
|
long lastTrackPointId = contentProviderUtils.getLastTrackPointId(selectedTrackId);
|
||||||
int samplingFrequency = -1;
|
int samplingFrequency = -1;
|
||||||
boolean includeNextPoint = false;
|
boolean includeNextPoint = false;
|
||||||
|
|||||||
@@ -16,7 +16,17 @@
|
|||||||
|
|
||||||
package de.dennisguse.opentracks.content.data;
|
package de.dennisguse.opentracks.content.data;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A track.
|
* A track.
|
||||||
@@ -26,7 +36,9 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
|||||||
*/
|
*/
|
||||||
public class Track {
|
public class Track {
|
||||||
|
|
||||||
private long id = -1L;
|
private Track.Id id;
|
||||||
|
private UUID uuid = UUID.randomUUID();
|
||||||
|
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private String description = "";
|
private String description = "";
|
||||||
private String category = "";
|
private String category = "";
|
||||||
@@ -38,14 +50,26 @@ public class Track {
|
|||||||
public Track() {
|
public Track() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
/**
|
||||||
|
* May be null if the track was not loaded from the database.
|
||||||
|
*/
|
||||||
|
public @Nullable
|
||||||
|
Id getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(long id) {
|
public void setId(Id id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(UUID uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -85,4 +109,66 @@ public class Track {
|
|||||||
public void setTrackStatistics(TrackStatistics trackStatistics) {
|
public void setTrackStatistics(TrackStatistics trackStatistics) {
|
||||||
this.trackStatistics = trackStatistics;
|
this.trackStatistics = trackStatistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Id implements Parcelable {
|
||||||
|
|
||||||
|
private final long id;
|
||||||
|
|
||||||
|
public Id(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Id(@NonNull String id) {
|
||||||
|
this(Long.parseLong(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
//TOOD Limit visibility to TrackRecordingService / ContentProvider
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated //TODO Use a Track.Id of null instead
|
||||||
|
public boolean isValid() {
|
||||||
|
return id != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Id id1 = (Id) o;
|
||||||
|
return id == id1.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
throw new RuntimeException("Not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel parcel, int i) {
|
||||||
|
parcel.writeLong(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<Track.Id> CREATOR = new Parcelable.Creator<Track.Id>() {
|
||||||
|
public Track.Id createFromParcel(Parcel in) {
|
||||||
|
return new Track.Id(in.readLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Track.Id[] newArray(int size) {
|
||||||
|
return new Track.Id[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public interface TrackPointsColumns extends BaseColumns {
|
|||||||
Uri CONTENT_URI_BY_TRACKID = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TABLE_NAME + "/trackid");
|
Uri CONTENT_URI_BY_TRACKID = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TABLE_NAME + "/trackid");
|
||||||
String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.de.dennisguse.trackpoint";
|
String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.de.dennisguse.trackpoint";
|
||||||
String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.de.dennisguse.trackpoint";
|
String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.de.dennisguse.trackpoint";
|
||||||
String DEFAULT_SORT_ORDER = "_id";
|
String DEFAULT_SORT_ORDER = _ID;
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
String TRACKID = "trackid";
|
String TRACKID = "trackid";
|
||||||
|
|||||||
@@ -32,9 +32,10 @@ public interface TracksColumns extends BaseColumns {
|
|||||||
Uri CONTENT_URI = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TABLE_NAME);
|
Uri CONTENT_URI = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TABLE_NAME);
|
||||||
String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.de.dennisguse.track";
|
String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.de.dennisguse.track";
|
||||||
String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.de.dennisguse.track";
|
String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.de.dennisguse.track";
|
||||||
String DEFAULT_SORT_ORDER = "_id";
|
String DEFAULT_SORT_ORDER = _ID;
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
String UUID = "uuid";
|
||||||
String NAME = "name"; // track name
|
String NAME = "name"; // track name
|
||||||
String DESCRIPTION = "description"; // track description
|
String DESCRIPTION = "description"; // track description
|
||||||
String CATEGORY = "category"; // track activity type
|
String CATEGORY = "category"; // track activity type
|
||||||
@@ -71,5 +72,9 @@ public interface TracksColumns extends BaseColumns {
|
|||||||
+ MINELEVATION + " FLOAT, " // min elevation
|
+ MINELEVATION + " FLOAT, " // min elevation
|
||||||
+ MAXELEVATION + " FLOAT, " // max elevation
|
+ MAXELEVATION + " FLOAT, " // max elevation
|
||||||
+ ELEVATIONGAIN + " FLOAT, " // elevation gain
|
+ ELEVATIONGAIN + " FLOAT, " // elevation gain
|
||||||
+ ICON + " TEXT)"; // icon
|
+ ICON + " TEXT, " // icon
|
||||||
|
+ UUID + " BLOB)"; // UUID
|
||||||
|
|
||||||
|
String CREATE_TABLE_INDEX = "CREATE UNIQUE INDEX " + TABLE_NAME + "_" + UUID + "_index ON " + TABLE_NAME + "(" + UUID + ")";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,17 @@ package de.dennisguse.opentracks.content.data;
|
|||||||
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A waypoint.
|
* A waypoint.
|
||||||
*
|
*
|
||||||
@@ -30,15 +37,16 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
*/
|
*/
|
||||||
public final class Waypoint {
|
public final class Waypoint {
|
||||||
|
|
||||||
private long id = -1L;
|
private Id id;
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private String description = "";
|
private String description = "";
|
||||||
private String category = "";
|
private String category = "";
|
||||||
private String icon = "";
|
private String icon = "";
|
||||||
private long trackId = -1L;
|
private Track.Id trackId;
|
||||||
private double length = 0.0;
|
private double length = 0.0;
|
||||||
private long duration = 0;
|
private long duration = 0;
|
||||||
private Location location;
|
private Location location;
|
||||||
|
@Deprecated //TODO Make an URI instead of String
|
||||||
private String photoUrl = "";
|
private String photoUrl = "";
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -50,7 +58,7 @@ public final class Waypoint {
|
|||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Waypoint(String name, String description, String category, String icon, long trackId, double length, long duration, @NonNull Location location, String photoUrl) {
|
public Waypoint(String name, String description, String category, String icon, @NonNull Track.Id trackId, double length, long duration, @NonNull Location location, String photoUrl) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.category = category;
|
this.category = category;
|
||||||
@@ -62,11 +70,15 @@ public final class Waypoint {
|
|||||||
this.photoUrl = photoUrl;
|
this.photoUrl = photoUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
/**
|
||||||
|
* May be null if the waypoint was not loaded from the database.
|
||||||
|
*/
|
||||||
|
public @Nullable
|
||||||
|
Id getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(long id) {
|
public void setId(Id id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,11 +114,11 @@ public final class Waypoint {
|
|||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTrackId() {
|
public Track.Id getTrackId() {
|
||||||
return trackId;
|
return trackId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTrackId(long trackId) {
|
public void setTrackId(Track.Id trackId) {
|
||||||
this.trackId = trackId;
|
this.trackId = trackId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,4 +158,66 @@ public final class Waypoint {
|
|||||||
public boolean hasPhoto() {
|
public boolean hasPhoto() {
|
||||||
return photoUrl != null && !"".equals(photoUrl);
|
return photoUrl != null && !"".equals(photoUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Id implements Parcelable {
|
||||||
|
|
||||||
|
private final long id;
|
||||||
|
|
||||||
|
public Id(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Id(@NonNull String id) {
|
||||||
|
this(Long.parseLong(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
//TOOD Limit visibility to TrackRecordingService / ContentProvider
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated //TODO Use a Waypoint.Id of null instead
|
||||||
|
public boolean isValid() {
|
||||||
|
return id != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Id id1 = (Id) o;
|
||||||
|
return id == id1.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
throw new RuntimeException("Not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel parcel, int i) {
|
||||||
|
parcel.writeLong(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<Id> CREATOR = new Parcelable.Creator<Id>() {
|
||||||
|
public Id createFromParcel(Parcel in) {
|
||||||
|
return new Id(in.readLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Id[] newArray(int size) {
|
||||||
|
return new Id[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ public interface WaypointsColumns extends BaseColumns {
|
|||||||
|
|
||||||
String TABLE_NAME = "waypoints";
|
String TABLE_NAME = "waypoints";
|
||||||
Uri CONTENT_URI = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TABLE_NAME);
|
Uri CONTENT_URI = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TABLE_NAME);
|
||||||
|
Uri CONTENT_URI_BY_TRACKID = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TABLE_NAME + "/trackid");
|
||||||
String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.de.dennisguse.waypoint";
|
String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.de.dennisguse.waypoint";
|
||||||
String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.de.dennisguse.waypoint";
|
String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.de.dennisguse.waypoint";
|
||||||
String DEFAULT_SORT_ORDER = "_id";
|
String DEFAULT_SORT_ORDER = _ID;
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
String NAME = "name"; // waypoint name
|
String NAME = "name"; // waypoint name
|
||||||
|
|||||||
@@ -23,13 +23,19 @@ import android.database.Cursor;
|
|||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
import androidx.loader.content.CursorLoader;
|
||||||
|
import androidx.loader.content.Loader;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.BuildConfig;
|
import de.dennisguse.opentracks.BuildConfig;
|
||||||
import de.dennisguse.opentracks.android.ContentResolverWrapper;
|
import de.dennisguse.opentracks.android.ContentResolverWrapper;
|
||||||
@@ -42,6 +48,8 @@ import de.dennisguse.opentracks.content.data.Waypoint;
|
|||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.util.FileUtils;
|
import de.dennisguse.opentracks.util.FileUtils;
|
||||||
|
import de.dennisguse.opentracks.util.TrackUtils;
|
||||||
|
import de.dennisguse.opentracks.util.UUIDUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ContentProviderUtils} implementation.
|
* {@link ContentProviderUtils} implementation.
|
||||||
@@ -55,7 +63,8 @@ public class ContentProviderUtils {
|
|||||||
private static final int MAX_LATITUDE = 90000000;
|
private static final int MAX_LATITUDE = 90000000;
|
||||||
|
|
||||||
// The authority (the first part of the URI) for the app's content provider.
|
// The authority (the first part of the URI) for the app's content provider.
|
||||||
static final String AUTHORITY_PACKAGE = BuildConfig.APPLICATION_ID + ".content";
|
@VisibleForTesting
|
||||||
|
public static final String AUTHORITY_PACKAGE = BuildConfig.APPLICATION_ID + ".content";
|
||||||
|
|
||||||
// The base URI for the app's content provider.
|
// The base URI for the app's content provider.
|
||||||
public static final String CONTENT_BASE_URI = "content://" + AUTHORITY_PACKAGE;
|
public static final String CONTENT_BASE_URI = "content://" + AUTHORITY_PACKAGE;
|
||||||
@@ -85,8 +94,8 @@ public class ContentProviderUtils {
|
|||||||
*
|
*
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
public void clearTrack(Context context, long trackId) {
|
public void clearTrack(Track.Id trackId) {
|
||||||
deleteTrackPointsAndWaypoints(context, trackId);
|
deleteTrackPointsAndWaypoints(trackId);
|
||||||
Track track = new Track();
|
Track track = new Track();
|
||||||
track.setId(trackId);
|
track.setId(trackId);
|
||||||
updateTrack(track);
|
updateTrack(track);
|
||||||
@@ -99,6 +108,7 @@ public class ContentProviderUtils {
|
|||||||
*/
|
*/
|
||||||
public Track createTrack(Cursor cursor) {
|
public Track createTrack(Cursor cursor) {
|
||||||
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
|
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
|
||||||
|
int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID);
|
||||||
int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME);
|
int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME);
|
||||||
int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
|
int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
|
||||||
int categoryIndex = cursor.getColumnIndexOrThrow(TracksColumns.CATEGORY);
|
int categoryIndex = cursor.getColumnIndexOrThrow(TracksColumns.CATEGORY);
|
||||||
@@ -116,7 +126,10 @@ public class ContentProviderUtils {
|
|||||||
Track track = new Track();
|
Track track = new Track();
|
||||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||||
if (!cursor.isNull(idIndex)) {
|
if (!cursor.isNull(idIndex)) {
|
||||||
track.setId(cursor.getLong(idIndex));
|
track.setId(new Track.Id(cursor.getLong(idIndex)));
|
||||||
|
}
|
||||||
|
if (!cursor.isNull(uuidIndex)) {
|
||||||
|
track.setUuid(UUIDUtils.fromBytes(cursor.getBlob(uuidIndex)));
|
||||||
}
|
}
|
||||||
if (!cursor.isNull(nameIndex)) {
|
if (!cursor.isNull(nameIndex)) {
|
||||||
track.setName(cursor.getString(nameIndex));
|
track.setName(cursor.getString(nameIndex));
|
||||||
@@ -160,9 +173,7 @@ public class ContentProviderUtils {
|
|||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@VisibleForTesting
|
||||||
* Deletes all tracks (including waypoints and trackPoints).
|
|
||||||
*/
|
|
||||||
public void deleteAllTracks(Context context) {
|
public void deleteAllTracks(Context context) {
|
||||||
contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, null, null);
|
contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, null, null);
|
||||||
contentResolver.delete(WaypointsColumns.CONTENT_URI, null, null);
|
contentResolver.delete(WaypointsColumns.CONTENT_URI, null, null);
|
||||||
@@ -178,14 +189,17 @@ public class ContentProviderUtils {
|
|||||||
*
|
*
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
public void deleteTrack(Context context, long trackId) {
|
public void deleteTrack(Context context, Track.Id trackId) {
|
||||||
deleteTrackPointsAndWaypoints(context, trackId);
|
if (trackId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deleteTrackPointsAndWaypoints(trackId);
|
||||||
|
|
||||||
// Delete track folder resources.
|
// Delete track folder resources.
|
||||||
FileUtils.deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId));
|
FileUtils.deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId));
|
||||||
|
|
||||||
// Delete track last since it triggers a database vacuum call
|
// Delete track last since it triggers a database vacuum call
|
||||||
contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", new String[]{Long.toString(trackId)});
|
contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", new String[]{Long.toString(trackId.getId())});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -193,21 +207,15 @@ public class ContentProviderUtils {
|
|||||||
*
|
*
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
private void deleteTrackPointsAndWaypoints(Context context, long trackId) {
|
private void deleteTrackPointsAndWaypoints(@NonNull Track.Id trackId) {
|
||||||
String where = TrackPointsColumns.TRACKID + "=?";
|
String[] selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||||
String[] selectionArgs = new String[]{Long.toString(trackId)};
|
|
||||||
contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, where, selectionArgs);
|
|
||||||
|
|
||||||
contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns.TRACKID + "=?", new String[]{Long.toString(trackId)});
|
contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, TrackPointsColumns.TRACKID + "=?", selectionArgs);
|
||||||
|
contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns.TRACKID + "=?", selectionArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all the tracks.
|
|
||||||
*
|
|
||||||
* @return the tracks do not have any trackPoints attached.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public List<Track> getAllTracks() {
|
public List<Track> getTracks() {
|
||||||
ArrayList<Track> tracks = new ArrayList<>();
|
ArrayList<Track> tracks = new ArrayList<>();
|
||||||
try (Cursor cursor = getTrackCursor(null, null, TracksColumns._ID)) {
|
try (Cursor cursor = getTrackCursor(null, null, TracksColumns._ID)) {
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
@@ -220,6 +228,17 @@ public class ContentProviderUtils {
|
|||||||
return tracks;
|
return tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Loader<Cursor> getTracksCursorLoader(Context context) {
|
||||||
|
String[] PROJECTION = new String[]{TracksColumns._ID, TracksColumns.NAME,
|
||||||
|
TracksColumns.DESCRIPTION, TracksColumns.CATEGORY, TracksColumns.STARTTIME,
|
||||||
|
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON};
|
||||||
|
|
||||||
|
return new CursorLoader(context, TracksColumns.CONTENT_URI, PROJECTION, null, null, TrackUtils.TRACK_SORT_ORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
//TODO Do not use; rather get the proper TrackId (e.g., resume a track might give you some weird effects).
|
||||||
|
@VisibleForTesting
|
||||||
public Track getLastTrack() {
|
public Track getLastTrack() {
|
||||||
try (Cursor cursor = getTrackCursor(null, null, TracksColumns.STARTTIME + " DESC")) {
|
try (Cursor cursor = getTrackCursor(null, null, TracksColumns.STARTTIME + " DESC")) {
|
||||||
// Using the same order as shown in the track list
|
// Using the same order as shown in the track list
|
||||||
@@ -232,13 +251,25 @@ public class ContentProviderUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param trackId the track id.
|
* @param trackId the track id.
|
||||||
* @return the track doesn't have any trackPoints attached
|
|
||||||
*/
|
*/
|
||||||
public Track getTrack(long trackId) {
|
public Track getTrack(Track.Id trackId) {
|
||||||
if (trackId < 0) {
|
if (trackId == null || !trackId.isValid()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try (Cursor cursor = getTrackCursor(TracksColumns._ID + "=?", new String[]{Long.toString(trackId)}, TracksColumns._ID)) {
|
try (Cursor cursor = getTrackCursor(TracksColumns._ID + "=?", new String[]{Long.toString(trackId.getId())}, null)) {
|
||||||
|
if (cursor != null && cursor.moveToNext()) {
|
||||||
|
return createTrack(cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param trackUUID the track uuid.
|
||||||
|
*/
|
||||||
|
public Track getTrack(@NonNull UUID trackUUID) {
|
||||||
|
String trackUUIDsearch = UUIDUtils.toHex(trackUUID);
|
||||||
|
try (Cursor cursor = getTrackCursor("hex(" + TracksColumns.UUID + ")=?", new String[]{trackUUIDsearch}, null)) {
|
||||||
if (cursor != null && cursor.moveToNext()) {
|
if (cursor != null && cursor.moveToNext()) {
|
||||||
return createTrack(cursor);
|
return createTrack(cursor);
|
||||||
}
|
}
|
||||||
@@ -276,7 +307,7 @@ public class ContentProviderUtils {
|
|||||||
* @param track the track
|
* @param track the track
|
||||||
*/
|
*/
|
||||||
public void updateTrack(Track track) {
|
public void updateTrack(Track track) {
|
||||||
contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.getId())});
|
contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.getId().getId())});
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContentValues createContentValues(Track track) {
|
private ContentValues createContentValues(Track track) {
|
||||||
@@ -284,9 +315,10 @@ public class ContentProviderUtils {
|
|||||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||||
|
|
||||||
// Value < 0 indicates no id is available
|
// Value < 0 indicates no id is available
|
||||||
if (track.getId() >= 0) {
|
if (track.getId() != null && track.getId().isValid()) {
|
||||||
values.put(TracksColumns._ID, track.getId());
|
values.put(TracksColumns._ID, track.getId().getId());
|
||||||
}
|
}
|
||||||
|
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid()));
|
||||||
values.put(TracksColumns.NAME, track.getName());
|
values.put(TracksColumns.NAME, track.getName());
|
||||||
values.put(TracksColumns.DESCRIPTION, track.getDescription());
|
values.put(TracksColumns.DESCRIPTION, track.getDescription());
|
||||||
values.put(TracksColumns.CATEGORY, track.getCategory());
|
values.put(TracksColumns.CATEGORY, track.getCategory());
|
||||||
@@ -350,7 +382,7 @@ public class ContentProviderUtils {
|
|||||||
Waypoint waypoint = new Waypoint(location);
|
Waypoint waypoint = new Waypoint(location);
|
||||||
|
|
||||||
if (!cursor.isNull(idIndex)) {
|
if (!cursor.isNull(idIndex)) {
|
||||||
waypoint.setId(cursor.getLong(idIndex));
|
waypoint.setId(new Waypoint.Id(cursor.getLong(idIndex)));
|
||||||
}
|
}
|
||||||
if (!cursor.isNull(nameIndex)) {
|
if (!cursor.isNull(nameIndex)) {
|
||||||
waypoint.setName(cursor.getString(nameIndex));
|
waypoint.setName(cursor.getString(nameIndex));
|
||||||
@@ -365,7 +397,7 @@ public class ContentProviderUtils {
|
|||||||
waypoint.setIcon(cursor.getString(iconIndex));
|
waypoint.setIcon(cursor.getString(iconIndex));
|
||||||
}
|
}
|
||||||
if (!cursor.isNull(trackIdIndex)) {
|
if (!cursor.isNull(trackIdIndex)) {
|
||||||
waypoint.setTrackId(cursor.getLong(trackIdIndex));
|
waypoint.setTrackId(new Track.Id(cursor.getLong(trackIdIndex)));
|
||||||
}
|
}
|
||||||
if (!cursor.isNull(lengthIndex)) {
|
if (!cursor.isNull(lengthIndex)) {
|
||||||
waypoint.setLength(cursor.getFloat(lengthIndex));
|
waypoint.setLength(cursor.getFloat(lengthIndex));
|
||||||
@@ -380,10 +412,10 @@ public class ContentProviderUtils {
|
|||||||
return waypoint;
|
return waypoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteWaypoint(Context context, long waypointId) {
|
public void deleteWaypoint(Context context, Waypoint.Id waypointId) {
|
||||||
final Waypoint waypoint = getWaypoint(waypointId);
|
final Waypoint waypoint = getWaypoint(waypointId);
|
||||||
deleteWaypointPhoto(context, waypoint);
|
deleteWaypointPhoto(context, waypoint);
|
||||||
contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns._ID + "=?", new String[]{Long.toString(waypointId)});
|
contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns._ID + "=?", new String[]{Long.toString(waypointId.getId())});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -392,13 +424,13 @@ public class ContentProviderUtils {
|
|||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
* @return -1 if not able to get the next waypoint number.
|
* @return -1 if not able to get the next waypoint number.
|
||||||
*/
|
*/
|
||||||
public int getNextWaypointNumber(long trackId) {
|
public int getNextWaypointNumber(Track.Id trackId) {
|
||||||
if (trackId < 0) {
|
if (!trackId.isValid()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
String[] projection = {WaypointsColumns._ID};
|
String[] projection = {WaypointsColumns._ID};
|
||||||
String selection = WaypointsColumns.TRACKID + "=?";
|
String selection = WaypointsColumns.TRACKID + "=?";
|
||||||
String[] selectionArgs = new String[]{Long.toString(trackId)};
|
String[] selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||||
try (Cursor cursor = getWaypointCursor(projection, selection, selectionArgs, WaypointsColumns._ID, -1)) {
|
try (Cursor cursor = getWaypointCursor(projection, selection, selectionArgs, WaypointsColumns._ID, -1)) {
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
return cursor.getCount();
|
return cursor.getCount();
|
||||||
@@ -407,12 +439,12 @@ public class ContentProviderUtils {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Waypoint getWaypoint(long waypointId) {
|
public Waypoint getWaypoint(Waypoint.Id waypointId) {
|
||||||
if (waypointId < 0) {
|
if (!waypointId.isValid()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try (Cursor cursor = getWaypointCursor(null, WaypointsColumns._ID + "=?",
|
try (Cursor cursor = getWaypointCursor(null, WaypointsColumns._ID + "=?",
|
||||||
new String[]{Long.toString(waypointId)}, WaypointsColumns._ID, 1)) {
|
new String[]{Long.toString(waypointId.getId())}, WaypointsColumns._ID, 1)) {
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
return createWaypoint(cursor);
|
return createWaypoint(cursor);
|
||||||
}
|
}
|
||||||
@@ -438,30 +470,30 @@ public class ContentProviderUtils {
|
|||||||
* The caller owns the returned cursor and is responsible for closing it.
|
* The caller owns the returned cursor and is responsible for closing it.
|
||||||
*
|
*
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
* @param minWaypointId the minimum waypoint id. -1L to ignore
|
* @param minWaypointId the minimum waypoint id. null to ignore
|
||||||
* @param maxWaypoints the maximum number of waypoints to return. -1 for no limit
|
* @param maxWaypoints the maximum number of waypoints to return. -1 for no limit
|
||||||
*/
|
*/
|
||||||
public Cursor getWaypointCursor(long trackId, long minWaypointId, int maxWaypoints) {
|
public Cursor getWaypointCursor(Track.Id trackId, @Nullable Waypoint.Id minWaypointId, int maxWaypoints) {
|
||||||
if (trackId < 0) {
|
if (!trackId.isValid()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String selection;
|
String selection;
|
||||||
String[] selectionArgs;
|
String[] selectionArgs;
|
||||||
if (minWaypointId >= 0) {
|
if (minWaypointId != null && minWaypointId.isValid()) {
|
||||||
selection = WaypointsColumns.TRACKID + "=? AND " + WaypointsColumns._ID + ">=?";
|
selection = WaypointsColumns.TRACKID + "=? AND " + WaypointsColumns._ID + ">=?";
|
||||||
selectionArgs = new String[]{Long.toString(trackId), Long.toString(minWaypointId)};
|
selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(minWaypointId.getId())};
|
||||||
} else {
|
} else {
|
||||||
selection = WaypointsColumns.TRACKID + "=?";
|
selection = WaypointsColumns.TRACKID + "=?";
|
||||||
selectionArgs = new String[]{Long.toString(trackId)};
|
selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||||
}
|
}
|
||||||
return getWaypointCursor(null, selection, selectionArgs, WaypointsColumns._ID, maxWaypoints);
|
return getWaypointCursor(null, selection, selectionArgs, WaypointsColumns._ID, maxWaypoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public List<Waypoint> getWaypoints(long trackId) {
|
public List<Waypoint> getWaypoints(Track.Id trackId) {
|
||||||
ArrayList<Waypoint> waypoints = new ArrayList<>();
|
ArrayList<Waypoint> waypoints = new ArrayList<>();
|
||||||
try (Cursor cursor = getWaypointCursor(trackId, -1L, -1)) {
|
try (Cursor cursor = getWaypointCursor(trackId, null, -1)) {
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
waypoints.add(createWaypoint(cursor));
|
waypoints.add(createWaypoint(cursor));
|
||||||
@@ -471,19 +503,34 @@ public class ContentProviderUtils {
|
|||||||
return waypoints;
|
return waypoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Loader<Cursor> getWaypointsLoader(Context context, @Nullable Track.Id trackId) {
|
||||||
|
final String[] PROJECTION = new String[]{WaypointsColumns._ID,
|
||||||
|
WaypointsColumns.NAME, WaypointsColumns.DESCRIPTION, WaypointsColumns.CATEGORY,
|
||||||
|
WaypointsColumns.TIME, WaypointsColumns.PHOTOURL,
|
||||||
|
WaypointsColumns.LATITUDE, WaypointsColumns.LONGITUDE};
|
||||||
|
|
||||||
|
if (trackId != null) {
|
||||||
|
return new CursorLoader(context, WaypointsColumns.CONTENT_URI, PROJECTION,
|
||||||
|
WaypointsColumns.TRACKID + "=?",
|
||||||
|
new String[]{String.valueOf(trackId.getId())}, null);
|
||||||
|
} else {
|
||||||
|
return new CursorLoader(context, WaypointsColumns.CONTENT_URI, PROJECTION, null, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of waypoints for a track.
|
* Gets the number of waypoints for a track.
|
||||||
*
|
*
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
public int getWaypointCount(long trackId) {
|
public int getWaypointCount(Track.Id trackId) {
|
||||||
if (trackId < 0) {
|
if (!trackId.isValid()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] projection = new String[]{"count(*) AS count"};
|
String[] projection = new String[]{"count(*) AS count"};
|
||||||
String selection = WaypointsColumns.TRACKID + "=?";
|
String selection = WaypointsColumns.TRACKID + "=?";
|
||||||
String[] selectionArgs = new String[]{Long.toString(trackId)};
|
String[] selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||||
try (Cursor cursor = contentResolver.query(WaypointsColumns.CONTENT_URI, projection, selection, selectionArgs, WaypointsColumns._ID)) {
|
try (Cursor cursor = contentResolver.query(WaypointsColumns.CONTENT_URI, projection, selection, selectionArgs, WaypointsColumns._ID)) {
|
||||||
if (cursor == null) {
|
if (cursor == null) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -499,8 +546,8 @@ public class ContentProviderUtils {
|
|||||||
* @param waypoint the waypoint
|
* @param waypoint the waypoint
|
||||||
* @return the content provider URI of the inserted waypoint.
|
* @return the content provider URI of the inserted waypoint.
|
||||||
*/
|
*/
|
||||||
public Uri insertWaypoint(Waypoint waypoint) {
|
public Uri insertWaypoint(@NonNull Waypoint waypoint) {
|
||||||
waypoint.setId(-1L);
|
waypoint.setId(null);
|
||||||
return contentResolver.insert(WaypointsColumns.CONTENT_URI, createContentValues(waypoint));
|
return contentResolver.insert(WaypointsColumns.CONTENT_URI, createContentValues(waypoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,22 +582,23 @@ public class ContentProviderUtils {
|
|||||||
if (!updatedWaypoint.hasPhoto()) {
|
if (!updatedWaypoint.hasPhoto()) {
|
||||||
deleteWaypointPhoto(context, savedWaypoint);
|
deleteWaypointPhoto(context, savedWaypoint);
|
||||||
}
|
}
|
||||||
int rows = contentResolver.update(WaypointsColumns.CONTENT_URI, createContentValues(updatedWaypoint), WaypointsColumns._ID + "=?", new String[]{Long.toString(updatedWaypoint.getId())});
|
int rows = contentResolver.update(WaypointsColumns.CONTENT_URI, createContentValues(updatedWaypoint), WaypointsColumns._ID + "=?", new String[]{Long.toString(updatedWaypoint.getId().getId())});
|
||||||
return rows == 1;
|
return rows == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentValues createContentValues(Waypoint waypoint) {
|
ContentValues createContentValues(@NonNull Waypoint waypoint) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
|
|
||||||
// Value < 0 indicates no id is available
|
if (waypoint.getId() != null && waypoint.getId().isValid()) {
|
||||||
if (waypoint.getId() >= 0) {
|
values.put(WaypointsColumns._ID, waypoint.getId().getId());
|
||||||
values.put(WaypointsColumns._ID, waypoint.getId());
|
|
||||||
}
|
}
|
||||||
values.put(WaypointsColumns.NAME, waypoint.getName());
|
values.put(WaypointsColumns.NAME, waypoint.getName());
|
||||||
values.put(WaypointsColumns.DESCRIPTION, waypoint.getDescription());
|
values.put(WaypointsColumns.DESCRIPTION, waypoint.getDescription());
|
||||||
values.put(WaypointsColumns.CATEGORY, waypoint.getCategory());
|
values.put(WaypointsColumns.CATEGORY, waypoint.getCategory());
|
||||||
values.put(WaypointsColumns.ICON, waypoint.getIcon());
|
values.put(WaypointsColumns.ICON, waypoint.getIcon());
|
||||||
values.put(WaypointsColumns.TRACKID, waypoint.getTrackId());
|
if (waypoint.getTrackId() != null) {
|
||||||
|
values.put(WaypointsColumns.TRACKID, waypoint.getTrackId().getId());
|
||||||
|
}
|
||||||
values.put(WaypointsColumns.LENGTH, waypoint.getLength());
|
values.put(WaypointsColumns.LENGTH, waypoint.getLength());
|
||||||
values.put(WaypointsColumns.DURATION, waypoint.getDuration());
|
values.put(WaypointsColumns.DURATION, waypoint.getDuration());
|
||||||
|
|
||||||
@@ -643,7 +691,7 @@ public class ContentProviderUtils {
|
|||||||
* @return the number of trackPoints inserted
|
* @return the number of trackPoints inserted
|
||||||
*/
|
*/
|
||||||
//TODO Only used for testing and file import; might be better to replace it.
|
//TODO Only used for testing and file import; might be better to replace it.
|
||||||
public int bulkInsertTrackPoint(TrackPoint[] trackPoints, long trackId) {
|
public int bulkInsertTrackPoint(TrackPoint[] trackPoints, Track.Id trackId) {
|
||||||
ContentValues[] values = new ContentValues[trackPoints.length];
|
ContentValues[] values = new ContentValues[trackPoints.length];
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
values[i] = createContentValues(trackPoints[i], trackId);
|
values[i] = createContentValues(trackPoints[i], trackId);
|
||||||
@@ -653,23 +701,23 @@ public class ContentProviderUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the first location id for a track.
|
* Gets the first location id for a track.
|
||||||
* Returns -1L if it doesn't exist.
|
* Returns null if it doesn't exist.
|
||||||
*
|
*
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public long getFirstTrackPointId(long trackId) {
|
public Track.Id getFirstTrackPointId(Track.Id trackId) {
|
||||||
if (trackId < 0) {
|
if (!trackId.isValid()) {
|
||||||
return -1L;
|
return null;
|
||||||
}
|
}
|
||||||
String selection = TrackPointsColumns._ID + "=(SELECT MIN(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=?)";
|
String selection = TrackPointsColumns._ID + "=(SELECT MIN(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=?)";
|
||||||
String[] selectionArgs = new String[]{Long.toString(trackId)};
|
String[] selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||||
try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) {
|
try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) {
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID));
|
return new Track.Id(cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1L;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -679,12 +727,13 @@ public class ContentProviderUtils {
|
|||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public long getLastTrackPointId(long trackId) {
|
public long getLastTrackPointId(Track.Id trackId) {
|
||||||
if (trackId < 0) {
|
if (trackId == null || !trackId.isValid()) {
|
||||||
|
Log.w(TAG, "Fix callers who do this.");
|
||||||
return -1L;
|
return -1L;
|
||||||
}
|
}
|
||||||
String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") from " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=?)";
|
String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") from " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=?)";
|
||||||
String[] selectionArgs = new String[]{Long.toString(trackId)};
|
String[] selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||||
try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) {
|
try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) {
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID));
|
return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID));
|
||||||
@@ -700,12 +749,12 @@ public class ContentProviderUtils {
|
|||||||
* @param location the location
|
* @param location the location
|
||||||
* @return trackPoint id if the location is in the track. -1L otherwise.
|
* @return trackPoint id if the location is in the track. -1L otherwise.
|
||||||
*/
|
*/
|
||||||
public long getTrackPointId(long trackId, Location location) {
|
public long getTrackPointId(Track.Id trackId, Location location) {
|
||||||
if (trackId < 0) {
|
if (!trackId.isValid()) {
|
||||||
return -1L;
|
return -1L;
|
||||||
}
|
}
|
||||||
String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns.TIME + "=?)";
|
String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns.TIME + "=?)";
|
||||||
String[] selectionArgs = new String[]{Long.toString(trackId), Long.toString(location.getTime())};
|
String[] selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(location.getTime())};
|
||||||
try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) {
|
try (Cursor cursor = getTrackPointCursor(new String[]{TrackPointsColumns._ID}, selection, selectionArgs, TrackPointsColumns._ID)) {
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID));
|
return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID));
|
||||||
@@ -731,8 +780,8 @@ public class ContentProviderUtils {
|
|||||||
* @param maxLocations maximum number of locations to return. -1 for no limit
|
* @param maxLocations maximum number of locations to return. -1 for no limit
|
||||||
* @param descending true to sort the result in descending order (latest location first)
|
* @param descending true to sort the result in descending order (latest location first)
|
||||||
*/
|
*/
|
||||||
public Cursor getTrackPointCursor(long trackId, long startTrackPointId, int maxLocations, boolean descending) {
|
public Cursor getTrackPointCursor(Track.Id trackId, long startTrackPointId, int maxLocations, boolean descending) {
|
||||||
if (trackId < 0) {
|
if (!trackId.isValid()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,10 +790,10 @@ public class ContentProviderUtils {
|
|||||||
if (startTrackPointId >= 0) {
|
if (startTrackPointId >= 0) {
|
||||||
String comparison = descending ? "<=" : ">=";
|
String comparison = descending ? "<=" : ">=";
|
||||||
selection = TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns._ID + comparison + "?";
|
selection = TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns._ID + comparison + "?";
|
||||||
selectionArgs = new String[]{Long.toString(trackId), Long.toString(startTrackPointId)};
|
selectionArgs = new String[]{Long.toString(trackId.getId()), Long.toString(startTrackPointId)};
|
||||||
} else {
|
} else {
|
||||||
selection = TrackPointsColumns.TRACKID + "=?";
|
selection = TrackPointsColumns.TRACKID + "=?";
|
||||||
selectionArgs = new String[]{Long.toString(trackId)};
|
selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||||
}
|
}
|
||||||
|
|
||||||
String sortOrder = TrackPointsColumns._ID;
|
String sortOrder = TrackPointsColumns._ID;
|
||||||
@@ -764,12 +813,12 @@ public class ContentProviderUtils {
|
|||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public TrackPoint getLastValidTrackPoint(long trackId) {
|
public TrackPoint getLastValidTrackPoint(Track.Id trackId) {
|
||||||
if (trackId < 0) {
|
if (!trackId.isValid()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns.LATITUDE + "<=" + MAX_LATITUDE + ")";
|
String selection = TrackPointsColumns._ID + "=(SELECT MAX(" + TrackPointsColumns._ID + ") FROM " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns.LATITUDE + "<=" + MAX_LATITUDE + ")";
|
||||||
String[] selectionArgs = new String[]{Long.toString(trackId)};
|
String[] selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||||
return findTrackPointBy(selection, selectionArgs);
|
return findTrackPointBy(selection, selectionArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,7 +829,7 @@ public class ContentProviderUtils {
|
|||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
* @return the content provider URI of the inserted trackPoint
|
* @return the content provider URI of the inserted trackPoint
|
||||||
*/
|
*/
|
||||||
public Uri insertTrackPoint(TrackPoint trackPoint, long trackId) {
|
public Uri insertTrackPoint(TrackPoint trackPoint, Track.Id trackId) {
|
||||||
return contentResolver.insert(TrackPointsColumns.CONTENT_URI_BY_ID, createContentValues(trackPoint, trackId));
|
return contentResolver.insert(TrackPointsColumns.CONTENT_URI_BY_ID, createContentValues(trackPoint, trackId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,9 +839,9 @@ public class ContentProviderUtils {
|
|||||||
* @param trackPoint the trackPoint
|
* @param trackPoint the trackPoint
|
||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
private ContentValues createContentValues(TrackPoint trackPoint, long trackId) {
|
private ContentValues createContentValues(TrackPoint trackPoint, Track.Id trackId) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(TrackPointsColumns.TRACKID, trackId);
|
values.put(TrackPointsColumns.TRACKID, trackId.getId());
|
||||||
values.put(TrackPointsColumns.LONGITUDE, (int) (trackPoint.getLongitude() * 1E6));
|
values.put(TrackPointsColumns.LONGITUDE, (int) (trackPoint.getLongitude() * 1E6));
|
||||||
values.put(TrackPointsColumns.LATITUDE, (int) (trackPoint.getLatitude() * 1E6));
|
values.put(TrackPointsColumns.LATITUDE, (int) (trackPoint.getLatitude() * 1E6));
|
||||||
|
|
||||||
@@ -833,7 +882,7 @@ public class ContentProviderUtils {
|
|||||||
* @param startTrackPointId the starting trackPoint id. -1L to ignore
|
* @param startTrackPointId the starting trackPoint id. -1L to ignore
|
||||||
* @param descending true to sort the result in descending order (latest location first)
|
* @param descending true to sort the result in descending order (latest location first)
|
||||||
*/
|
*/
|
||||||
public TrackPointIterator getTrackPointLocationIterator(final long trackId, final long startTrackPointId, final boolean descending) {
|
public TrackPointIterator getTrackPointLocationIterator(final Track.Id trackId, final long startTrackPointId, final boolean descending) {
|
||||||
return new TrackPointIterator(this, trackId, startTrackPointId, descending);
|
return new TrackPointIterator(this, trackId, startTrackPointId, descending);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -859,7 +908,7 @@ public class ContentProviderUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public List<TrackPoint> getTrackPoints(long trackId) {
|
public List<TrackPoint> getTrackPoints(Track.Id trackId) {
|
||||||
List<TrackPoint> trackPoints = null;
|
List<TrackPoint> trackPoints = null;
|
||||||
|
|
||||||
try (Cursor trackPointCursor = getTrackPointCursor(trackId, -1L, -1, false)) {
|
try (Cursor trackPointCursor = getTrackPointCursor(trackId, -1L, -1, false)) {
|
||||||
@@ -890,13 +939,23 @@ public class ContentProviderUtils {
|
|||||||
this.defaultCursorBatchSize = defaultCursorBatchSize;
|
this.defaultCursorBatchSize = defaultCursorBatchSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String formatIdListForUri(Track.Id... trackIds) {
|
||||||
|
long[] ids = new long[trackIds.length];
|
||||||
|
for (int i = 0; i < trackIds.length; i++) {
|
||||||
|
ids[i] = trackIds[i].getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatIdListForUri(ids);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats an array of IDs as comma separated string value
|
* Formats an array of IDs as comma separated string value
|
||||||
*
|
*
|
||||||
* @param ids array with IDs
|
* @param ids array with IDs
|
||||||
* @return comma separated list of ids
|
* @return comma separated list of ids
|
||||||
*/
|
*/
|
||||||
public static String formatIdListForUri(long[] ids) {
|
private static String formatIdListForUri(long[] ids) {
|
||||||
StringBuilder idsPathSegment = new StringBuilder();
|
StringBuilder idsPathSegment = new StringBuilder();
|
||||||
for (long id : ids) {
|
for (long id : ids) {
|
||||||
if (idsPathSegment.length() > 0) {
|
if (idsPathSegment.length() > 0) {
|
||||||
@@ -910,5 +969,4 @@ public class ContentProviderUtils {
|
|||||||
public static String[] parseTrackIdsFromUri(Uri url) {
|
public static String[] parseTrackIdsFromUri(Uri url) {
|
||||||
return TextUtils.split(url.getLastPathSegment(), ID_SEPARATOR);
|
return TextUtils.split(url.getLastPathSegment(), ID_SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public abstract class CustomContentProvider extends ContentProvider {
|
public class CustomContentProvider extends ContentProvider {
|
||||||
|
|
||||||
private static final String TAG = CustomContentProvider.class.getSimpleName();
|
private static final String TAG = CustomContentProvider.class.getSimpleName();
|
||||||
|
|
||||||
@@ -63,6 +63,7 @@ public abstract class CustomContentProvider extends ContentProvider {
|
|||||||
|
|
||||||
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, WaypointsColumns.CONTENT_URI.getPath(), UrlType.WAYPOINTS.ordinal());
|
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, WaypointsColumns.CONTENT_URI.getPath(), UrlType.WAYPOINTS.ordinal());
|
||||||
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, WaypointsColumns.CONTENT_URI.getPath() + "/#", UrlType.WAYPOINTS_BY_ID.ordinal());
|
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, WaypointsColumns.CONTENT_URI.getPath() + "/#", UrlType.WAYPOINTS_BY_ID.ordinal());
|
||||||
|
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, WaypointsColumns.CONTENT_URI_BY_TRACKID.getPath() + "/*", UrlType.WAYPOINTS_BY_TRACKID.ordinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -140,6 +141,7 @@ public abstract class CustomContentProvider extends ContentProvider {
|
|||||||
case WAYPOINTS:
|
case WAYPOINTS:
|
||||||
return WaypointsColumns.CONTENT_TYPE;
|
return WaypointsColumns.CONTENT_TYPE;
|
||||||
case WAYPOINTS_BY_ID:
|
case WAYPOINTS_BY_ID:
|
||||||
|
case WAYPOINTS_BY_TRACKID:
|
||||||
return WaypointsColumns.CONTENT_ITEMTYPE;
|
return WaypointsColumns.CONTENT_ITEMTYPE;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unknown URL " + url);
|
throw new IllegalArgumentException("Unknown URL " + url);
|
||||||
@@ -219,6 +221,10 @@ public abstract class CustomContentProvider extends ContentProvider {
|
|||||||
queryBuilder.setTables(WaypointsColumns.TABLE_NAME);
|
queryBuilder.setTables(WaypointsColumns.TABLE_NAME);
|
||||||
queryBuilder.appendWhere(WaypointsColumns._ID + "=" + ContentUris.parseId(url));
|
queryBuilder.appendWhere(WaypointsColumns._ID + "=" + ContentUris.parseId(url));
|
||||||
break;
|
break;
|
||||||
|
case WAYPOINTS_BY_TRACKID:
|
||||||
|
queryBuilder.setTables(WaypointsColumns.TABLE_NAME);
|
||||||
|
queryBuilder.appendWhere(WaypointsColumns.TRACKID + " IN (" + TextUtils.join(SQL_LIST_DELIMITER, ContentProviderUtils.parseTrackIdsFromUri(url)) + ")");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unknown url " + url);
|
throw new IllegalArgumentException("Unknown url " + url);
|
||||||
}
|
}
|
||||||
@@ -382,6 +388,7 @@ public abstract class CustomContentProvider extends ContentProvider {
|
|||||||
TRACKS,
|
TRACKS,
|
||||||
TRACKS_BY_ID,
|
TRACKS_BY_ID,
|
||||||
WAYPOINTS,
|
WAYPOINTS,
|
||||||
WAYPOINTS_BY_ID
|
WAYPOINTS_BY_ID,
|
||||||
|
WAYPOINTS_BY_TRACKID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,34 @@
|
|||||||
package de.dennisguse.opentracks.content.provider;
|
package de.dennisguse.opentracks.content.provider;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||||
|
import de.dennisguse.opentracks.util.UUIDUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database helper for creating and upgrading the database.
|
* Database helper for creating and upgrading the database.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
private static final int DATABASE_VERSION = 25;
|
|
||||||
private static final String TAG = CustomSQLiteOpenHelper.class.getSimpleName();
|
private static final String TAG = CustomSQLiteOpenHelper.class.getSimpleName();
|
||||||
|
|
||||||
@VisibleForTesting
|
private static final int DATABASE_VERSION = 26;
|
||||||
private static final String DATABASE_NAME = "database.db";
|
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public static final String DATABASE_NAME = "database.db";
|
||||||
|
|
||||||
public CustomSQLiteOpenHelper(Context context) {
|
public CustomSQLiteOpenHelper(Context context) {
|
||||||
this(context, DATABASE_NAME);
|
this(context, DATABASE_NAME);
|
||||||
@@ -45,6 +50,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
|||||||
db.execSQL(TrackPointsColumns.CREATE_TABLE_INDEX);
|
db.execSQL(TrackPointsColumns.CREATE_TABLE_INDEX);
|
||||||
|
|
||||||
db.execSQL(TracksColumns.CREATE_TABLE);
|
db.execSQL(TracksColumns.CREATE_TABLE);
|
||||||
|
db.execSQL(TracksColumns.CREATE_TABLE_INDEX);
|
||||||
|
|
||||||
db.execSQL(WaypointsColumns.CREATE_TABLE);
|
db.execSQL(WaypointsColumns.CREATE_TABLE);
|
||||||
db.execSQL(WaypointsColumns.CREATE_TABLE_INDEX);
|
db.execSQL(WaypointsColumns.CREATE_TABLE_INDEX);
|
||||||
@@ -61,6 +67,9 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
|||||||
case 25:
|
case 25:
|
||||||
upgradeFrom24to25(db);
|
upgradeFrom24to25(db);
|
||||||
break;
|
break;
|
||||||
|
case 26:
|
||||||
|
upgradeFrom25to26(db);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Not implemented: upgrade to " + toVersion);
|
throw new RuntimeException("Not implemented: upgrade to " + toVersion);
|
||||||
@@ -79,6 +88,9 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
|||||||
case 24:
|
case 24:
|
||||||
downgradeFrom25to24(db);
|
downgradeFrom25to24(db);
|
||||||
break;
|
break;
|
||||||
|
case 25:
|
||||||
|
downgradeFrom26to25(db);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Not implemented: downgrade to " + toVersion);
|
throw new RuntimeException("Not implemented: downgrade to " + toVersion);
|
||||||
@@ -107,7 +119,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void downgradeFrom24to23(SQLiteDatabase db) {
|
private void downgradeFrom24to23(SQLiteDatabase db) {
|
||||||
//Not needed as the delete columns did not contain any data
|
//Not needed as the deleted columns did not contain any data
|
||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
db.execSQL("ALTER TABLE tracks RENAME TO tracks_old");
|
db.execSQL("ALTER TABLE tracks RENAME TO tracks_old");
|
||||||
db.execSQL("CREATE TABLE tracks (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, category TEXT, starttime INTEGER, stoptime INTEGER, numpoints INTEGER, totaldistance FLOAT, totaltime INTEGER, movingtime INTEGER, avgspeed FLOAT, avgmovingspeed FLOAT, maxspeed FLOAT, minelevation FLOAT, maxelevation FLOAT, elevationgain FLOAT, mingrade FLOAT, maxgrade FLOAT, icon TEXT)");
|
db.execSQL("CREATE TABLE tracks (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, category TEXT, starttime INTEGER, stoptime INTEGER, numpoints INTEGER, totaldistance FLOAT, totaltime INTEGER, movingtime INTEGER, avgspeed FLOAT, avgmovingspeed FLOAT, maxspeed FLOAT, minelevation FLOAT, maxelevation FLOAT, elevationgain FLOAT, mingrade FLOAT, maxgrade FLOAT, icon TEXT)");
|
||||||
@@ -142,4 +154,40 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
|||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void upgradeFrom25to26(SQLiteDatabase db) {
|
||||||
|
db.beginTransaction();
|
||||||
|
|
||||||
|
db.execSQL("ALTER TABLE tracks ADD COLUMN uuid BLOB");
|
||||||
|
try (Cursor cursor = db.query("tracks", new String[]{"_id"}, null, null, null, null, null)) {
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
int trackIdIndex = cursor.getColumnIndexOrThrow("_id");
|
||||||
|
do {
|
||||||
|
Track.Id trackId = new Track.Id(cursor.getLong(trackIdIndex));
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put("uuid", UUIDUtils.toBytes(UUID.randomUUID()));
|
||||||
|
db.update("tracks", cv, "_id = ?", new String[]{String.valueOf(trackId)});
|
||||||
|
} while (cursor.moveToNext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db.execSQL("CREATE UNIQUE INDEX tracks_uuid_index ON tracks(uuid)");
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downgradeFrom26to25(SQLiteDatabase db) {
|
||||||
|
db.beginTransaction();
|
||||||
|
|
||||||
|
db.execSQL("DROP INDEX tracks_uuid_index");
|
||||||
|
|
||||||
|
db.execSQL("ALTER TABLE tracks RENAME TO tracks_old");
|
||||||
|
db.execSQL("CREATE TABLE tracks (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, category TEXT, starttime INTEGER, stoptime INTEGER, numpoints INTEGER, totaldistance FLOAT, totaltime INTEGER, movingtime INTEGER, avgspeed FLOAT, avgmovingspeed FLOAT, maxspeed FLOAT, minelevation FLOAT, maxelevation FLOAT, elevationgain FLOAT, mingrade FLOAT, maxgrade FLOAT, icon TEXT)");
|
||||||
|
db.execSQL("INSERT INTO tracks SELECT _id, name, description, category, starttime, stoptime, numpoints, totaldistance, totaltime, movingtime, avgspeed, avgmovingspeed, maxspeed, minelevation, maxelevation, elevationgain, 0, 0, icon FROM tracks_old");
|
||||||
|
db.execSQL("DROP TABLE tracks_old");
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.content.pm.ProviderInfo;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.MatrixCursor;
|
import android.database.MatrixCursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.provider.OpenableColumns;
|
import android.provider.OpenableColumns;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -18,8 +17,11 @@ import androidx.annotation.Nullable;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.android.IContentResolver;
|
import de.dennisguse.opentracks.android.IContentResolver;
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
@@ -30,9 +32,9 @@ import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
|||||||
/**
|
/**
|
||||||
* A content provider that mimics the behavior of {@link androidx.core.content.FileProvider}, which shares virtual (non-existing) KML-files.
|
* A content provider that mimics the behavior of {@link androidx.core.content.FileProvider}, which shares virtual (non-existing) KML-files.
|
||||||
* The actual content of the virtual files is generated by using the functionality defined in {@link CustomContentProvider}.
|
* The actual content of the virtual files is generated by using the functionality defined in {@link CustomContentProvider}.
|
||||||
*
|
* <p>
|
||||||
* Moreover, it manages access to OpenTrack's database via {@link CustomContentProvider}.
|
* Moreover, it manages access to OpenTrack's database via {@link CustomContentProvider}.
|
||||||
*
|
* <p>
|
||||||
* Explanation:
|
* Explanation:
|
||||||
* Although a request is handled by a {@link android.content.ContentProvider} (with temporarily granted permission), Android's security infrastructure prevents forwarding queries to non-exported {@link android.content.ContentProvider}.
|
* Although a request is handled by a {@link android.content.ContentProvider} (with temporarily granted permission), Android's security infrastructure prevents forwarding queries to non-exported {@link android.content.ContentProvider}.
|
||||||
* Thus, if {@link ShareContentProvider} and {@link CustomContentProvider} would be two different instances, the data would not be accessible to external apps.
|
* Thus, if {@link ShareContentProvider} and {@link CustomContentProvider} would be two different instances, the data would not be accessible to external apps.
|
||||||
@@ -71,14 +73,20 @@ public class ShareContentProvider extends CustomContentProvider implements ICont
|
|||||||
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, TracksColumns.TABLE_NAME + "/" + TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getName() + "/*/*", URI_KMZ_WITH_TRACKDETAIL_SENSORDATA_AND_PICTURES);
|
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, TracksColumns.TABLE_NAME + "/" + TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getName() + "/*/*", URI_KMZ_WITH_TRACKDETAIL_SENSORDATA_AND_PICTURES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Pair<Uri, String> createURI(long[] trackIds, String trackName, @NonNull TrackFileFormat trackFileFormat) {
|
public static Pair<Uri, String> createURI(Track.Id trackId, String trackName, @NonNull TrackFileFormat trackFileFormat) {
|
||||||
if (trackIds.length == 0) {
|
Set<Track.Id> trackIds = new HashSet<>(1);
|
||||||
|
trackIds.add(trackId);
|
||||||
|
return createURI(trackIds, trackName, trackFileFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<Uri, String> createURI(Set<Track.Id> trackIds, String trackName, @NonNull TrackFileFormat trackFileFormat) {
|
||||||
|
if (trackIds.size() == 0) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder trackIdBuilder = new StringBuilder();
|
StringBuilder trackIdBuilder = new StringBuilder();
|
||||||
for (long trackId : trackIds) {
|
for (Track.Id trackId : trackIds) {
|
||||||
trackIdBuilder.append(trackId).append(TRACKID_DELIMITER);
|
trackIdBuilder.append(trackId.getId()).append(TRACKID_DELIMITER);
|
||||||
}
|
}
|
||||||
trackIdBuilder.deleteCharAt(trackIdBuilder.lastIndexOf(TRACKID_DELIMITER));
|
trackIdBuilder.deleteCharAt(trackIdBuilder.lastIndexOf(TRACKID_DELIMITER));
|
||||||
|
|
||||||
@@ -90,18 +98,18 @@ public class ShareContentProvider extends CustomContentProvider implements ICont
|
|||||||
return new Pair<>(uri, mime);
|
return new Pair<>(uri, mime);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long[] parseURI(Uri uri) {
|
static Set<Track.Id> parseURI(Uri uri) {
|
||||||
List<String> uriPaths = uri.getPathSegments();
|
List<String> uriPaths = uri.getPathSegments();
|
||||||
if (uriPaths == null || uriPaths.size() < 2) {
|
if (uriPaths == null || uriPaths.size() < 3) {
|
||||||
Log.d(TAG, "URI does not contain any trackIds.");
|
Log.d(TAG, "URI does not contain any trackIds.");
|
||||||
return new long[]{};
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] uriTrackIds = uriPaths.get(2).split(TRACKID_DELIMITER);
|
String[] uriTrackIds = uriPaths.get(2).split(TRACKID_DELIMITER);
|
||||||
|
|
||||||
long[] trackIds = new long[uriTrackIds.length];
|
Set<Track.Id> trackIds = new HashSet<>();
|
||||||
for (int i = 0; i < trackIds.length; i++) {
|
for (String uriTrackId : uriTrackIds) {
|
||||||
trackIds[i] = Long.parseLong(uriTrackIds[i]);
|
trackIds.add(new Track.Id(Long.parseLong(uriTrackId)));
|
||||||
}
|
}
|
||||||
return trackIds;
|
return trackIds;
|
||||||
}
|
}
|
||||||
@@ -203,22 +211,19 @@ public class ShareContentProvider extends CustomContentProvider implements ICont
|
|||||||
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
||||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
|
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
|
||||||
|
|
||||||
long[] trackIds = parseURI(uri);
|
Set<Track.Id> trackIds = parseURI(uri);
|
||||||
final Track[] tracks = new Track[trackIds.length];
|
final ArrayList<Track> tracks = new ArrayList<>();
|
||||||
for (int i = 0; i < trackIds.length; i++) {
|
for (Track.Id trackId : trackIds) {
|
||||||
tracks[i] = contentProviderUtils.getTrack(trackIds[i]);
|
tracks.add(contentProviderUtils.getTrack(trackId));
|
||||||
}
|
}
|
||||||
|
|
||||||
final TrackExporter trackExporter = getTrackFileFormat(uri).newTrackExporter(getContext(), tracks, null);
|
final TrackExporter trackExporter = getTrackFileFormat(uri).newTrackExporter(getContext());
|
||||||
|
|
||||||
PipeDataWriter pipeDataWriter = new PipeDataWriter<String>() {
|
PipeDataWriter<String> pipeDataWriter = (output, uri1, mimeType, opts, args) -> {
|
||||||
@Override
|
try (FileOutputStream fileOutputStream = new FileOutputStream(output.getFileDescriptor())) {
|
||||||
public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri, @NonNull String mimeType, @Nullable Bundle opts, @Nullable String args) {
|
trackExporter.writeTrack(tracks.toArray(new Track[0]), fileOutputStream);
|
||||||
try (FileOutputStream fileOutputStream = new FileOutputStream(output.getFileDescriptor())) {
|
} catch (IOException e) {
|
||||||
trackExporter.writeTrack(getContext(), fileOutputStream);
|
Log.w(TAG, "there occurred an error while sharing a file: " + e);
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(TAG, "there occurred an error while sharing a file: " + e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.util.Log;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,14 +17,14 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
|||||||
private static final String TAG = TrackPointIterator.class.getSimpleName();
|
private static final String TAG = TrackPointIterator.class.getSimpleName();
|
||||||
|
|
||||||
private final ContentProviderUtils contentProviderUtils;
|
private final ContentProviderUtils contentProviderUtils;
|
||||||
private final long trackId;
|
private final Track.Id trackId;
|
||||||
private final boolean descending;
|
private final boolean descending;
|
||||||
private final CachedTrackPointsIndexes indexes;
|
private final CachedTrackPointsIndexes indexes;
|
||||||
private long lastTrackPointId = -1L;
|
private long lastTrackPointId = -1L;
|
||||||
private Cursor cursor;
|
private Cursor cursor;
|
||||||
|
|
||||||
|
|
||||||
public TrackPointIterator(ContentProviderUtils contentProviderUtils, long trackId, long startTrackPointId, boolean descending) {
|
public TrackPointIterator(ContentProviderUtils contentProviderUtils, Track.Id trackId, long startTrackPointId, boolean descending) {
|
||||||
this.contentProviderUtils = contentProviderUtils;
|
this.contentProviderUtils = contentProviderUtils;
|
||||||
this.trackId = trackId;
|
this.trackId = trackId;
|
||||||
this.descending = descending;
|
this.descending = descending;
|
||||||
@@ -100,13 +101,4 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
|||||||
public void remove() {
|
public void remove() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCount() {
|
|
||||||
if (cursor == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cursor.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||