Compare commits
145 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
@@ -1,4 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
liberapay: dennis.guse
|
||||
liberapay: OpenTracks
|
||||
custom: https://play.google.com/store/apps/details?id=de.dennisguse.opentracks.playstore
|
||||
|
||||
@@ -7,4 +7,7 @@ A clear and concise description of what the pull request changes/adds.
|
||||
(If available): The link to the issue that this pull request solves.
|
||||
|
||||
**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,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/vcs.xml
|
||||
.idea/uiDesigner.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/markdown-navigator-enh.xml
|
||||
.idea/markdown-navigator.xml
|
||||
|
||||
# Keystore files
|
||||
*.jks
|
||||
@@ -76,4 +79,4 @@ captures/
|
||||
# Fastlane
|
||||
Appfile
|
||||
releasePlayStore/*
|
||||
Gemfile.lock
|
||||
Gemfile.lock
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
@@ -21,7 +21,7 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
||||
</a>
|
||||
</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">
|
||||
</a>
|
||||
</td>
|
||||
@@ -51,13 +51,19 @@ _OpenTracks_ is a sport tracking application that completely respects your priva
|
||||
__Only required permissions:__
|
||||
* _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:_
|
||||
_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.
|
||||
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
|
||||
<div>
|
||||
@@ -87,7 +93,7 @@ Rework of _OpenTracks_ included:
|
||||
* removing calorie estimation and activity estimation,
|
||||
* removing support for ANT+ and Classic Bluetooth,
|
||||
* 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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## Implementation
|
||||
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.
|
||||
These URIs notify observers if on content changes (e.g., a new `TrackPoint` was added).
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 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)
|
||||
3. Manually update _version code_ and _version name_ in `build.gradle`
|
||||
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()
|
||||
}
|
||||
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 = { ->
|
||||
try {
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
@@ -50,25 +36,26 @@ def getVersionName = { ->
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
applicationId "de.dennisguse.opentracks"
|
||||
manifestPlaceholders = [
|
||||
applicationLogo: "@drawable/ic_logo_color_24dp",
|
||||
applicationName: "@string/app_name"
|
||||
]
|
||||
|
||||
versionCode 3396
|
||||
//versionCode getVersionCode() //Useful for debugging.
|
||||
versionName "v3.7.4"
|
||||
versionCode 3541
|
||||
versionName "v3.9.2"
|
||||
|
||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||
|
||||
|
||||
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
targetSdkVersion 30
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@@ -77,10 +64,6 @@ android {
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
versionNameSuffix "-debug"
|
||||
manifestPlaceholders = [
|
||||
applicationLogo: "@drawable/ic_logo_black_24dp",
|
||||
applicationName: "OpenTracks (Debug)"
|
||||
]
|
||||
}
|
||||
|
||||
release {
|
||||
@@ -99,20 +82,17 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.preference:preference:1.1.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.espresso:espresso-core:3.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.2.0'
|
||||
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'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
androidTestImplementation 'androidx.test:core:1.3.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||
androidTestImplementation 'org.mockito:mockito-android:3.4.6'
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ endlegend
|
||||
TrackListActivity --> TrackRecordingActivity : Start recording
|
||||
TrackListActivity --> SearchListActivity
|
||||
TrackListActivity --> MarkerListActivity : Show all markers
|
||||
TrackListActivity --> AggregatedStatisticsActivity : Aggregated stats
|
||||
TrackListActivity --> TrackRecordedActivity : Show track
|
||||
TrackListActivity --> TrackDeleteActivity
|
||||
|
||||
@@ -46,6 +47,9 @@ MarkerDetailActivity --> CoordinateOnMapIntent : URI
|
||||
SettingsActivity --> AboutActivity
|
||||
SettingsActivity --> HelpActivity
|
||||
SettingsActivity --> ExportActivity
|
||||
SettingsActivity --> ImportActivity
|
||||
SettingsActivity --> DirectoryChooserActivity
|
||||
SettingsActivity --> DirectoryChooserActivity
|
||||
DirectoryChooserActivity$ImportDirectoryChooserActivity --> ImportActivity
|
||||
DirectoryChooserActivity$ExportDirectoryChooserActivity --> ExportActivity
|
||||
|
||||
@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 |
@@ -1 +1 @@
|
||||
OpenTracks – ein GPS-Tracker, der deine Daten für sich behält.
|
||||
OpenTracks – ein GPS-Tracker, der deine Daten für sich behält.
|
||||
@@ -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
|
||||
@@ -1 +1 @@
|
||||
OpenTracks - Suivi d'activités sportives respectueux de votre vie privée.
|
||||
OpenTracks - Suivi d'activités sportives respectueux de votre vie privée.
|
||||
@@ -67,7 +67,7 @@ public class DescriptionGeneratorTest {
|
||||
track.setTrackStatistics(stats);
|
||||
track.setCategory("hiking");
|
||||
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>"
|
||||
+ "Activity type: hiking<br>"
|
||||
+ "Description: -<br>"
|
||||
@@ -103,7 +103,7 @@ public class DescriptionGeneratorTest {
|
||||
track.setTrackStatistics(stats);
|
||||
track.setCategory("hiking");
|
||||
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>"
|
||||
+ "Activity type: hiking<br>"
|
||||
+ "Description: -<br>"
|
||||
|
||||
@@ -17,18 +17,17 @@
|
||||
package de.dennisguse.opentracks.content;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.rule.provider.ProviderTestRule;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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.Waypoint;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -48,29 +49,32 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SearchEngineTest {
|
||||
|
||||
private static final String TAG = SearchEngineTest.class.getSimpleName();
|
||||
|
||||
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 SearchEngine engine;
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
providerUtils = new ContentProviderUtils(context);
|
||||
providerUtils = new ContentProviderUtils(sqliteContentProviderRule.getResolver());
|
||||
|
||||
engine = new SearchEngine(providerUtils);
|
||||
}
|
||||
|
||||
@After
|
||||
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.setName(title);
|
||||
track.setDescription(description);
|
||||
@@ -84,18 +88,18 @@ public class SearchEngineTest {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private long insertTrack(String title, long hoursAgo) {
|
||||
private Track.Id insertTrack(String title, long 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.setLatitude(location.getLatitude() + distance);
|
||||
location.setLongitude(location.getLongitude() + distance);
|
||||
@@ -109,22 +113,22 @@ public class SearchEngineTest {
|
||||
waypoint.setTrackId(trackId);
|
||||
|
||||
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) {
|
||||
return insertWaypoint(title, description, category, 0.0, -1, -1);
|
||||
private Waypoint.Id insertWaypoint(String title, String description, String category) {
|
||||
return insertWaypoint(title, description, category, 0.0, -1, null);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, double distance) {
|
||||
return insertWaypoint(title, "", "", distance, -1, -1);
|
||||
private Waypoint.Id insertWaypoint(String title, double distance) {
|
||||
return insertWaypoint(title, "", "", distance, -1, null);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, long hoursAgo) {
|
||||
return insertWaypoint(title, "", "", 0.0, hoursAgo, -1);
|
||||
private Waypoint.Id insertWaypoint(String title, long hoursAgo) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -139,14 +143,14 @@ public class SearchEngineTest {
|
||||
// - one which will match in title and description
|
||||
// - one which will match in all fields
|
||||
insertTrack("bb", "cc", "dd");
|
||||
long descriptionMatchId = insertTrack("bb", "aa", "cc");
|
||||
long categoryMatchId = insertTrack("bb", "cc", "aa");
|
||||
long titleMatchId = insertTrack("aa", "bb", "cc");
|
||||
long titleCategoryMatchId = insertTrack("aa", "bb", "ca");
|
||||
long titleDescriptionMatchId = insertTrack("aa", "ba", "cc");
|
||||
long allMatchId = insertTrack("aa", "ba", "ca");
|
||||
Track.Id descriptionMatchId = insertTrack("bb", "aa", "cc");
|
||||
Track.Id categoryMatchId = insertTrack("bb", "cc", "aa");
|
||||
Track.Id titleMatchId = insertTrack("aa", "bb", "cc");
|
||||
Track.Id titleCategoryMatchId = insertTrack("aa", "bb", "ca");
|
||||
Track.Id titleDescriptionMatchId = insertTrack("aa", "ba", "cc");
|
||||
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));
|
||||
|
||||
// Title > Description > Category.
|
||||
@@ -164,14 +168,14 @@ public class SearchEngineTest {
|
||||
// - one which will match in title and description
|
||||
// - one which will match in all fields
|
||||
insertWaypoint("bb", "cc", "dd");
|
||||
long descriptionMatchId = insertWaypoint("bb", "aa", "cc");
|
||||
long categoryMatchId = insertWaypoint("bb", "cc", "aa");
|
||||
long titleMatchId = insertWaypoint("aa", "bb", "cc");
|
||||
long titleCategoryMatchId = insertWaypoint("aa", "bb", "ca");
|
||||
long titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc");
|
||||
long allMatchId = insertWaypoint("aa", "ba", "ca");
|
||||
Waypoint.Id descriptionMatchId = insertWaypoint("bb", "aa", "cc");
|
||||
Waypoint.Id categoryMatchId = insertWaypoint("bb", "cc", "aa");
|
||||
Waypoint.Id titleMatchId = insertWaypoint("aa", "bb", "cc");
|
||||
Waypoint.Id titleCategoryMatchId = insertWaypoint("aa", "bb", "ca");
|
||||
Waypoint.Id titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc");
|
||||
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));
|
||||
|
||||
// Title > Description > Category.
|
||||
@@ -186,13 +190,13 @@ public class SearchEngineTest {
|
||||
// - one waypoint which will match by title
|
||||
// - one track which won't match
|
||||
// - one track which will match by title
|
||||
long descriptionWaypointId = insertWaypoint("bb", "aa", "cc");
|
||||
Waypoint.Id descriptionWaypointId = insertWaypoint("bb", "aa", "cc");
|
||||
insertWaypoint("bb", "cc", "dd");
|
||||
long titleWaypointId = insertWaypoint("aa", "bb", "cc");
|
||||
Waypoint.Id titleWaypointId = insertWaypoint("aa", "bb", "cc");
|
||||
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));
|
||||
|
||||
// Title > Description > Category.
|
||||
@@ -205,11 +209,11 @@ public class SearchEngineTest {
|
||||
@Test
|
||||
public void testSearchWaypointDistance() {
|
||||
// All results match text, but they're at difference distances from the user.
|
||||
long farFarAwayId = insertWaypoint("aa", 0.3);
|
||||
long nearId = insertWaypoint("ab", 0.1);
|
||||
long farId = insertWaypoint("ac", 0.2);
|
||||
Waypoint.Id farFarAwayId = insertWaypoint("aa", 0.3);
|
||||
Waypoint.Id nearId = insertWaypoint("ab", 0.1);
|
||||
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));
|
||||
|
||||
// Distance order.
|
||||
@@ -218,11 +222,11 @@ public class SearchEngineTest {
|
||||
|
||||
public void testSearchTrackRecent() {
|
||||
// All results match text, but they're were recorded at different times.
|
||||
long oldestId = insertTrack("aa", 3);
|
||||
long recentId = insertTrack("ab", 1);
|
||||
long oldId = insertTrack("ac", 2);
|
||||
Track.Id oldestId = insertTrack("aa", 3);
|
||||
Track.Id recentId = insertTrack("ab", 1);
|
||||
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));
|
||||
|
||||
// Reverse time order.
|
||||
@@ -232,11 +236,11 @@ public class SearchEngineTest {
|
||||
@Test
|
||||
public void testSearchWaypointRecent() {
|
||||
// All results match text, but they're were recorded at different times.
|
||||
long oldestId = insertWaypoint("aa", 2);
|
||||
long recentId = insertWaypoint("ab", 0);
|
||||
long oldId = insertWaypoint("ac", 1);
|
||||
Waypoint.Id oldestId = insertWaypoint("aa", 2);
|
||||
Waypoint.Id recentId = insertWaypoint("ab", 0);
|
||||
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));
|
||||
|
||||
// Reverse time order.
|
||||
@@ -246,8 +250,8 @@ public class SearchEngineTest {
|
||||
@Test
|
||||
public void testSearchCurrentTrack() {
|
||||
// All results match text, but one of them is the current track.
|
||||
long currentId = insertTrack("ab", 1);
|
||||
long otherId = insertTrack("aa", 1);
|
||||
Track.Id currentId = insertTrack("ab", 1);
|
||||
Track.Id otherId = insertTrack("aa", 1);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, currentId, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<>(engine.search(query));
|
||||
@@ -259,24 +263,29 @@ public class SearchEngineTest {
|
||||
@Test
|
||||
public void testSearchCurrentTrackWaypoint() {
|
||||
// All results match text, but one of them is in the current track.
|
||||
long otherId = insertWaypoint("aa", 1, 456);
|
||||
long currentId = insertWaypoint("ab", 1, 123);
|
||||
Waypoint.Id otherId = insertWaypoint("aa", 1, new Track.Id(456));
|
||||
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));
|
||||
|
||||
// Waypoint in current track should be promoted.
|
||||
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.assertNull("Ambiguous result", result.waypoint);
|
||||
Assert.assertEquals(trackId, result.track.getId());
|
||||
}
|
||||
|
||||
private void assertTrackResults(List<ScoredResult> results, long... trackIds) {
|
||||
String errMsg = "Expected IDs=" + Arrays.toString(trackIds) + "; results=" + results;
|
||||
private void assertTrackResults(List<ScoredResult> results, Track.Id... trackIds) {
|
||||
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);
|
||||
for (int i = 0; i < results.size(); 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.assertNull("Ambiguous result", result.track);
|
||||
Assert.assertEquals(waypointId, result.waypoint.getId());
|
||||
}
|
||||
|
||||
private void assertWaypointResults(List<ScoredResult> results, long... waypointIds) {
|
||||
String errMsg = "Expected IDs=" + Arrays.toString(waypointIds) + "; results=" + results;
|
||||
private void assertWaypointResults(List<ScoredResult> results, Waypoint.Id... waypointIds) {
|
||||
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);
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
ScoredResult result = results.get(i);
|
||||
|
||||
@@ -20,10 +20,10 @@ public class TestDataUtil {
|
||||
/**
|
||||
* Create a track without any trackPoints.
|
||||
*/
|
||||
public static Track createTrack(long trackId) {
|
||||
public static Track createTrack(Track.Id trackId) {
|
||||
Track track = new Track();
|
||||
track.setId(trackId);
|
||||
track.setName("Test: " + trackId);
|
||||
track.setName("Test: " + trackId.getId());
|
||||
|
||||
return track;
|
||||
}
|
||||
@@ -34,18 +34,18 @@ public class TestDataUtil {
|
||||
* @param trackId the trackId of 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);
|
||||
|
||||
TrackPoint[] trackPoints = new TrackPoint[numPoints];
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
trackPoints[i] = (createTrackPoint(i));
|
||||
trackPoints[i] = createTrackPoint(i);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
insertTrackWithLocations(contentProviderUtils, pair.first, pair.second);
|
||||
@@ -56,17 +56,22 @@ public class TestDataUtil {
|
||||
/**
|
||||
* Creates a location.
|
||||
*
|
||||
* @param i the index to set the value of location.
|
||||
* @return created location
|
||||
* @param i the index for the TrackPoint.
|
||||
*/
|
||||
public static TrackPoint createTrackPoint(int i) {
|
||||
Location location = new Location("test");
|
||||
location.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0);
|
||||
location.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
|
||||
location.setAccuracy((float) i / 100.0f);
|
||||
location.setAltitude(i * ALTITUDE_INTERVAL);
|
||||
location.setTime(i + 1);
|
||||
return new TrackPoint(location);
|
||||
TrackPoint trackPoint = new TrackPoint();
|
||||
trackPoint.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0);
|
||||
trackPoint.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
|
||||
trackPoint.setAccuracy((float) i / 100.0f);
|
||||
trackPoint.setAltitude(i * ALTITUDE_INTERVAL);
|
||||
trackPoint.setTime(i + 1);
|
||||
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.
|
||||
* @return the Waypoint created.
|
||||
*/
|
||||
public static Waypoint createWaypointWithPhoto(Context context, long trackId, Location location) throws IOException {
|
||||
String photoUrl = "";
|
||||
public static Waypoint createWaypointWithPhoto(Context context, Track.Id trackId, Location location) throws IOException {
|
||||
File dstFile = new File(FileUtils.getImageUrl(context, trackId));
|
||||
dstFile.createNewFile();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.net.Uri;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
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.WaypointsColumns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests {@link CustomContentProvider}.
|
||||
*
|
||||
@@ -51,7 +53,7 @@ public class CustomContentProviderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testOnCreate() {
|
||||
Assert.assertTrue(customContentProvider.onCreate(context));
|
||||
assertTrue(customContentProvider.onCreate(context));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,13 +61,13 @@ public class CustomContentProviderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testGetType() {
|
||||
Assert.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_TYPE, customContentProvider.getType(TracksColumns.CONTENT_URI));
|
||||
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));
|
||||
Assert.assertEquals(TrackPointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(TrackPointsColumns.CONTENT_URI_BY_TRACKID.buildUpon(), 1).build()));
|
||||
assertEquals(TrackPointsColumns.CONTENT_TYPE, customContentProvider.getType(TrackPointsColumns.CONTENT_URI_BY_ID));
|
||||
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));
|
||||
Assert.assertEquals(WaypointsColumns.CONTENT_ITEMTYPE, customContentProvider.getType(ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), 1).build()));
|
||||
assertEquals(WaypointsColumns.CONTENT_TYPE, customContentProvider.getType(WaypointsColumns.CONTENT_URI));
|
||||
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.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||
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.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
import de.dennisguse.opentracks.util.UUIDUtils;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -81,39 +83,39 @@ public class CustomContentProviderUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testLocationIterator_noPoints() {
|
||||
testIterator(1, 0, 1, false);
|
||||
testIterator(new Track.Id(1), 0, 1, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocationIterator_noBatchAscending() {
|
||||
testIterator(1, 50, 100, false);
|
||||
testIterator(2, 50, 50, false);
|
||||
testIterator(new Track.Id(1), 50, 100, false);
|
||||
testIterator(new Track.Id(2), 50, 50, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocationIterator_noBatchDescending() {
|
||||
testIterator(1, 50, 100, true);
|
||||
testIterator(2, 50, 50, true);
|
||||
testIterator(new Track.Id(1), 50, 100, true);
|
||||
testIterator(new Track.Id(2), 50, 50, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocationIterator_batchAscending() {
|
||||
testIterator(1, 50, 11, false);
|
||||
testIterator(2, 50, 25, false);
|
||||
testIterator(new Track.Id(1), 50, 11, false);
|
||||
testIterator(new Track.Id(2), 50, 25, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocationIterator_batchDescending() {
|
||||
testIterator(1, 50, 11, true);
|
||||
testIterator(2, 50, 25, true);
|
||||
testIterator(new Track.Id(1), 50, 11, true);
|
||||
testIterator(new Track.Id(2), 50, 25, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
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);
|
||||
contentProviderUtils.setDefaultCursorBatchSize(batchSize);
|
||||
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.setId(id);
|
||||
track.setName("Test: " + id);
|
||||
track.setName("Test: " + id.getId());
|
||||
contentProviderUtils.insertTrack(track);
|
||||
track = contentProviderUtils.getTrack(id);
|
||||
Assert.assertNotNull(track);
|
||||
@@ -171,22 +173,26 @@ public class CustomContentProviderUtilsTest {
|
||||
*/
|
||||
@Test
|
||||
public void testCreateTrack() {
|
||||
int startColumnIndex = 1;
|
||||
int columnIndex = startColumnIndex;
|
||||
when(cursorMock.getColumnIndexOrThrow(TracksColumns._ID)).thenReturn(columnIndex++);
|
||||
when(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).thenReturn(columnIndex++);
|
||||
columnIndex = startColumnIndex;
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
|
||||
int columnIndex = 1;
|
||||
// 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
|
||||
when(cursorMock.isNull(columnIndex++)).thenReturn(false);
|
||||
long trackId = System.currentTimeMillis();
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
when(cursorMock.getLong(columnIndex++)).thenReturn(trackId);
|
||||
// Name
|
||||
String name = NAME_PREFIX + trackId;
|
||||
when(cursorMock.getString(columnIndex++)).thenReturn(name);
|
||||
columnIndex++;
|
||||
String name = NAME_PREFIX + trackId.getId();
|
||||
when(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).thenReturn(columnIndex);
|
||||
when(cursorMock.isNull(columnIndex)).thenReturn(false);
|
||||
when(cursorMock.getString(columnIndex)).thenReturn(name);
|
||||
|
||||
Track track = contentProviderUtils.createTrack(cursorMock);
|
||||
Assert.assertEquals(trackId, track.getId());
|
||||
@@ -199,8 +205,8 @@ public class CustomContentProviderUtilsTest {
|
||||
@Test
|
||||
public void testDeleteAllTracks() {
|
||||
// Insert track, points and waypoint at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
contentProviderUtils.insertWaypoint(waypoint);
|
||||
@@ -229,7 +235,7 @@ public class CustomContentProviderUtilsTest {
|
||||
@Test
|
||||
public void testDeleteAllTracks_withWaypointAndPhoto() throws IOException {
|
||||
// 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);
|
||||
|
||||
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
|
||||
public void testDeleteTrack() {
|
||||
// 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, trackId, 0);
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId1, 0);
|
||||
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 1, 10);
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 2, 10);
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId2, 10);
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId3, 10);
|
||||
|
||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId + 1));
|
||||
waypoint.setTrackId(trackId);
|
||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId2));
|
||||
waypoint.setTrackId(trackId1);
|
||||
contentProviderUtils.insertWaypoint(waypoint);
|
||||
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
@@ -286,7 +295,7 @@ public class CustomContentProviderUtilsTest {
|
||||
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, null, WaypointsColumns._ID);
|
||||
Assert.assertEquals(1, waypointCursor.getCount());
|
||||
// Delete one track.
|
||||
contentProviderUtils.deleteTrack(context, trackId);
|
||||
contentProviderUtils.deleteTrack(context, trackId1);
|
||||
// Check whether all data of a track has been deleted.
|
||||
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID);
|
||||
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
|
||||
public void testDeleteTrack_withWaypointPhoto() throws IOException {
|
||||
// Insert three tracks.
|
||||
long trackId = System.currentTimeMillis();
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 1, 10);
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId + 2, 10);
|
||||
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);
|
||||
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId1, 10);
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId2, 10);
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId3, 10);
|
||||
|
||||
// Insert a waypoint in tracks trackId and trackId + 1.
|
||||
TrackPoint trackPoint1 = contentProviderUtils.getLastValidTrackPoint(trackId);
|
||||
Waypoint waypoint1 = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint1.getLocation());
|
||||
TrackPoint trackPoint1 = contentProviderUtils.getLastValidTrackPoint(trackId1);
|
||||
Waypoint waypoint1 = TestDataUtil.createWaypointWithPhoto(context, trackId1, trackPoint1.getLocation());
|
||||
contentProviderUtils.insertWaypoint(waypoint1);
|
||||
File dir1 = FileUtils.getPhotoDir(context, trackId);
|
||||
File dir1 = FileUtils.getPhotoDir(context, trackId1);
|
||||
|
||||
TrackPoint trackPoint2 = contentProviderUtils.getLastValidTrackPoint(trackId + 1);
|
||||
Waypoint waypoint2 = TestDataUtil.createWaypointWithPhoto(context, trackId + 1, trackPoint2.getLocation());
|
||||
TrackPoint trackPoint2 = contentProviderUtils.getLastValidTrackPoint(trackId2);
|
||||
Waypoint waypoint2 = TestDataUtil.createWaypointWithPhoto(context, trackId2, trackPoint2.getLocation());
|
||||
contentProviderUtils.insertWaypoint(waypoint2);
|
||||
File dir2 = FileUtils.getPhotoDir(context, trackId + 1);
|
||||
File dir2 = FileUtils.getPhotoDir(context, trackId2);
|
||||
|
||||
// Check.
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
@@ -334,7 +347,7 @@ public class CustomContentProviderUtilsTest {
|
||||
Assert.assertEquals(1, dir2.list().length);
|
||||
Assert.assertTrue(dir2.exists());
|
||||
// Delete one track.
|
||||
contentProviderUtils.deleteTrack(context, trackId);
|
||||
contentProviderUtils.deleteTrack(context, trackId1);
|
||||
// Check whether all data of a track has been deleted.
|
||||
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, TracksColumns._ID);
|
||||
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
|
||||
public void testGetAllTracks() {
|
||||
// given
|
||||
int initialTrackNumber = contentProviderUtils.getAllTracks().size();
|
||||
long trackId = System.currentTimeMillis();
|
||||
int initialTrackNumber = contentProviderUtils.getTracks().size();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
||||
|
||||
// when
|
||||
List<Track> allTracks = contentProviderUtils.getAllTracks();
|
||||
List<Track> allTracks = contentProviderUtils.getTracks();
|
||||
|
||||
// then
|
||||
Assert.assertEquals(initialTrackNumber + 1, allTracks.size());
|
||||
@@ -369,28 +382,45 @@ public class CustomContentProviderUtilsTest {
|
||||
*/
|
||||
@Test
|
||||
public void testGetLastTrack() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
||||
Assert.assertEquals(trackId, contentProviderUtils.getLastTrack().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link ContentProviderUtils#getTrack(long)}
|
||||
* Tests the method {@link ContentProviderUtils#getTrack(Track.Id)}
|
||||
*/
|
||||
@Test
|
||||
public void testGetTrack() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
public void testGetTrack_by_id() {
|
||||
// given
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
contentProviderUtils.insertTrack(TestDataUtil.createTrack(trackId));
|
||||
|
||||
// when / then
|
||||
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)}
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateTrack() {
|
||||
// given
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Track track = TestDataUtil.createTrack(trackId);
|
||||
String nameOld = "name1";
|
||||
String nameNew = "name2";
|
||||
@@ -409,7 +439,7 @@ public class CustomContentProviderUtilsTest {
|
||||
*/
|
||||
@Test
|
||||
public void testCreateContentValues_waypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||
|
||||
// Bottom
|
||||
@@ -435,10 +465,10 @@ public class CustomContentProviderUtilsTest {
|
||||
|
||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(contentResolverMock);
|
||||
|
||||
long waypointId = System.currentTimeMillis();
|
||||
Waypoint.Id waypointId = new Waypoint.Id(System.currentTimeMillis());
|
||||
waypoint.setId(waypointId);
|
||||
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(TEST_DESC, contentValues.get(WaypointsColumns.DESCRIPTION));
|
||||
}
|
||||
@@ -472,19 +502,19 @@ public class CustomContentProviderUtilsTest {
|
||||
when(cursorMock.getLong(columnIndex++)).thenReturn(trackId);
|
||||
|
||||
Waypoint waypoint = contentProviderUtils.createWaypoint(cursorMock);
|
||||
Assert.assertEquals(id, waypoint.getId());
|
||||
Assert.assertEquals(id, waypoint.getId().getId());
|
||||
Assert.assertEquals(name, waypoint.getName());
|
||||
Assert.assertEquals(trackId, waypoint.getTrackId());
|
||||
Assert.assertEquals(trackId, waypoint.getTrackId().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link ContentProviderUtils#deleteWaypoint(Context, long)}
|
||||
* {@link ContentProviderUtils#deleteWaypoint(Context, Waypoint.Id)}
|
||||
* when there is only one waypoint in the track.
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteWaypoint_onlyOneWayPoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
// Insert at first.
|
||||
@@ -497,7 +527,7 @@ public class CustomContentProviderUtilsTest {
|
||||
Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1);
|
||||
|
||||
// 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
|
||||
contentProviderUtils.deleteWaypoint(context, waypoint1Id);
|
||||
@@ -507,12 +537,12 @@ public class CustomContentProviderUtilsTest {
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link ContentProviderUtils#deleteWaypoint(Context, long)}
|
||||
* {@link ContentProviderUtils#deleteWaypoint(Context, Waypoint.Id)}
|
||||
* when there is only one waypoint in the track.
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteWaypoint_onlyOneWayPointWithPhotoUrl() throws IOException {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
// Insert at first.
|
||||
@@ -524,7 +554,7 @@ public class CustomContentProviderUtilsTest {
|
||||
Assert.assertEquals(contentProviderUtils.getWaypointCount(trackId), 1);
|
||||
|
||||
// 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.
|
||||
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
|
||||
public void testDeleteWaypoint_hasNextWayPoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
// Track track = TestDataUtil.createTrackAndInsert(trackId, 10);
|
||||
@@ -569,12 +599,12 @@ public class CustomContentProviderUtilsTest {
|
||||
Waypoint waypoint1 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
waypoint1.setDescription(MOCK_DESC);
|
||||
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));
|
||||
waypoint2.setDescription(MOCK_DESC);
|
||||
waypoint2.setTrackId(trackId);
|
||||
long waypoint2Id = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint2));
|
||||
Waypoint.Id waypoint2Id = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint2)));
|
||||
|
||||
// Delete
|
||||
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
|
||||
public void testGetNextWaypointNumber() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
Waypoint waypoint1 = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
@@ -610,17 +640,17 @@ public class CustomContentProviderUtilsTest {
|
||||
|
||||
/**
|
||||
* Tests the method {@link ContentProviderUtils#insertWaypoint(Waypoint)} and
|
||||
* {@link ContentProviderUtils#getWaypoint(long)}.
|
||||
* {@link ContentProviderUtils#getWaypoint(Waypoint.Id)}.
|
||||
*/
|
||||
@Test
|
||||
public void testInsertAndGetWaypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
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());
|
||||
}
|
||||
@@ -630,14 +660,14 @@ public class CustomContentProviderUtilsTest {
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateWaypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
// Insert at first.
|
||||
Waypoint waypoint = new Waypoint(contentProviderUtils.getLastValidTrackPoint(trackId));
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
waypoint.setTrackId(trackId);
|
||||
long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint));
|
||||
Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)));
|
||||
|
||||
// Update
|
||||
waypoint = contentProviderUtils.getWaypoint(waypointId);
|
||||
@@ -654,7 +684,7 @@ public class CustomContentProviderUtilsTest {
|
||||
public void testUpdateWaypoint_withPhoto() throws IOException {
|
||||
// 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);
|
||||
|
||||
// Insert at first.
|
||||
@@ -662,9 +692,9 @@ public class CustomContentProviderUtilsTest {
|
||||
Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
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.isDirectory());
|
||||
Assert.assertEquals(1, dir.list().length);
|
||||
@@ -690,7 +720,7 @@ public class CustomContentProviderUtilsTest {
|
||||
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.
|
||||
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
// Insert at first.
|
||||
@@ -698,9 +728,9 @@ public class CustomContentProviderUtilsTest {
|
||||
Waypoint waypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
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.isDirectory());
|
||||
Assert.assertEquals(1, dir.list().length);
|
||||
@@ -725,7 +755,7 @@ public class CustomContentProviderUtilsTest {
|
||||
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.
|
||||
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
// Insert two waypoints with photos.
|
||||
@@ -736,10 +766,10 @@ public class CustomContentProviderUtilsTest {
|
||||
Waypoint otherWaypoint = TestDataUtil.createWaypointWithPhoto(context, trackId, trackPoint.getLocation());
|
||||
otherWaypoint.setDescription(TEST_DESC);
|
||||
otherWaypoint.setTrackId(trackId);
|
||||
long waypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint));
|
||||
long otherWaypointId = ContentUris.parseId(contentProviderUtils.insertWaypoint(otherWaypoint));
|
||||
Waypoint.Id waypointId = new Waypoint.Id(ContentUris.parseId(contentProviderUtils.insertWaypoint(waypoint)));
|
||||
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.isDirectory());
|
||||
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
|
||||
public void testBulkInsertTrackPoint() {
|
||||
// given
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||
TestDataUtil.insertTrackWithLocations(contentProviderUtils, track.first, track.second);
|
||||
|
||||
@@ -818,12 +848,12 @@ public class CustomContentProviderUtilsTest {
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link ContentProviderUtils#insertTrackPoint(TrackPoint, long)}.
|
||||
* {@link ContentProviderUtils#insertTrackPoint(TrackPoint, Track.Id)}.
|
||||
*/
|
||||
@Test
|
||||
public void testInsertTrackPoint() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
contentProviderUtils.insertTrackPoint(TestDataUtil.createTrackPoint(22), trackId);
|
||||
@@ -833,7 +863,7 @@ public class CustomContentProviderUtilsTest {
|
||||
@Test
|
||||
public void testInsertAndLoadTrackPoint() {
|
||||
// given
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
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
|
||||
public void testGetLastValidTrackPoint() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
|
||||
|
||||
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
|
||||
public void testGetTrackPointCursor_desc() {
|
||||
// given
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||
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
|
||||
public void testGetTrackPointCursor_asc() {
|
||||
// given
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||
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
|
||||
public void testGetTrackPointLocationIterator_desc() {
|
||||
// given
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||
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
|
||||
public void testGetTrackPointLocationIterator_asc() {
|
||||
// given
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Pair<Track, TrackPoint[]> track = TestDataUtil.createTrack(trackId, 10);
|
||||
contentProviderUtils.insertTrack(track.first);
|
||||
|
||||
@@ -972,7 +1002,7 @@ public class CustomContentProviderUtilsTest {
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private void checkLocation(int i, Location location) {
|
||||
@@ -982,12 +1012,10 @@ public class CustomContentProviderUtilsTest {
|
||||
Assert.assertEquals(i * TestDataUtil.ALTITUDE_INTERVAL, location.getAltitude(), 0.01);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFormatIdListForUri() {
|
||||
Assert.assertEquals("", ContentProviderUtils.formatIdListForUri(new long[]{}));
|
||||
Assert.assertEquals("12", ContentProviderUtils.formatIdListForUri(new long[]{12}));
|
||||
Assert.assertEquals("42,43,44", ContentProviderUtils.formatIdListForUri(new long[]{42, 43, 44}));
|
||||
Assert.assertEquals("", ContentProviderUtils.formatIdListForUri());
|
||||
Assert.assertEquals("12", ContentProviderUtils.formatIdListForUri(new Track.Id(12)));
|
||||
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.database.Cursor;
|
||||
import android.database.sqlite.SQLiteConstraintException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
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.WaypointsColumns;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class CustomSQLiteOpenHelperTest {
|
||||
|
||||
@@ -36,7 +42,8 @@ public class CustomSQLiteOpenHelperTest {
|
||||
*
|
||||
* @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<>();
|
||||
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) {
|
||||
@@ -53,6 +60,7 @@ public class CustomSQLiteOpenHelperTest {
|
||||
*
|
||||
* @return Map(tableName, SQL)
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static Map<String, String> getIndexSQL(SQLiteDatabase db) {
|
||||
HashMap<String, String> indexSQL = new HashMap<>();
|
||||
try (Cursor cursor = db.rawQuery("SELECT tbl_name, SQL FROM sqlite_master WHERE type = 'index'", null)) {
|
||||
@@ -85,6 +93,7 @@ public class CustomSQLiteOpenHelperTest {
|
||||
}
|
||||
|
||||
@Before
|
||||
@After
|
||||
public void setUp() {
|
||||
context.deleteDatabase(DATABASE_NAME);
|
||||
}
|
||||
@@ -92,36 +101,21 @@ public class CustomSQLiteOpenHelperTest {
|
||||
@Test
|
||||
public void onCreate() {
|
||||
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));
|
||||
Assert.assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE_INDEX));
|
||||
assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE));
|
||||
assertTrue(hasSqlCreate(db, TrackPointsColumns.CREATE_TABLE_INDEX));
|
||||
|
||||
Assert.assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE));
|
||||
Assert.assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE_INDEX));
|
||||
assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE));
|
||||
assertTrue(hasSqlCreate(db, WaypointsColumns.CREATE_TABLE_INDEX));
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUpgrade_FromVersion23() {
|
||||
// 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();
|
||||
}
|
||||
createVersion23();
|
||||
|
||||
// Open database with SQL upgrade
|
||||
Map<String, String> tableByUpgrade;
|
||||
@@ -130,10 +124,9 @@ public class CustomSQLiteOpenHelperTest {
|
||||
tableByUpgrade = getTableSQL(dbUpgraded);
|
||||
indicesByUpgrade = getIndexSQL(dbUpgraded);
|
||||
}
|
||||
|
||||
// Open database via
|
||||
context.deleteDatabase(DATABASE_NAME);
|
||||
|
||||
// Open database via creation script
|
||||
Map<String, String> tablesByCreate;
|
||||
Map<String, String> indicesByCreate;
|
||||
try (SQLiteDatabase dbCreated = new CustomSQLiteOpenHelper(context, DATABASE_NAME).getReadableDatabase()) {
|
||||
@@ -142,17 +135,18 @@ public class CustomSQLiteOpenHelperTest {
|
||||
}
|
||||
|
||||
// then - verify table structure
|
||||
Assert.assertEquals(3, tableByUpgrade.size());
|
||||
Assert.assertEquals(tableByUpgrade.size(), tablesByCreate.size());
|
||||
assertEquals(3, tableByUpgrade.size());
|
||||
assertEquals(tableByUpgrade.size(), tablesByCreate.size());
|
||||
|
||||
Assert.assertEquals(tablesByCreate.get(TracksColumns.TABLE_NAME), tableByUpgrade.get(TracksColumns.TABLE_NAME));
|
||||
Assert.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(TracksColumns.TABLE_NAME), tableByUpgrade.get(TracksColumns.TABLE_NAME));
|
||||
assertEquals(tablesByCreate.get(TrackPointsColumns.TABLE_NAME), tableByUpgrade.get(TrackPointsColumns.TABLE_NAME));
|
||||
assertEquals(tablesByCreate.get(WaypointsColumns.TABLE_NAME), tableByUpgrade.get(WaypointsColumns.TABLE_NAME));
|
||||
|
||||
// then - verify custom indices
|
||||
Assert.assertEquals(2, indicesByCreate.size());
|
||||
Assert.assertEquals(indicesByUpgrade.get(TrackPointsColumns.TABLE_NAME), indicesByCreate.get(TrackPointsColumns.TABLE_NAME));
|
||||
Assert.assertEquals(indicesByUpgrade.get(WaypointsColumns.TABLE_NAME), indicesByCreate.get(WaypointsColumns.TABLE_NAME));
|
||||
assertEquals(3, indicesByCreate.size());
|
||||
assertEquals(indicesByUpgrade.get(TracksColumns.TABLE_NAME), indicesByCreate.get(TracksColumns.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
|
||||
@@ -169,11 +163,41 @@ public class CustomSQLiteOpenHelperTest {
|
||||
}
|
||||
|
||||
// then - verify table structure
|
||||
Assert.assertEquals(TRACKS_CREATE_TABLE_V23, tablesByDowngrade.get("tracks"));
|
||||
Assert.assertEquals(TRACKPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("trackpoints"));
|
||||
Assert.assertEquals(WAYPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("waypoints"));
|
||||
assertEquals(TRACKS_CREATE_TABLE_V23, tablesByDowngrade.get("tracks"));
|
||||
assertEquals(TRACKPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("trackpoints"));
|
||||
assertEquals(WAYPOINTS_CREATE_TABLE_V23, tablesByDowngrade.get("waypoints"));
|
||||
|
||||
// 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.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||
|
||||
public class ShareContentProviderTest {
|
||||
|
||||
@Test
|
||||
public void testCreateandParseURI() {
|
||||
long[] trackIds = {1, 3, 5};
|
||||
public void testCreateandParseURI_invalid() {
|
||||
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);
|
||||
|
||||
Assert.assertArrayEquals(trackIds, ShareContentProvider.parseURI(shareURIandMIME.first));
|
||||
Assert.assertEquals(trackIds, ShareContentProvider.parseURI(shareURIandMIME.first));
|
||||
}
|
||||
|
||||
@Test
|
||||
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);
|
||||
|
||||
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.setSpeed(130);
|
||||
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.setSpeed(102);
|
||||
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.setSpeed(102);
|
||||
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 java.text.SimpleDateFormat;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Locale;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
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.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_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_1 = 2;
|
||||
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 Uri WAYPOINT_ID_O_URI = ContentUris.appendId(WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build();
|
||||
|
||||
@@ -76,7 +76,7 @@ public abstract class AbstractTestFileTrackImporter {
|
||||
|
||||
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.
|
||||
SimpleTimeZone utc = new SimpleTimeZone(0, "UTC");
|
||||
TimeZone utc = SimpleTimeZone.getTimeZone(ZoneOffset.UTC);
|
||||
DATE_FORMAT_0.setTimeZone(utc);
|
||||
DATE_FORMAT_1.setTimeZone(utc);
|
||||
}
|
||||
@@ -96,11 +96,11 @@ public abstract class AbstractTestFileTrackImporter {
|
||||
/**
|
||||
* Expects the first track point to be added.
|
||||
*
|
||||
* @param trackPoint the trackPoint
|
||||
* @param trackPoint the trackPoint
|
||||
* @param trackId the track 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);
|
||||
}
|
||||
|
||||
@@ -111,10 +111,10 @@ public abstract class AbstractTestFileTrackImporter {
|
||||
* @param lastTrack true if it is the last track in the gpx
|
||||
* @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());
|
||||
|
||||
when(contentProviderUtils.insertWaypoint((Waypoint) any())).thenReturn(WAYPOINT_ID_O_URI);
|
||||
when(contentProviderUtils.insertWaypoint(any())).thenReturn(WAYPOINT_ID_O_URI);
|
||||
if (lastTrack) {
|
||||
// Return null to not add waypoints
|
||||
when(contentProviderUtils.getTrack(trackId)).thenReturn(null);
|
||||
|
||||
@@ -17,8 +17,10 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
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.exporter.TrackExporter;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
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.
|
||||
@@ -48,9 +52,12 @@ public class ExportImportTest {
|
||||
private static final String TRACK_ICON = "the track icon";
|
||||
private static final String TRACK_CATEGORY = "the category";
|
||||
private static final String TRACK_DESCRIPTION = "the description";
|
||||
|
||||
private final List<Waypoint> waypoints = new ArrayList<>();
|
||||
private long importTrackId;
|
||||
private final long trackId = System.currentTimeMillis();
|
||||
private final List<TrackPoint> trackPoints = new ArrayList<>();
|
||||
|
||||
private Track.Id importTrackId;
|
||||
private final Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -61,6 +68,9 @@ public class ExportImportTest {
|
||||
contentProviderUtils.insertTrack(track.first);
|
||||
contentProviderUtils.bulkInsertTrackPoint(track.second, track.first.getId());
|
||||
|
||||
trackPoints.clear();
|
||||
trackPoints.addAll(Arrays.asList(track.second));
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Waypoint waypoint = new Waypoint(track.second[i].getLocation());
|
||||
waypoint.setName("the waypoint " + i);
|
||||
@@ -96,26 +106,59 @@ public class ExportImportTest {
|
||||
// given
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
|
||||
TrackFileFormat trackFileFormat = TrackFileFormat.KML_WITH_TRACKDETAIL;
|
||||
TrackExporter trackExporter = trackFileFormat.newTrackExporter(context, new Track[]{track});
|
||||
TrackExporter trackExporter = TrackFileFormat.KML_WITH_TRACKDETAIL.newTrackExporter(context);
|
||||
|
||||
// when
|
||||
// 1. export
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
trackExporter.writeTrack(context, outputStream);
|
||||
|
||||
System.out.println(outputStream.toString());
|
||||
trackExporter.writeTrack(track, outputStream);
|
||||
contentProviderUtils.deleteTrack(context, trackId);
|
||||
|
||||
// 2. import
|
||||
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);
|
||||
|
||||
// then
|
||||
// 1. track
|
||||
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
|
||||
assertNotNull(importedTrack);
|
||||
//TODO assertEquals(track.getTrackPoints(), importedTrack.getTrackPoints());
|
||||
assertEquals(track.getCategory(), importedTrack.getCategory());
|
||||
assertEquals(track.getDescription(), importedTrack.getDescription());
|
||||
assertEquals(track.getName(), importedTrack.getName());
|
||||
@@ -124,14 +167,32 @@ public class ExportImportTest {
|
||||
// 2. waypoints
|
||||
assertWaypoints();
|
||||
|
||||
//TODO Check absolute time of trackpoints
|
||||
// 3. trackpoints
|
||||
assertTrackpoints(true, true, true);
|
||||
}
|
||||
|
||||
@LargeTest
|
||||
@Test
|
||||
public void kml_with_trackdetail_and_sensordata() {
|
||||
// TODO
|
||||
Log.e(TAG, "Test not implemented.");
|
||||
public void kml_with_trackdetail_and_sensordata_duplicate_trackUUID() {
|
||||
// given
|
||||
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
|
||||
@@ -168,13 +229,13 @@ public class ExportImportTest {
|
||||
// given
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
|
||||
TrackFileFormat trackFileFormat = TrackFileFormat.GPX;
|
||||
TrackExporter trackExporter = trackFileFormat.newTrackExporter(context, new Track[]{track});
|
||||
TrackExporter trackExporter = TrackFileFormat.GPX.newTrackExporter(context);
|
||||
|
||||
// when
|
||||
// 1. export
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
trackExporter.writeTrack(context, outputStream);
|
||||
trackExporter.writeTrack(track, outputStream);
|
||||
contentProviderUtils.deleteTrack(context, trackId);
|
||||
|
||||
// 2. import
|
||||
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||
@@ -185,7 +246,6 @@ public class ExportImportTest {
|
||||
// 1. track
|
||||
Track trackImported = contentProviderUtils.getTrack(importTrackId);
|
||||
assertNotNull(trackImported);
|
||||
//TODO assertEquals(track.getTrackPoints(), trackImported.getTrackPoints());
|
||||
assertEquals(track.getCategory(), trackImported.getCategory());
|
||||
assertEquals(track.getDescription(), trackImported.getDescription());
|
||||
assertEquals(track.getName(), trackImported.getName());
|
||||
@@ -196,7 +256,33 @@ public class ExportImportTest {
|
||||
// 2. waypoints
|
||||
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() {
|
||||
@@ -217,4 +303,33 @@ public class ExportImportTest {
|
||||
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.runners.JUnit4;
|
||||
|
||||
import de.dennisguse.opentracks.services.handlers.AdaptiveLocationListenerPolicy;
|
||||
|
||||
/**
|
||||
* Tests the {@link AdaptiveLocationListenerPolicy}.
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.location.Location;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
@@ -33,6 +34,7 @@ import androidx.test.rule.ServiceTestRule;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -69,10 +71,17 @@ public class TrackRecordingServiceTest {
|
||||
@Rule
|
||||
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 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) {
|
||||
return new Intent(context, TrackRecordingService.class);
|
||||
@@ -125,7 +134,7 @@ public class TrackRecordingServiceTest {
|
||||
@Test
|
||||
public void testRecording_noTracks() throws Exception {
|
||||
// given
|
||||
List<Track> tracks = contentProviderUtils.getAllTracks();
|
||||
List<Track> tracks = contentProviderUtils.getTracks();
|
||||
Assert.assertTrue(tracks.isEmpty());
|
||||
|
||||
// when
|
||||
@@ -136,7 +145,7 @@ public class TrackRecordingServiceTest {
|
||||
// then
|
||||
// Test if we start in no-recording mode by default.
|
||||
Assert.assertFalse(service.isRecording());
|
||||
Assert.assertEquals(-1L, service.getRecordingTrackId());
|
||||
Assert.assertNull(service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
@@ -150,7 +159,7 @@ public class TrackRecordingServiceTest {
|
||||
|
||||
// then
|
||||
Assert.assertFalse(service.isRecording());
|
||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
||||
Assert.assertNull(service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
@@ -172,7 +181,7 @@ public class TrackRecordingServiceTest {
|
||||
// given
|
||||
createDummyTrack(trackId, -1L, true);
|
||||
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
||||
insertLocation(service);
|
||||
newTrackPoint(service);
|
||||
|
||||
// when
|
||||
service.pauseCurrentTrack();
|
||||
@@ -182,7 +191,7 @@ public class TrackRecordingServiceTest {
|
||||
|
||||
//when
|
||||
service.resumeTrack(trackId);
|
||||
insertLocation(service);
|
||||
newTrackPoint(service);
|
||||
|
||||
// then
|
||||
Assert.assertTrue(service.isRecording());
|
||||
@@ -201,14 +210,14 @@ public class TrackRecordingServiceTest {
|
||||
// given
|
||||
createDummyTrack(trackId, -1L, true);
|
||||
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
||||
insertLocation(service);
|
||||
newTrackPoint(service);
|
||||
service.endCurrentTrack();
|
||||
|
||||
Assert.assertEquals(1, contentProviderUtils.getTrackPoints(trackId).size());
|
||||
|
||||
// when
|
||||
service.resumeTrack(trackId);
|
||||
insertLocation(service);
|
||||
newTrackPoint(service);
|
||||
|
||||
// then
|
||||
Assert.assertTrue(service.isRecording());
|
||||
@@ -234,7 +243,7 @@ public class TrackRecordingServiceTest {
|
||||
|
||||
// then
|
||||
Assert.assertFalse(service.isRecording());
|
||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
||||
Assert.assertNull(service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
@@ -245,13 +254,13 @@ public class TrackRecordingServiceTest {
|
||||
service.startNewTrack();
|
||||
Assert.assertTrue(service.isRecording());
|
||||
|
||||
long trackId = service.getRecordingTrackId();
|
||||
Track.Id trackId = service.getRecordingTrackId();
|
||||
|
||||
// when
|
||||
long newTrackId = service.startNewTrack();
|
||||
Track.Id newTrackId = service.startNewTrack();
|
||||
|
||||
// then
|
||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, newTrackId);
|
||||
Assert.assertNull(newTrackId);
|
||||
|
||||
Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context));
|
||||
Assert.assertEquals(trackId, service.getRecordingTrackId());
|
||||
@@ -270,7 +279,7 @@ public class TrackRecordingServiceTest {
|
||||
|
||||
// then
|
||||
Assert.assertFalse(PreferencesUtils.isRecording(context));
|
||||
Assert.assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
||||
Assert.assertNull(service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
@@ -281,10 +290,10 @@ public class TrackRecordingServiceTest {
|
||||
Assert.assertFalse(service.isRecording());
|
||||
|
||||
// when
|
||||
long waypointId = service.insertWaypoint(null, null, null, null);
|
||||
Waypoint.Id waypointId = service.insertWaypoint(null, null, null, null);
|
||||
|
||||
// then
|
||||
Assert.assertEquals(-1L, waypointId);
|
||||
Assert.assertNull(waypointId);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
@@ -294,11 +303,11 @@ public class TrackRecordingServiceTest {
|
||||
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
|
||||
service.startNewTrack();
|
||||
Assert.assertTrue(service.isRecording());
|
||||
insertLocation(service);
|
||||
long trackId = service.getRecordingTrackId();
|
||||
newTrackPoint(service);
|
||||
Track.Id trackId = service.getRecordingTrackId();
|
||||
|
||||
// when
|
||||
long waypointId = service.insertWaypoint(null, null, null, null);
|
||||
Waypoint.Id waypointId = service.insertWaypoint(null, null, null, null);
|
||||
|
||||
// then
|
||||
Assert.assertNotEquals(-1L, waypointId);
|
||||
@@ -313,15 +322,15 @@ public class TrackRecordingServiceTest {
|
||||
}
|
||||
|
||||
private void addTrack(Track track, boolean isRecording) {
|
||||
Assert.assertTrue(track.getId() >= 0);
|
||||
Assert.assertTrue(track.getId().isValid());
|
||||
contentProviderUtils.insertTrack(track);
|
||||
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);
|
||||
}
|
||||
|
||||
// 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();
|
||||
dummyTrack.setId(id);
|
||||
dummyTrack.setName("Dummy Track");
|
||||
@@ -331,18 +340,18 @@ public class TrackRecordingServiceTest {
|
||||
addTrack(dummyTrack, isRecording);
|
||||
}
|
||||
|
||||
private static void insertLocation(TrackRecordingServiceInterface trackRecordingService) throws InterruptedException {
|
||||
insertLocation(trackRecordingService, 45.0f, 35f, 5, 10, System.currentTimeMillis());
|
||||
private static void newTrackPoint(TrackRecordingServiceInterface trackRecordingService) throws InterruptedException {
|
||||
newTrackPoint(trackRecordingService, 45.0f, 35f, 5, 10, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
static void insertLocation(TrackRecordingServiceInterface trackRecordingService, double latitude, double longitude, float accuracy, long speed) throws InterruptedException {
|
||||
insertLocation(trackRecordingService, latitude, longitude, accuracy, speed, System.currentTimeMillis());
|
||||
static void newTrackPoint(TrackRecordingServiceInterface trackRecordingService, double latitude, double longitude, float accuracy, long speed) throws InterruptedException {
|
||||
newTrackPoint(trackRecordingService, latitude, longitude, accuracy, speed, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.setLongitude(longitude);
|
||||
location.setLatitude(latitude);
|
||||
@@ -350,7 +359,9 @@ public class TrackRecordingServiceTest {
|
||||
location.setSpeed(speed);
|
||||
location.setTime(time);
|
||||
location.setBearing(3.0f);
|
||||
trackRecordingService.insertLocation(location);
|
||||
TrackPoint trackPoint = new TrackPoint(location);
|
||||
int prefAccuracy = PreferencesUtils.getRecordingGPSAccuracy(ApplicationProvider.getApplicationContext());
|
||||
trackRecordingService.newTrackPoint(trackPoint, prefAccuracy);
|
||||
|
||||
//TODO Needed?
|
||||
Thread.sleep(200);
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
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.TrackPointsColumns;
|
||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||
@@ -72,14 +73,11 @@ public class TrackRecordingServiceTestLocation {
|
||||
sharedPreferences.edit().clear().commit();
|
||||
|
||||
service = ((TrackRecordingServiceInterface) mServiceRule.bindService(TrackRecordingServiceTest.createStartIntent(context)));
|
||||
//Disable executorService to not insert locations from GPS via LocationManager
|
||||
service.enableLocationExecutor(false);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
// Reset service (if some previous test failed)
|
||||
service.enableLocationExecutor(true);
|
||||
if (service.isRecording() || service.isPaused()) {
|
||||
service.endCurrentTrack();
|
||||
}
|
||||
@@ -92,15 +90,15 @@ public class TrackRecordingServiceTestLocation {
|
||||
@Test
|
||||
public void testOnLocationChangedAsync_movingAccurate() throws Exception {
|
||||
// given
|
||||
long trackId = service.startNewTrack();
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
|
||||
// when
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0001, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0002, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0003, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0004, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0005, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0001, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0002, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0003, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0004, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0005, 35.0, 5, 15);
|
||||
|
||||
service.endCurrentTrack();
|
||||
|
||||
@@ -112,42 +110,19 @@ public class TrackRecordingServiceTestLocation {
|
||||
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
|
||||
@Test
|
||||
public void testOnLocationChangedAsync_slowMovingAccurate() throws Exception {
|
||||
// given
|
||||
long trackId = service.startNewTrack();
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
|
||||
// when
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.000001, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.000002, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.000003, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.000004, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.000005, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.000001, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.000002, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.000003, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.000004, 35.0, 5, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.000005, 35.0, 5, 15);
|
||||
|
||||
service.endCurrentTrack();
|
||||
|
||||
@@ -181,15 +156,15 @@ public class TrackRecordingServiceTestLocation {
|
||||
@Test
|
||||
public void testOnLocationChangedAsync_idle() throws Exception {
|
||||
// given
|
||||
long trackId = service.startNewTrack();
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
|
||||
// when
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 1, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 2, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 3, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 4, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 6, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 2, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 3, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 6, 0);
|
||||
|
||||
service.endCurrentTrack();
|
||||
|
||||
@@ -207,15 +182,15 @@ public class TrackRecordingServiceTestLocation {
|
||||
@Test
|
||||
public void testOnLocationChangedAsync_idle_withMovement() throws Exception {
|
||||
// given
|
||||
long trackId = service.startNewTrack();
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
|
||||
// when
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 1, 15);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 2, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 3, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 4, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 6, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 15);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 2, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 3, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 6, 15);
|
||||
|
||||
service.endCurrentTrack();
|
||||
|
||||
@@ -235,7 +210,7 @@ public class TrackRecordingServiceTestLocation {
|
||||
@Test
|
||||
public void testOnLocationChangedAsync_idle_withSensorData() throws Exception {
|
||||
// given
|
||||
long trackId = service.startNewTrack();
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
|
||||
service.setRemoteSensorManager(new BluetoothRemoteSensorManager(context) {
|
||||
|
||||
@@ -253,12 +228,12 @@ public class TrackRecordingServiceTestLocation {
|
||||
});
|
||||
|
||||
// when
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 0, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 1, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 2, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 3, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 4, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 5, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 0, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 2, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 3, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 5, 0);
|
||||
|
||||
service.endCurrentTrack();
|
||||
|
||||
@@ -279,14 +254,14 @@ public class TrackRecordingServiceTestLocation {
|
||||
@Test
|
||||
public void testOnLocationChangedAsync_segment() throws Exception {
|
||||
// given
|
||||
long trackId = service.startNewTrack();
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
|
||||
// when
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.0, 35.0, 1, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.1, 35.0, 2, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.1, 35.0, 3, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.2, 35.0, 4, 0);
|
||||
TrackRecordingServiceTest.insertLocation(service, 45.2, 35.0, 5, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.1, 35.0, 2, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.1, 35.0, 3, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.2, 35.0, 4, 0);
|
||||
TrackRecordingServiceTest.newTrackPoint(service, 45.2, 35.0, 5, 0);
|
||||
|
||||
service.endCurrentTrack();
|
||||
|
||||
@@ -303,25 +278,4 @@ public class TrackRecordingServiceTestLocation {
|
||||
Assert.assertEquals(4, trackPoints.get(5).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.content.data.Track;
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.content.provider.CustomContentProvider;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
@@ -186,7 +187,7 @@ public class TrackRecordingServiceTestLooper {
|
||||
@MediumTest
|
||||
@Test
|
||||
public void testIntegration_completeRecordingSession() throws TimeoutException {
|
||||
List<Track> tracks = contentProviderUtils.getAllTracks();
|
||||
List<Track> tracks = contentProviderUtils.getTracks();
|
||||
Assert.assertTrue(tracks.isEmpty());
|
||||
fullRecordingSession();
|
||||
}
|
||||
@@ -196,14 +197,14 @@ public class TrackRecordingServiceTestLooper {
|
||||
Assert.assertFalse(service.isRecording());
|
||||
|
||||
// Start a track.
|
||||
long id = service.startNewTrack();
|
||||
Assert.assertTrue(id >= 0);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
Assert.assertTrue(trackId.isValid());
|
||||
Assert.assertTrue(service.isRecording());
|
||||
Track track = contentProviderUtils.getTrack(id);
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
Assert.assertNotNull(track);
|
||||
Assert.assertEquals(id, track.getId());
|
||||
Assert.assertEquals(id, PreferencesUtils.getRecordingTrackId(context));
|
||||
Assert.assertEquals(id, service.getRecordingTrackId());
|
||||
Assert.assertEquals(trackId, track.getId());
|
||||
Assert.assertEquals(trackId, PreferencesUtils.getRecordingTrackId(context));
|
||||
Assert.assertEquals(trackId, service.getRecordingTrackId());
|
||||
|
||||
// Insert a few points, markers and statistics.
|
||||
long startTime = System.currentTimeMillis();
|
||||
@@ -215,7 +216,9 @@ public class TrackRecordingServiceTestLooper {
|
||||
location.setSpeed(10);
|
||||
location.setTime(startTime + i * 10000);
|
||||
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) {
|
||||
service.insertWaypoint(null, null, null, null);
|
||||
@@ -225,10 +228,10 @@ public class TrackRecordingServiceTestLooper {
|
||||
// Stop the track. Validate if it has correct data.
|
||||
service.endCurrentTrack();
|
||||
Assert.assertFalse(service.isRecording());
|
||||
Assert.assertEquals(-1L, service.getRecordingTrackId());
|
||||
track = contentProviderUtils.getTrack(id);
|
||||
Assert.assertNull(service.getRecordingTrackId());
|
||||
track = contentProviderUtils.getTrack(trackId);
|
||||
Assert.assertNotNull(track);
|
||||
Assert.assertEquals(id, track.getId());
|
||||
Assert.assertEquals(trackId, track.getId());
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
Assert.assertNotNull(trackStatistics);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,7 @@ public class StringUtilsTest {
|
||||
*/
|
||||
@Test
|
||||
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: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));
|
||||
}
|
||||
|
||||
@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 de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
|
||||
/**
|
||||
* Tests {@link TrackNameUtils}.
|
||||
@@ -39,7 +40,7 @@ import de.dennisguse.opentracks.R;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
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 Context CONTEXT = ApplicationProvider.getApplicationContext();
|
||||
@@ -69,6 +70,6 @@ public class TrackNameUtilsTest {
|
||||
@Test
|
||||
public void testTrackName_number() {
|
||||
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"?><!--
|
||||
Copyright 2013 Google Inc.
|
||||
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.
|
||||
@@ -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
|
||||
limitations under the License.
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_button_stop_pressed" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/ic_button_stop" />
|
||||
</selector>
|
||||
<resources>
|
||||
<string name="app_name">OpenTracks (Debug)</string>
|
||||
</resources>
|
||||
@@ -14,48 +14,102 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="de.dennisguse.opentracks"
|
||||
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
|
||||
android:name=".Startup"
|
||||
android:allowBackup="false"
|
||||
android:hasFragileUserData="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:icon="${applicationLogo}"
|
||||
android:label="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/ThemeCustom">
|
||||
|
||||
<!-- Activities -->
|
||||
<activity android:name=".AboutActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".TrackDeleteActivity"
|
||||
android:theme="@style/ThemeCustomTransparent" />
|
||||
android:theme="@style/TrackDeleteActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".HelpActivity"
|
||||
android:label="@string/menu_help" />
|
||||
|
||||
<activity android:name=".io.file.importer.DirectoryChooserActivity$ImportDirectoryChooserActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".io.file.importer.ImportActivity"
|
||||
android:theme="@style/ThemeCustomTransparent">
|
||||
android:theme="@style/ThemeCustomTransparentActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.ATTACH_DATA" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<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/vnd.google-earth.gpx" />
|
||||
<data android:mimeType="application/vnd.google-earth.gpx+xml" />
|
||||
<data android:scheme="file" />
|
||||
<data
|
||||
android:scheme="content"
|
||||
android:host="*"
|
||||
android:pathPattern="*gpx" />
|
||||
</intent-filter>
|
||||
</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" />
|
||||
|
||||
@@ -78,13 +132,9 @@ limitations under the License.
|
||||
android:resource="@xml/searchable" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".TrackRecordedActivity"
|
||||
android:screenOrientation="userPortrait" />
|
||||
<activity android:name=".TrackRecordedActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".TrackRecordingActivity"
|
||||
android:screenOrientation="userPortrait" />
|
||||
<activity android:name=".TrackRecordingActivity" />
|
||||
|
||||
<activity android:name=".TrackEditActivity" />
|
||||
|
||||
@@ -98,12 +148,29 @@ limitations under the License.
|
||||
android:value=".SearchListActivity" />
|
||||
</activity>
|
||||
|
||||
<activity android:name=".AggregatedStatisticsActivity" />
|
||||
|
||||
<activity android:name=".io.file.importer.DirectoryChooserActivity$ExportDirectoryChooserActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".io.file.exporter.ExportActivity"
|
||||
android:theme="@style/ThemeCustomTransparent" />
|
||||
android:theme="@style/ThemeCustomTransparentActivity" />
|
||||
|
||||
<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
|
||||
android:name=".content.provider.ShareContentProvider"
|
||||
android:authorities="${applicationId}.content"
|
||||
@@ -128,32 +195,4 @@ limitations under the License.
|
||||
android:icon="@drawable/ic_logo_color_24dp"
|
||||
android:label="@string/recording_service" />
|
||||
</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>
|
||||
|
||||
@@ -2,7 +2,6 @@ package de.dennisguse.opentracks;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -30,7 +29,7 @@ public class AboutActivity extends AbstractActivity {
|
||||
TextView textURL = findViewById(R.id.about_app_url);
|
||||
textURL.setText(getString(R.string.about_url, getString(R.string.app_web_url)));
|
||||
|
||||
ViewUtils.makeClickableLinks((ViewGroup) findViewById(android.R.id.content));
|
||||
ViewUtils.makeClickableLinks(findViewById(android.R.id.content));
|
||||
}
|
||||
|
||||
protected int getLayoutResId() {
|
||||
|
||||
@@ -18,6 +18,10 @@ package de.dennisguse.opentracks;
|
||||
|
||||
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.ConfirmDeleteCaller;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
@@ -55,30 +59,29 @@ public abstract class AbstractListActivity extends AbstractActivity implements C
|
||||
*
|
||||
* @param trackIds the track ids
|
||||
*/
|
||||
protected void deleteTracks(long[] trackIds) {
|
||||
protected void deleteTracks(Track.Id... trackIds) {
|
||||
ConfirmDeleteDialogFragment.showDialog(getSupportFragmentManager(), trackIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfirmDeleteDone(long[] trackIds) {
|
||||
public void onConfirmDeleteDone(Track.Id... trackIds) {
|
||||
boolean stopRecording = false;
|
||||
if (trackIds.length == 1 && trackIds[0] == -1L) {
|
||||
stopRecording = true;
|
||||
} else {
|
||||
long recordingTrackId = PreferencesUtils.getRecordingTrackId(this);
|
||||
for (long trackId : trackIds) {
|
||||
if (trackId == recordingTrackId) {
|
||||
stopRecording = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Track.Id recordingTrackId = PreferencesUtils.getRecordingTrackId(this);
|
||||
for (Track.Id trackId : trackIds) {
|
||||
if (trackId.equals(recordingTrackId)) {
|
||||
stopRecording = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stopRecording) {
|
||||
getTrackRecordingServiceConnection().stopRecording(this, false);
|
||||
}
|
||||
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);
|
||||
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,6 @@
|
||||
package de.dennisguse.opentracks;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -12,7 +11,7 @@ public class HelpActivity extends AbstractActivity {
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ViewUtils.makeClickableLinks((ViewGroup) findViewById(android.R.id.content));
|
||||
ViewUtils.makeClickableLinks(findViewById(android.R.id.content));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,32 +48,33 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark
|
||||
|
||||
private static final String TAG = MarkerDetailActivity.class.getSimpleName();
|
||||
|
||||
private List<Long> markerIds;
|
||||
private List<Waypoint.Id> waypointIds;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
long markerId = getIntent().getLongExtra(EXTRA_MARKER_ID, -1L);
|
||||
if (markerId == -1L) {
|
||||
Waypoint.Id waypointId = getIntent().getParcelableExtra(EXTRA_MARKER_ID);
|
||||
if (waypointId == null) {
|
||||
Log.d(TAG, "invalid marker id");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
|
||||
Waypoint waypoint = contentProviderUtils.getWaypoint(markerId);
|
||||
Waypoint waypoint = contentProviderUtils.getWaypoint(waypointId);
|
||||
|
||||
markerIds = new ArrayList<>();
|
||||
waypointIds = new ArrayList<>();
|
||||
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()) {
|
||||
for (int i = 0; i < cursor.getCount(); i++) {
|
||||
Waypoint currentMarker = contentProviderUtils.createWaypoint(cursor);
|
||||
markerIds.add(currentMarker.getId());
|
||||
if (currentMarker.getId() == markerId) {
|
||||
markerIndex = markerIds.size() - 1;
|
||||
waypointIds.add(currentMarker.getId());
|
||||
if (waypointId.equals(currentMarker.getId())) {
|
||||
markerIndex = waypointIds.size() - 1;
|
||||
}
|
||||
|
||||
cursor.moveToNext();
|
||||
@@ -109,12 +110,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark
|
||||
|
||||
@Override
|
||||
public void onDeleteMarkerDone() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
runOnUiThread(this::finish);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,13 +121,13 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark
|
||||
private class MarkerDetailPagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
MarkerDetailPagerAdapter(FragmentManager fragmentManager) {
|
||||
super(fragmentManager);
|
||||
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Fragment getItem(int position) {
|
||||
return MarkerDetailFragment.newInstance(markerIds.get(position));
|
||||
return MarkerDetailFragment.newInstance(waypointIds.get(position));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -142,7 +138,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return markerIds.size();
|
||||
return waypointIds.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import android.util.Pair;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
@@ -43,6 +42,7 @@ import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
|
||||
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.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_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 GALLERY_IMG_REQUEST_CODE = 7;
|
||||
|
||||
private static final String TAG = MarkerEditActivity.class.getSimpleName();
|
||||
private long trackId;
|
||||
private long markerId;
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||
private Track.Id trackId;
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection = new TrackRecordingServiceConnection();
|
||||
private Waypoint waypoint;
|
||||
|
||||
private MenuItem insertPhotoMenuItem;
|
||||
@@ -80,15 +81,13 @@ public class MarkerEditActivity extends AbstractActivity {
|
||||
private EditText waypointDescription;
|
||||
private ImageView waypointPhoto;
|
||||
private ImageView waypointDeletePhotoBtn;
|
||||
private Button done;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L);
|
||||
markerId = getIntent().getLongExtra(EXTRA_MARKER_ID, -1L);
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(null);
|
||||
trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID);
|
||||
Waypoint.Id waypointId = getIntent().getParcelableExtra(EXTRA_MARKER_ID);
|
||||
|
||||
hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
|
||||
|
||||
@@ -101,26 +100,67 @@ public class MarkerEditActivity extends AbstractActivity {
|
||||
waypointPhoto = findViewById(R.id.marker_edit_waypoint_photo);
|
||||
|
||||
waypointDeletePhotoBtn = findViewById(R.id.marker_edit_waypoint_photo_delete);
|
||||
waypointDeletePhotoBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (waypoint != null && waypoint.hasPhoto())
|
||||
waypoint.setPhotoUrl(null);
|
||||
waypointPhoto.setImageBitmap(null);
|
||||
photoUri = null;
|
||||
hideAndShowOptions();
|
||||
waypointDeletePhotoBtn.setOnClickListener(v -> {
|
||||
if (waypoint != null && waypoint.hasPhoto()) {
|
||||
waypoint.setPhotoUrl(null);
|
||||
}
|
||||
waypointPhoto.setImageBitmap(null);
|
||||
photoUri = null;
|
||||
hideAndShowOptions();
|
||||
});
|
||||
|
||||
Button cancel = findViewById(R.id.marker_edit_cancel);
|
||||
cancel.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
cancel.setOnClickListener(v -> finish());
|
||||
|
||||
final boolean isNewMarker = waypointId == null;
|
||||
|
||||
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
|
||||
@@ -129,6 +169,12 @@ public class MarkerEditActivity extends AbstractActivity {
|
||||
trackRecordingServiceConnection.startConnection(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putParcelable(BUNDLE_PHOTO_URI, photoUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
@@ -198,54 +244,6 @@ public class MarkerEditActivity extends AbstractActivity {
|
||||
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.
|
||||
*
|
||||
@@ -263,8 +261,8 @@ public class MarkerEditActivity extends AbstractActivity {
|
||||
/**
|
||||
* Returns the trackId. If trackId == -1 then get it from waypoint object.
|
||||
*/
|
||||
private long getTrackId() {
|
||||
return trackId == -1 ? waypoint.getTrackId() : trackId;
|
||||
private Track.Id getTrackId() {
|
||||
return trackId == null ? waypoint.getTrackId() : trackId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,13 +270,13 @@ public class MarkerEditActivity extends AbstractActivity {
|
||||
*
|
||||
* @param uri the uri photo.
|
||||
*/
|
||||
private void setWaypointImageView(Uri uri) {
|
||||
private void setWaypointImageView(@NonNull Uri uri) {
|
||||
try (ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "r")) {
|
||||
FileDescriptor fd = pfd.getFileDescriptor();
|
||||
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
|
||||
waypointPhoto.setImageBitmap(bitmap);
|
||||
hideAndShowOptions();
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a marker.
|
||||
*/
|
||||
private void addMarker() {
|
||||
trackRecordingServiceConnection.addMarker(this,
|
||||
waypointName.getText().toString(),
|
||||
@@ -306,9 +301,6 @@ public class MarkerEditActivity extends AbstractActivity {
|
||||
photoUri != null ? photoUri.toString() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a marker.
|
||||
*/
|
||||
private void saveMarker() {
|
||||
waypoint.setName(waypointName.getText().toString());
|
||||
waypoint.setCategory(waypointMarkerType.getText().toString());
|
||||
|
||||
@@ -26,18 +26,16 @@ import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ListView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
|
||||
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.provider.ContentProviderUtils;
|
||||
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[] PROJECTION = new String[]{WaypointsColumns._ID,
|
||||
WaypointsColumns.NAME, WaypointsColumns.DESCRIPTION, WaypointsColumns.CATEGORY,
|
||||
WaypointsColumns.TIME, WaypointsColumns.PHOTOURL,
|
||||
WaypointsColumns.LATITUDE, WaypointsColumns.LONGITUDE};
|
||||
|
||||
private ContentProviderUtils contentProviderUtils;
|
||||
|
||||
private SharedPreferences sharedPreferences;
|
||||
|
||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||
private Track.Id recordingTrackId;
|
||||
private boolean recordingTrackPaused;
|
||||
|
||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@@ -82,12 +75,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(MarkerListActivity.this);
|
||||
}
|
||||
if (key != null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MarkerListActivity.this.invalidateOptionsMenu();
|
||||
}
|
||||
});
|
||||
runOnUiThread(MarkerListActivity.this::invalidateOptionsMenu);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -124,23 +112,20 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
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);
|
||||
|
||||
contentProviderUtils = new ContentProviderUtils(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.setEmptyView(findViewById(R.id.marker_list_empty));
|
||||
listView.setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Intent intent = IntentUtils.newIntent(MarkerListActivity.this, MarkerDetailActivity.class)
|
||||
.putExtra(MarkerDetailActivity.EXTRA_MARKER_ID, id);
|
||||
startActivity(intent);
|
||||
}
|
||||
listView.setOnItemClickListener((parent, view, position, id) -> {
|
||||
Intent intent = IntentUtils.newIntent(MarkerListActivity.this, MarkerDetailActivity.class)
|
||||
.putExtra(MarkerDetailActivity.EXTRA_MARKER_ID, new Waypoint.Id(id));
|
||||
startActivity(intent);
|
||||
});
|
||||
resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) {
|
||||
@Override
|
||||
@@ -173,14 +158,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
||||
@NonNull
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||
if (track != 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);
|
||||
}
|
||||
return ContentProviderUtils.getWaypointsLoader(MarkerListActivity.this, track != null ? track.getId() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -233,7 +211,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -251,34 +229,38 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
||||
/**
|
||||
* Handles a context item selection.
|
||||
*
|
||||
* @param itemId the menu item id
|
||||
* @param markerIds the marker ids
|
||||
* @param itemId the menu item id
|
||||
* @param longWaypointIds the marker ids
|
||||
* @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;
|
||||
switch (itemId) {
|
||||
case R.id.list_context_menu_show_on_map:
|
||||
if (markerIds.length == 1) {
|
||||
IntentUtils.showCoordinateOnMap(this, contentProviderUtils.getWaypoint(markerIds[0]));
|
||||
if (waypointIds.length == 1) {
|
||||
IntentUtils.showCoordinateOnMap(this, contentProviderUtils.getWaypoint(waypointIds[0]));
|
||||
}
|
||||
return true;
|
||||
case R.id.list_context_menu_edit:
|
||||
if (markerIds.length == 1) {
|
||||
if (waypointIds.length == 1) {
|
||||
intent = IntentUtils.newIntent(this, MarkerEditActivity.class)
|
||||
.putExtra(MarkerEditActivity.EXTRA_MARKER_ID, markerIds[0]);
|
||||
.putExtra(MarkerEditActivity.EXTRA_MARKER_ID, waypointIds[0]);
|
||||
startActivity(intent);
|
||||
}
|
||||
return true;
|
||||
case R.id.list_context_menu_delete:
|
||||
if (markerIds.length > 1 && markerIds.length == listView.getCount()) {
|
||||
markerIds = new long[]{-1L};
|
||||
if (waypointIds.length > 1 && waypointIds.length == listView.getCount()) {
|
||||
waypointIds = null;
|
||||
}
|
||||
DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), markerIds);
|
||||
DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), waypointIds);
|
||||
return true;
|
||||
case R.id.list_context_menu_select_all:
|
||||
int size = listView.getCount();
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int i = 0; i < listView.getCount(); i++) {
|
||||
listView.setItemChecked(i, true);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -26,8 +26,6 @@ import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
@@ -99,7 +97,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
||||
|
||||
private boolean metricUnits = true;
|
||||
|
||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||
private Track.Id recordingTrackId;
|
||||
|
||||
private boolean recordingTrackPaused;
|
||||
|
||||
@@ -153,12 +151,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(SearchListActivity.this);
|
||||
}
|
||||
if (key != null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
arrayAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
runOnUiThread(() -> arrayAdapter.notifyDataSetChanged());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -172,7 +165,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
||||
|
||||
contentProviderUtils = new ContentProviderUtils(this);
|
||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(null);
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection();
|
||||
searchEngine = new SearchEngine(contentProviderUtils);
|
||||
|
||||
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.setAdapter(arrayAdapter);
|
||||
listView.setEmptyView(findViewById(R.id.search_list_empty));
|
||||
listView.setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Map<String, Object> item = arrayAdapter.getItem(position);
|
||||
Long trackId = (Long) item.get(TRACK_ID_FIELD);
|
||||
Long markerId = (Long) item.get(MARKER_ID_FIELD);
|
||||
Intent intent = IntentUtils.newIntent(SearchListActivity.this, TrackRecordedActivity.class);
|
||||
if (markerId != null) {
|
||||
intent = intent.putExtra(TrackRecordedActivity.EXTRA_MARKER_ID, markerId);
|
||||
} else {
|
||||
intent = intent.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId);
|
||||
}
|
||||
startActivity(intent);
|
||||
listView.setOnItemClickListener((parent, view, position, id) -> {
|
||||
Map<String, Object> item = arrayAdapter.getItem(position);
|
||||
Track.Id trackId = (Track.Id) item.get(TRACK_ID_FIELD);
|
||||
Long markerId = (Long) item.get(MARKER_ID_FIELD);
|
||||
Intent intent = IntentUtils.newIntent(SearchListActivity.this, TrackRecordedActivity.class);
|
||||
if (markerId != null) {
|
||||
intent = intent.putExtra(TrackRecordedActivity.EXTRA_MARKER_ID, markerId);
|
||||
} else {
|
||||
intent = intent.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId);
|
||||
}
|
||||
startActivity(intent);
|
||||
});
|
||||
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
|
||||
handleIntent(getIntent());
|
||||
@@ -280,22 +270,22 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
||||
return false;
|
||||
}
|
||||
Map<String, Object> item = arrayAdapter.getItem(positions[0]);
|
||||
Long trackId = (Long) item.get(TRACK_ID_FIELD);
|
||||
Long markerId = (Long) item.get(MARKER_ID_FIELD);
|
||||
Track.Id trackId = (Track.Id) item.get(TRACK_ID_FIELD);
|
||||
Waypoint.Id waypointId = (Waypoint.Id) item.get(MARKER_ID_FIELD);
|
||||
Intent intent;
|
||||
switch (itemId) {
|
||||
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) + "");
|
||||
return true;
|
||||
case R.id.list_context_menu_share:
|
||||
intent = IntentUtils.newShareFileIntent(this, new long[]{trackId});
|
||||
intent = IntentUtils.newShareFileIntent(this, trackId);
|
||||
intent = Intent.createChooser(intent, null);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.list_context_menu_edit:
|
||||
if (markerId != null) {
|
||||
if (waypointId != null) {
|
||||
intent = IntentUtils.newIntent(this, MarkerEditActivity.class)
|
||||
.putExtra(MarkerEditActivity.EXTRA_MARKER_ID, markerId);
|
||||
.putExtra(MarkerEditActivity.EXTRA_MARKER_ID, waypointId);
|
||||
} else {
|
||||
intent = IntentUtils.newIntent(this, TrackEditActivity.class)
|
||||
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId);
|
||||
@@ -306,10 +296,10 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
||||
finish();
|
||||
return true;
|
||||
case R.id.list_context_menu_delete:
|
||||
if (markerId != null) {
|
||||
DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), new long[]{markerId});
|
||||
if (waypointId != null) {
|
||||
DeleteMarkerDialogFragment.showDialog(getSupportFragmentManager(), waypointId);
|
||||
} else {
|
||||
deleteTracks(new long[]{trackId});
|
||||
deleteTracks(trackId);
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
@@ -341,17 +331,14 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
||||
* @param textQuery the query
|
||||
*/
|
||||
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);
|
||||
final List<Map<String, Object>> displayResults = prepareResultsforDisplay(scoredResults);
|
||||
|
||||
// Use the UI thread to display the results
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
arrayAdapter.clear();
|
||||
arrayAdapter.addAll(displayResults);
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
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.
|
||||
String trackName = null;
|
||||
long trackId = waypoint.getTrackId();
|
||||
if (trackId != -1L) {
|
||||
Track.Id trackId = waypoint.getTrackId();
|
||||
if (!trackId.isValid()) {
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
if (track != null) {
|
||||
trackName = track.getName();
|
||||
@@ -448,12 +435,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
||||
|
||||
@Override
|
||||
public void onDeleteMarkerDone() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleIntent(getIntent());
|
||||
}
|
||||
});
|
||||
runOnUiThread(() -> handleIntent(getIntent()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -463,11 +445,6 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
|
||||
|
||||
@Override
|
||||
protected void onDeleted() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleIntent(getIntent());
|
||||
}
|
||||
});
|
||||
runOnUiThread(() -> 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.util.Log;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
|
||||
/**
|
||||
@@ -25,7 +27,16 @@ public class Startup extends Application {
|
||||
|
||||
//Set default values of preferences on first start.
|
||||
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.
|
||||
if (BuildConfig.DEBUG) {
|
||||
|
||||
@@ -16,15 +16,24 @@
|
||||
|
||||
package de.dennisguse.opentracks;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||
import de.dennisguse.opentracks.util.ActivityUtils;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
import de.dennisguse.opentracks.util.UnitConversions;
|
||||
|
||||
@@ -46,12 +55,12 @@ public class TrackController {
|
||||
private final ImageButton recordImageButton;
|
||||
private final ImageButton stopImageButton;
|
||||
private final boolean alwaysShow;
|
||||
private ButtonDelay buttonDelay;
|
||||
|
||||
private boolean isRecording;
|
||||
private boolean isPaused;
|
||||
private long totalTime = 0;
|
||||
|
||||
// the timestamp for the toal time
|
||||
private long totalTimeTimestamp = 0;
|
||||
|
||||
private boolean isResumed = false;
|
||||
@@ -66,6 +75,7 @@ public class TrackController {
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
TrackController(Activity activity, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean alwaysShow, OnClickListener recordListener, OnClickListener stopListener) {
|
||||
this.activity = activity;
|
||||
this.trackRecordingServiceConnection = trackRecordingServiceConnection;
|
||||
@@ -76,10 +86,91 @@ public class TrackController {
|
||||
totalTimeTextView = activity.findViewById(R.id.track_controller_total_time);
|
||||
|
||||
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.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) {
|
||||
@@ -96,10 +187,10 @@ public class TrackController {
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
statusTextView.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
||||
|
||||
@@ -16,26 +16,29 @@
|
||||
|
||||
package de.dennisguse.opentracks;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
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
|
||||
*/
|
||||
public class TrackDeleteActivity extends Activity {
|
||||
public class TrackDeleteActivity extends AbstractActivity {
|
||||
|
||||
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
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -44,53 +47,48 @@ public class TrackDeleteActivity extends Activity {
|
||||
setResult(RESULT_CANCELED);
|
||||
|
||||
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();
|
||||
if (retained instanceof DeleteAsyncTask) {
|
||||
deleteAsyncTask = (DeleteAsyncTask) retained;
|
||||
deleteAsyncTask.setActivity(this);
|
||||
} else {
|
||||
deleteAsyncTask = new DeleteAsyncTask(this, trackIds);
|
||||
deleteAsyncTask.execute();
|
||||
}
|
||||
PowerManager.WakeLock wakeLock = SystemUtils.acquireWakeLock(TrackDeleteActivity.this, null);
|
||||
|
||||
for (Track.Id id : trackIds) {
|
||||
if (Thread.interrupted()) {
|
||||
break;
|
||||
}
|
||||
contentProviderUtils.deleteTrack(TrackDeleteActivity.this, id);
|
||||
}
|
||||
|
||||
wakeLock = SystemUtils.releaseWakeLock(wakeLock);
|
||||
if (Thread.interrupted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
runOnUiThread(TrackDeleteActivity.this::onAsyncTaskCompleted);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onRetainNonConfigurationInstance() {
|
||||
deleteAsyncTask.setActivity(null);
|
||||
return deleteAsyncTask;
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
deleteThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id) {
|
||||
if (id != DIALOG_PROGRESS_ID) {
|
||||
return null;
|
||||
}
|
||||
return DialogUtils.createSpinnerProgressDialog(
|
||||
this, R.string.track_delete_progress_message, new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
deleteAsyncTask.cancel(true);
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
deleteThread.interrupt();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.track_delete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes when the associated AsyncTask completes.
|
||||
*/
|
||||
public void onAsyncTaskCompleted() {
|
||||
removeDialog(DIALOG_PROGRESS_ID);
|
||||
findViewById(R.id.progressbar).setVisibility(View.INVISIBLE);
|
||||
setResult(RESULT_OK);
|
||||
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.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
@@ -65,9 +64,9 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(null);
|
||||
long trackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1L);
|
||||
if (trackId == -1L) {
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection();
|
||||
Track.Id trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID);
|
||||
if (!trackId.isValid()) {
|
||||
Log.e(TAG, "invalid trackId");
|
||||
finish();
|
||||
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);
|
||||
activityType.setAdapter(adapter);
|
||||
activityType.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
activityType.setOnItemClickListener((parent, view, position, id) -> setActivityTypeIcon(TrackIconUtils.getIconValue(
|
||||
TrackEditActivity.this, (String) activityType.getAdapter().getItem(position))));
|
||||
activityType.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (!hasFocus) {
|
||||
setActivityTypeIcon(TrackIconUtils.getIconValue(
|
||||
TrackEditActivity.this, (String) activityType.getAdapter().getItem(position)));
|
||||
}
|
||||
});
|
||||
activityType.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (!hasFocus) {
|
||||
setActivityTypeIcon(TrackIconUtils.getIconValue(
|
||||
TrackEditActivity.this, activityType.getText().toString()));
|
||||
}
|
||||
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.setAdapter(TrackIconUtils.getIconSpinnerAdapter(this, iconValue));
|
||||
activityTypeIcon.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), activityType.getText().toString());
|
||||
}
|
||||
return true;
|
||||
activityTypeIcon.setOnTouchListener((v, event) -> {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), activityType.getText().toString());
|
||||
}
|
||||
return true;
|
||||
});
|
||||
activityTypeIcon.setOnKeyListener(new View.OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
|
||||
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), activityType.getText().toString());
|
||||
}
|
||||
return true;
|
||||
activityTypeIcon.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
|
||||
ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), activityType.getText().toString());
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
description = findViewById(R.id.track_edit_description);
|
||||
description.setText(track.getDescription());
|
||||
|
||||
Button saveButton = findViewById(R.id.track_edit_save);
|
||||
saveButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
TrackUtils.updateTrack(TrackEditActivity.this, track, nameEditText.getText().toString(),
|
||||
activityType.getText().toString(), description.getText().toString(),
|
||||
contentProviderUtils);
|
||||
finish();
|
||||
}
|
||||
saveButton.setOnClickListener(v -> {
|
||||
TrackUtils.updateTrack(TrackEditActivity.this, track, nameEditText.getText().toString(),
|
||||
activityType.getText().toString(), description.getText().toString(),
|
||||
contentProviderUtils);
|
||||
finish();
|
||||
});
|
||||
|
||||
Button cancel = findViewById(R.id.track_edit_cancel);
|
||||
@@ -155,12 +137,7 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
|
||||
cancel.setVisibility(View.GONE);
|
||||
} else {
|
||||
setTitle(R.string.menu_edit);
|
||||
cancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
cancel.setOnClickListener(v -> finish());
|
||||
cancel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
@@ -33,8 +34,6 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -44,25 +43,23 @@ import androidx.core.app.ActivityCompat;
|
||||
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
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.provider.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||
import de.dennisguse.opentracks.util.ActivityUtils;
|
||||
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||
import de.dennisguse.opentracks.util.IntentUtils;
|
||||
import de.dennisguse.opentracks.util.ListItemUtils;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.ServiceUtils;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||
import de.dennisguse.opentracks.util.TrackUtils;
|
||||
|
||||
/**
|
||||
* 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[] 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
|
||||
private ContentProviderUtils contentProviderUtils;
|
||||
private SharedPreferences sharedPreferences;
|
||||
@@ -84,12 +77,12 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
private TrackController trackController;
|
||||
private ListView listView;
|
||||
private ResourceCursorAdapter resourceCursorAdapter;
|
||||
private GpsStatusValue gpsStatusValue;
|
||||
|
||||
private final LoaderCallbacks<Cursor> loaderCallbacks = new LoaderCallbacks<Cursor>() {
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||
return new CursorLoader(TrackListActivity.this, TracksColumns.CONTENT_URI, PROJECTION, null,
|
||||
null, TrackUtils.TRACK_SORT_ORDER);
|
||||
return ContentProviderUtils.getTracksCursorLoader(TrackListActivity.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,7 +98,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
|
||||
// Preferences
|
||||
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
|
||||
private final ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() {
|
||||
@@ -126,8 +119,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
|
||||
private boolean recordingTrackPaused;
|
||||
|
||||
private final OnSharedPreferenceChangeListener
|
||||
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String 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);
|
||||
}
|
||||
if (key != null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TrackListActivity.this.invalidateOptionsMenu();
|
||||
LoaderManager.getInstance(TrackListActivity.this).restartLoader(0, null, loaderCallbacks);
|
||||
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
||||
trackController.update(isRecording, recordingTrackPaused);
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
TrackListActivity.this.invalidateOptionsMenu();
|
||||
LoaderManager.getInstance(TrackListActivity.this).restartLoader(0, null, loaderCallbacks);
|
||||
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.
|
||||
private final Runnable bindChangedCallback = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
});
|
||||
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
||||
|
||||
if (!startGps) {
|
||||
return;
|
||||
}
|
||||
// After binding changes (e.g., becomes available), update the total time in trackController.
|
||||
runOnUiThread(() -> trackController.update(isRecording, recordingTrackPaused));
|
||||
|
||||
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
||||
if (service == null) {
|
||||
Log.d(TAG, "service not available to start gps or a new recording");
|
||||
gpsStatusValue = GpsStatusValue.GPS_NONE;
|
||||
return;
|
||||
}
|
||||
if (startGps) {
|
||||
service.startGps();
|
||||
startGps = false;
|
||||
|
||||
// Get GPS status and listen GPS status changes.
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -225,6 +216,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
gpsStatusValue = GpsStatusValue.GPS_NONE;
|
||||
|
||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||
|
||||
contentProviderUtils = new ContentProviderUtils(this);
|
||||
@@ -238,31 +231,23 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
// Show trackController when search dialog is dismissed
|
||||
SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
|
||||
if (searchManager != null) {
|
||||
searchManager.setOnDismissListener(new SearchManager.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
trackController.show();
|
||||
}
|
||||
});
|
||||
searchManager.setOnDismissListener(() -> trackController.show());
|
||||
}
|
||||
|
||||
listView = findViewById(R.id.track_list);
|
||||
listView.setEmptyView(findViewById(R.id.track_list_empty_view));
|
||||
listView.setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long trackId) {
|
||||
Intent newIntent;
|
||||
if (trackId == recordingTrackId) {
|
||||
// Is recording -> open record activity.
|
||||
newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class)
|
||||
.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId);
|
||||
} else {
|
||||
// Not recording -> open detail activity.
|
||||
newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordedActivity.class)
|
||||
.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId);
|
||||
}
|
||||
startActivity(newIntent);
|
||||
listView.setOnItemClickListener((parent, view, position, trackId) -> {
|
||||
Intent newIntent;
|
||||
if (trackId == recordingTrackId.getId()) {
|
||||
// Is recording -> open record activity.
|
||||
newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class)
|
||||
.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) {
|
||||
@@ -277,7 +262,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
int categoryIndex = cursor.getColumnIndex(TracksColumns.CATEGORY);
|
||||
int descriptionIndex = cursor.getColumnIndex(TracksColumns.DESCRIPTION);
|
||||
|
||||
long trackId = cursor.getLong(idIndex);
|
||||
Track.Id trackId = new Track.Id(cursor.getLong(idIndex));
|
||||
boolean isRecording = trackId == recordingTrackId;
|
||||
String icon = cursor.getString(iconIndex);
|
||||
int iconId = TrackIconUtils.getIconDrawable(icon);
|
||||
@@ -299,7 +284,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
|
||||
|
||||
LoaderManager.getInstance(this).initLoader(0, null, loaderCallbacks);
|
||||
showStartupDialogs();
|
||||
|
||||
requestGPSPermissions();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -366,7 +352,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
boolean isGpsStarted = ServiceUtils.isTrackRecordingServiceRunning(this);
|
||||
boolean isGpsStarted = isGpsStarted();
|
||||
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
||||
updateMenuItems(isGpsStarted, isRecording);
|
||||
|
||||
@@ -386,10 +372,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
|
||||
startActivity(intent);
|
||||
} else {
|
||||
startGps = !ServiceUtils.isTrackRecordingServiceRunning(this);
|
||||
|
||||
// Invoke trackRecordingService
|
||||
if (startGps) {
|
||||
if (!isGpsStarted()) {
|
||||
trackRecordingServiceConnection.startAndBind(this);
|
||||
bindChangedCallback.run();
|
||||
} else {
|
||||
@@ -404,6 +388,10 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
this.invalidateOptionsMenu();
|
||||
}
|
||||
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:
|
||||
intent = IntentUtils.newIntent(this, MarkerListActivity.class);
|
||||
startActivity(intent);
|
||||
@@ -441,17 +429,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows start up dialogs.
|
||||
*/
|
||||
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 boolean isGpsStarted() {
|
||||
return gpsStatusValue != GpsStatusValue.GPS_NONE && gpsStatusValue != GpsStatusValue.GPS_DISABLED;
|
||||
}
|
||||
|
||||
private void requestGPSPermissions() {
|
||||
@@ -461,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 isRecording true if recording
|
||||
*/
|
||||
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) {
|
||||
startGpsMenuItem.setVisible(!isRecording);
|
||||
if (!isRecording) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,15 +471,20 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
/**
|
||||
* Handles a context item selection.
|
||||
*
|
||||
* @param itemId the menu item id
|
||||
* @param trackIds the track ids
|
||||
* @param itemId the menu item id
|
||||
* @param longTrackIds the track ids
|
||||
* @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;
|
||||
switch (itemId) {
|
||||
case R.id.list_context_menu_show_on_map:
|
||||
IntentUtils.showTrackOnMap(this, trackIds);
|
||||
IntentDashboardUtils.startDashboard(this, false, trackIds);
|
||||
return true;
|
||||
case R.id.list_context_menu_share:
|
||||
intent = IntentUtils.newShareFileIntent(this, trackIds);
|
||||
@@ -500,9 +497,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.list_context_menu_delete:
|
||||
if (trackIds.length > 1 && trackIds.length == listView.getCount()) {
|
||||
trackIds = new long[]{-1L};
|
||||
}
|
||||
deleteTracks(trackIds);
|
||||
return true;
|
||||
case R.id.list_context_menu_select_all:
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package de.dennisguse.opentracks;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
@@ -40,6 +39,7 @@ 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;
|
||||
@@ -66,7 +66,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos
|
||||
private ViewPager pager;
|
||||
|
||||
// From intent.
|
||||
private long trackId;
|
||||
private Track.Id trackId;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -133,7 +133,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos
|
||||
// Update UI
|
||||
this.invalidateOptionsMenu();
|
||||
|
||||
if (trackId != -1L) {
|
||||
if (trackId.isValid()) {
|
||||
trackDataHub.loadTrack(trackId);
|
||||
}
|
||||
}
|
||||
@@ -182,12 +182,12 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos
|
||||
Intent intent;
|
||||
switch (item.getItemId()) {
|
||||
case R.id.track_detail_share:
|
||||
intent = IntentUtils.newShareFileIntent(this, new long[]{trackId});
|
||||
intent = IntentUtils.newShareFileIntent(this, trackId);
|
||||
intent = Intent.createChooser(intent, null);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.track_detail_menu_show_on_map:
|
||||
IntentUtils.showTrackOnMap(this, new long[]{trackId});
|
||||
IntentDashboardUtils.startDashboard(this, false, trackId);
|
||||
return true;
|
||||
case R.id.track_detail_markers:
|
||||
intent = IntentUtils.newIntent(this, MarkerListActivity.class)
|
||||
@@ -200,7 +200,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.track_detail_delete:
|
||||
deleteTracks(new long[]{trackId});
|
||||
deleteTracks(trackId);
|
||||
return true;
|
||||
case R.id.track_detail_resume_track:
|
||||
Intent newIntent = IntentUtils.newIntent(TrackRecordedActivity.this, TrackRecordingActivity.class)
|
||||
@@ -226,12 +226,7 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos
|
||||
|
||||
@Override
|
||||
protected void onDeleted() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
runOnUiThread(this::finish);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,12 +238,12 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L);
|
||||
trackId = intent.getParcelableExtra(EXTRA_TRACK_ID);
|
||||
|
||||
long markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L);
|
||||
if (markerId != -1L) {
|
||||
Waypoint.Id waypointId = intent.getParcelableExtra(EXTRA_MARKER_ID);
|
||||
if (waypointId != null) {
|
||||
// Use the trackId from the marker
|
||||
Waypoint waypoint = contentProviderUtils.getWaypoint(markerId);
|
||||
Waypoint waypoint = contentProviderUtils.getWaypoint(waypointId);
|
||||
if (waypoint == null) {
|
||||
finish();
|
||||
return;
|
||||
@@ -256,10 +251,9 @@ public class TrackRecordedActivity extends AbstractListActivity implements Choos
|
||||
trackId = waypoint.getTrackId();
|
||||
}
|
||||
|
||||
if (trackId == -1L) {
|
||||
if (trackId == null) {
|
||||
Log.e(TAG, "TrackDetailActivity needs EXTRA_TRACK_ID.");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package de.dennisguse.opentracks;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
@@ -12,10 +11,10 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
@@ -30,6 +29,7 @@ import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||
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;
|
||||
@@ -41,6 +41,8 @@ import de.dennisguse.opentracks.util.TrackUtils;
|
||||
* @author Leif Hendrik Wilden
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
//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";
|
||||
@@ -57,47 +59,34 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
private ViewPager pager;
|
||||
private TrackController trackController;
|
||||
|
||||
// From intent
|
||||
private long trackId;
|
||||
// Initialized from Intent; if a new track recording is started, a new TrackId will be provided by TrackRecordingService
|
||||
private Track.Id trackId;
|
||||
|
||||
// Preferences
|
||||
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
|
||||
private boolean recordingTrackPaused;
|
||||
|
||||
private final Runnable bindChangedCallback = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// After binding changes (is available), update the total time in trackController.
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
trackController.update(true, recordingTrackPaused);
|
||||
}
|
||||
});
|
||||
|
||||
if (recordingTrackId == -1L) {
|
||||
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
||||
if (service == null) {
|
||||
Log.d(TAG, "could not get TrackRecordingService");
|
||||
return;
|
||||
}
|
||||
runOnUiThread(() -> trackController.update(true, recordingTrackPaused));
|
||||
|
||||
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
||||
if (service == null) {
|
||||
Log.d(TAG, "could not get TrackRecordingService");
|
||||
return;
|
||||
}
|
||||
if (!service.isRecording()) {
|
||||
// Starts or resumes a track.
|
||||
int msg;
|
||||
if (trackId == -1L) {
|
||||
if (trackId == null) {
|
||||
// trackId isn't initialized -> leads a new recording.
|
||||
trackId = service.startNewTrack();
|
||||
recordingTrackId = trackId;
|
||||
msg = R.string.track_detail_record_success;
|
||||
} else {
|
||||
// trackId is initialized -> resumes the track.
|
||||
recordingTrackId = trackId;
|
||||
service.resumeTrack(trackId);
|
||||
msg = R.string.track_detail_resume_success;
|
||||
}
|
||||
|
||||
// A recording track is on.
|
||||
Toast.makeText(TrackRecordingActivity.this, msg, Toast.LENGTH_SHORT).show();
|
||||
trackDataHub.loadTrack(trackId);
|
||||
trackController.update(true, false);
|
||||
trackController.onResume(true, recordingTrackPaused);
|
||||
@@ -108,12 +97,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.recording_track_id_key, key)) {
|
||||
recordingTrackId = PreferencesUtils.getRecordingTrackId(TrackRecordingActivity.this);
|
||||
setLockscreenPolicy();
|
||||
setScreenOnPolicy();
|
||||
}
|
||||
|
||||
if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.recording_track_paused_key, key)) {
|
||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackRecordingActivity.this);
|
||||
setLockscreenPolicy();
|
||||
@@ -127,15 +110,15 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.stats_keep_screen_on_while_recording_key, key)) {
|
||||
setScreenOnPolicy();
|
||||
}
|
||||
if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.stats_fullscreen_while_recording_key, key)) {
|
||||
setFullscreenPolicy();
|
||||
}
|
||||
|
||||
if (key == null) return;
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TrackRecordingActivity.this.invalidateOptionsMenu();
|
||||
trackController.update(true, recordingTrackPaused);
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
TrackRecordingActivity.this.invalidateOptionsMenu();
|
||||
trackController.update(true, recordingTrackPaused);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -176,52 +159,28 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(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);
|
||||
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
||||
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 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);
|
||||
}
|
||||
return "Unknown Tab";
|
||||
}
|
||||
};
|
||||
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);
|
||||
tabs.setupWithViewPager(pager);
|
||||
if (savedInstanceState != null) {
|
||||
@@ -235,12 +194,12 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
public void onAttachedToWindow() {
|
||||
setLockscreenPolicy();
|
||||
setScreenOnPolicy();
|
||||
setFullscreenPolicy();
|
||||
super.onAttachedToWindow();
|
||||
}
|
||||
|
||||
private void setLockscreenPolicy() {
|
||||
boolean showOnLockScreen = PreferencesUtils.shouldShowStatsOnLockscreen(TrackRecordingActivity.this)
|
||||
&& PreferencesUtils.isRecording(this);
|
||||
boolean showOnLockScreen = PreferencesUtils.shouldShowStatsOnLockscreen(TrackRecordingActivity.this);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
setShowWhenLocked(showOnLockScreen);
|
||||
@@ -252,8 +211,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
}
|
||||
|
||||
private void setScreenOnPolicy() {
|
||||
boolean keepScreenOn = PreferencesUtils.shouldKeepScreenOn(TrackRecordingActivity.this)
|
||||
&& PreferencesUtils.isRecording(this);
|
||||
boolean keepScreenOn = PreferencesUtils.shouldKeepScreenOn(TrackRecordingActivity.this);
|
||||
|
||||
if (keepScreenOn) {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
@@ -262,6 +220,16 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
@@ -280,12 +248,25 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
// Update UI
|
||||
this.invalidateOptionsMenu();
|
||||
|
||||
if (trackId != -1L) {
|
||||
if (trackId != null) {
|
||||
trackDataHub.loadTrack(trackId);
|
||||
trackController.onResume(true, recordingTrackPaused);
|
||||
}
|
||||
|
||||
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
|
||||
@@ -302,24 +283,11 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
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_record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
handleIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.track_record, menu);
|
||||
@@ -347,7 +315,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.track_detail_menu_show_on_map:
|
||||
IntentUtils.showTrackOnMap(this, new long[]{trackId});
|
||||
IntentDashboardUtils.startDashboard(this, true, trackId);
|
||||
return true;
|
||||
case R.id.track_detail_markers:
|
||||
intent = IntentUtils.newIntent(this, MarkerListActivity.class)
|
||||
@@ -376,22 +344,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
return trackDataHub;
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L);
|
||||
if (trackId == -1L) {
|
||||
return;
|
||||
}
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
if (track == null) {
|
||||
track = contentProviderUtils.getLastTrack();
|
||||
if (track != null) {
|
||||
trackId = track.getId();
|
||||
return;
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the menu items.
|
||||
*/
|
||||
@@ -412,14 +364,44 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
||||
TrackUtils.updateTrack(this, track, null, category, null, contentProviderUtils);
|
||||
}
|
||||
|
||||
private void startRecording() {
|
||||
trackRecordingServiceConnection.startAndBind(this);
|
||||
private class CustomFragmentPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
bindChangedCallback.run();
|
||||
public CustomFragmentPagerAdapter(@NonNull FragmentManager fm, int behavior) {
|
||||
super(fm, behavior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
speed = trackStatisticsUpdater.getSmoothedSpeed() * UnitConversions.MS_TO_KMH;
|
||||
speed = trackStatisticsUpdater.getSmoothedSpeed() * UnitConversions.MPS_TO_KMH;
|
||||
if (!metricUnits) {
|
||||
speed *= UnitConversions.KM_TO_MI;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ public class DescriptionGenerator {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
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;
|
||||
builder.append(context.getString(resId, speedInKmHr, speedInMiHr));
|
||||
builder.append(lineBreak);
|
||||
|
||||
@@ -108,28 +108,25 @@ public class SearchEngine {
|
||||
/**
|
||||
* Comparator for scored results.
|
||||
*/
|
||||
private static final Comparator<ScoredResult> SCORED_RESULT_COMPARATOR = new Comparator<ScoredResult>() {
|
||||
@Override
|
||||
public int compare(ScoredResult r1, ScoredResult r2) {
|
||||
// Score ordering.
|
||||
int scoreDiff = Double.compare(r2.score, r1.score);
|
||||
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);
|
||||
private static final Comparator<ScoredResult> SCORED_RESULT_COMPARATOR = (r1, r2) -> {
|
||||
// Score ordering.
|
||||
int scoreDiff = Double.compare(r2.score, r1.score);
|
||||
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().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;
|
||||
@@ -293,7 +290,7 @@ public class SearchEngine {
|
||||
score *= getTimeBoost(query, location.getTime());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -385,10 +382,10 @@ public class SearchEngine {
|
||||
public static class SearchQuery {
|
||||
final String textQuery;
|
||||
final Location currentLocation;
|
||||
final long currentTrackId;
|
||||
final Track.Id currentTrackId;
|
||||
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.currentLocation = currentLocation;
|
||||
this.currentTrackId = currentTrackId;
|
||||
@@ -420,8 +417,8 @@ public class SearchEngine {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ScoredResult ["
|
||||
+ (track != null ? ("trackId=" + track.getId() + ", ") : "")
|
||||
+ (waypoint != null ? ("wptId=" + waypoint.getId() + ", ") : "")
|
||||
+ (track != null ? ("trackId=" + track.getId().getId() + ", ") : "")
|
||||
+ (waypoint != null ? ("wptId=" + waypoint.getId().getId() + ", ") : "")
|
||||
+ "score=" + score + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -78,8 +79,8 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
private Handler handler;
|
||||
|
||||
// Preference values
|
||||
private long selectedTrackId;
|
||||
private long recordingTrackId;
|
||||
private Track.Id selectedTrackId;
|
||||
private Track.Id recordingTrackId;
|
||||
private boolean recordingTrackPaused;
|
||||
|
||||
// Track points sampling state
|
||||
@@ -144,12 +145,9 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
|
||||
PreferencesUtils.register(context, this);
|
||||
onSharedPreferenceChanged(null, null);
|
||||
runInHandlerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (started) {
|
||||
loadDataForAll();
|
||||
}
|
||||
runInHandlerThread(() -> {
|
||||
if (started) {
|
||||
loadDataForAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -177,17 +175,14 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
handler = null;
|
||||
}
|
||||
|
||||
public void loadTrack(final long trackId) {
|
||||
runInHandlerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (trackId == selectedTrackId) {
|
||||
Log.i(TAG, "Not reloading track " + trackId);
|
||||
return;
|
||||
}
|
||||
selectedTrackId = trackId;
|
||||
loadDataForAll();
|
||||
public void loadTrack(final @NonNull Track.Id trackId) {
|
||||
runInHandlerThread(() -> {
|
||||
if (trackId.equals(selectedTrackId)) {
|
||||
Log.i(TAG, "Not reloading track " + trackId.getId());
|
||||
return;
|
||||
}
|
||||
selectedTrackId = trackId;
|
||||
loadDataForAll();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -197,13 +192,10 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
* @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) {
|
||||
runInHandlerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
trackDataManager.registerTrackDataListener(trackDataListener, tracksTable, waypointsTable, trackPointsTable_SampleIn, trackPointsTable_SampleOut);
|
||||
if (started) {
|
||||
loadDataForListener(trackDataListener);
|
||||
}
|
||||
runInHandlerThread(() -> {
|
||||
trackDataManager.registerTrackDataListener(trackDataListener, tracksTable, waypointsTable, trackPointsTable_SampleIn, trackPointsTable_SampleOut);
|
||||
if (started) {
|
||||
loadDataForListener(trackDataListener);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -214,39 +206,31 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
* @param trackDataListener the track data listener
|
||||
*/
|
||||
public void unregisterTrackDataListener(final TrackDataListener trackDataListener) {
|
||||
runInHandlerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
trackDataManager.unregisterTrackDataListener(trackDataListener);
|
||||
}
|
||||
});
|
||||
runInHandlerThread(() -> trackDataManager.unregisterTrackDataListener(trackDataListener));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the selected track is recording.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public boolean isSelectedTrackPaused() {
|
||||
return selectedTrackId == recordingTrackId && recordingTrackPaused;
|
||||
return selectedTrackId != null && selectedTrackId.equals(recordingTrackId) && recordingTrackPaused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, final String key) {
|
||||
runInHandlerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
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);
|
||||
}
|
||||
runInHandlerThread(() -> {
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -289,7 +273,7 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
if (isOnlyListener) {
|
||||
resetSamplingState();
|
||||
}
|
||||
Set<TrackDataListener> sampledOutListeners = hasSampledOut ? trackDataListeners : Collections.<TrackDataListener>emptySet();
|
||||
Set<TrackDataListener> sampledOutListeners = hasSampledOut ? trackDataListeners : Collections.emptySet();
|
||||
notifyTrackPointsTableUpdate(isOnlyListener, trackDataListeners, sampledOutListeners);
|
||||
}
|
||||
|
||||
@@ -328,7 +312,7 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
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()) {
|
||||
do {
|
||||
Waypoint waypoint = contentProviderUtils.createWaypoint(cursor);
|
||||
@@ -373,6 +357,11 @@ public class TrackDataHub implements SharedPreferences.OnSharedPreferenceChangeL
|
||||
long localLastSeenTrackPointIdId = updateSamplingState ? lastSeenTrackPointId : -1L;
|
||||
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);
|
||||
int samplingFrequency = -1;
|
||||
boolean includeNextPoint = false;
|
||||
|
||||
@@ -16,7 +16,17 @@
|
||||
|
||||
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.util.PreferencesUtils;
|
||||
|
||||
/**
|
||||
* A track.
|
||||
@@ -26,7 +36,9 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
*/
|
||||
public class Track {
|
||||
|
||||
private long id = -1L;
|
||||
private Track.Id id;
|
||||
private UUID uuid = UUID.randomUUID();
|
||||
|
||||
private String name = "";
|
||||
private String description = "";
|
||||
private String category = "";
|
||||
@@ -38,14 +50,26 @@ public class Track {
|
||||
public Track() {
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
/**
|
||||
* May be null if the track was not loaded from the database.
|
||||
*/
|
||||
public @Nullable
|
||||
Id getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
public void setId(Id id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -85,4 +109,66 @@ public class Track {
|
||||
public void setTrackStatistics(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");
|
||||
String CONTENT_TYPE = "vnd.android.cursor.dir/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
|
||||
String TRACKID = "trackid";
|
||||
|
||||
@@ -32,9 +32,10 @@ public interface TracksColumns extends BaseColumns {
|
||||
Uri CONTENT_URI = Uri.parse(ContentProviderUtils.CONTENT_BASE_URI + "/" + TABLE_NAME);
|
||||
String CONTENT_TYPE = "vnd.android.cursor.dir/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
|
||||
String UUID = "uuid";
|
||||
String NAME = "name"; // track name
|
||||
String DESCRIPTION = "description"; // track description
|
||||
String CATEGORY = "category"; // track activity type
|
||||
@@ -71,5 +72,9 @@ public interface TracksColumns extends BaseColumns {
|
||||
+ MINELEVATION + " FLOAT, " // min elevation
|
||||
+ MAXELEVATION + " FLOAT, " // max elevation
|
||||
+ 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.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
|
||||
/**
|
||||
* A waypoint.
|
||||
*
|
||||
@@ -30,15 +37,16 @@ import androidx.annotation.VisibleForTesting;
|
||||
*/
|
||||
public final class Waypoint {
|
||||
|
||||
private long id = -1L;
|
||||
private Id id;
|
||||
private String name = "";
|
||||
private String description = "";
|
||||
private String category = "";
|
||||
private String icon = "";
|
||||
private long trackId = -1L;
|
||||
private Track.Id trackId;
|
||||
private double length = 0.0;
|
||||
private long duration = 0;
|
||||
private Location location;
|
||||
@Deprecated //TODO Make an URI instead of String
|
||||
private String photoUrl = "";
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -50,7 +58,7 @@ public final class Waypoint {
|
||||
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.description = description;
|
||||
this.category = category;
|
||||
@@ -62,11 +70,15 @@ public final class Waypoint {
|
||||
this.photoUrl = photoUrl;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
/**
|
||||
* May be null if the waypoint was not loaded from the database.
|
||||
*/
|
||||
public @Nullable
|
||||
Id getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
public void setId(Id id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@@ -102,11 +114,11 @@ public final class Waypoint {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public long getTrackId() {
|
||||
public Track.Id getTrackId() {
|
||||
return trackId;
|
||||
}
|
||||
|
||||
public void setTrackId(long trackId) {
|
||||
public void setTrackId(Track.Id trackId) {
|
||||
this.trackId = trackId;
|
||||
}
|
||||
|
||||
@@ -146,4 +158,66 @@ public final class Waypoint {
|
||||
public boolean hasPhoto() {
|
||||
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";
|
||||
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_ITEMTYPE = "vnd.android.cursor.item/vnd.de.dennisguse.waypoint";
|
||||
String DEFAULT_SORT_ORDER = "_id";
|
||||
String DEFAULT_SORT_ORDER = _ID;
|
||||
|
||||
// Columns
|
||||
String NAME = "name"; // waypoint name
|
||||
|
||||
@@ -23,13 +23,19 @@ import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.BuildConfig;
|
||||
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.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
import de.dennisguse.opentracks.util.TrackUtils;
|
||||
import de.dennisguse.opentracks.util.UUIDUtils;
|
||||
|
||||
/**
|
||||
* {@link ContentProviderUtils} implementation.
|
||||
@@ -55,7 +63,8 @@ public class ContentProviderUtils {
|
||||
private static final int MAX_LATITUDE = 90000000;
|
||||
|
||||
// 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.
|
||||
public static final String CONTENT_BASE_URI = "content://" + AUTHORITY_PACKAGE;
|
||||
@@ -85,8 +94,8 @@ public class ContentProviderUtils {
|
||||
*
|
||||
* @param trackId the track id
|
||||
*/
|
||||
public void clearTrack(Context context, long trackId) {
|
||||
deleteTrackPointsAndWaypoints(context, trackId);
|
||||
public void clearTrack(Track.Id trackId) {
|
||||
deleteTrackPointsAndWaypoints(trackId);
|
||||
Track track = new Track();
|
||||
track.setId(trackId);
|
||||
updateTrack(track);
|
||||
@@ -99,6 +108,7 @@ public class ContentProviderUtils {
|
||||
*/
|
||||
public Track createTrack(Cursor cursor) {
|
||||
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
|
||||
int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID);
|
||||
int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME);
|
||||
int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
|
||||
int categoryIndex = cursor.getColumnIndexOrThrow(TracksColumns.CATEGORY);
|
||||
@@ -116,7 +126,10 @@ public class ContentProviderUtils {
|
||||
Track track = new Track();
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
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)) {
|
||||
track.setName(cursor.getString(nameIndex));
|
||||
@@ -160,9 +173,7 @@ public class ContentProviderUtils {
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all tracks (including waypoints and trackPoints).
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public void deleteAllTracks(Context context) {
|
||||
contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, null, null);
|
||||
contentResolver.delete(WaypointsColumns.CONTENT_URI, null, null);
|
||||
@@ -178,14 +189,17 @@ public class ContentProviderUtils {
|
||||
*
|
||||
* @param trackId the track id
|
||||
*/
|
||||
public void deleteTrack(Context context, long trackId) {
|
||||
deleteTrackPointsAndWaypoints(context, trackId);
|
||||
public void deleteTrack(Context context, Track.Id trackId) {
|
||||
if (trackId == null) {
|
||||
return;
|
||||
}
|
||||
deleteTrackPointsAndWaypoints(trackId);
|
||||
|
||||
// Delete track folder resources.
|
||||
FileUtils.deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId));
|
||||
|
||||
// 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
|
||||
*/
|
||||
private void deleteTrackPointsAndWaypoints(Context context, long trackId) {
|
||||
String where = TrackPointsColumns.TRACKID + "=?";
|
||||
String[] selectionArgs = new String[]{Long.toString(trackId)};
|
||||
contentResolver.delete(TrackPointsColumns.CONTENT_URI_BY_ID, where, selectionArgs);
|
||||
private void deleteTrackPointsAndWaypoints(@NonNull Track.Id trackId) {
|
||||
String[] selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||
|
||||
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
|
||||
public List<Track> getAllTracks() {
|
||||
public List<Track> getTracks() {
|
||||
ArrayList<Track> tracks = new ArrayList<>();
|
||||
try (Cursor cursor = getTrackCursor(null, null, TracksColumns._ID)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
@@ -220,6 +228,17 @@ public class ContentProviderUtils {
|
||||
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() {
|
||||
try (Cursor cursor = getTrackCursor(null, null, TracksColumns.STARTTIME + " DESC")) {
|
||||
// Using the same order as shown in the track list
|
||||
@@ -232,13 +251,25 @@ public class ContentProviderUtils {
|
||||
|
||||
/**
|
||||
* @param trackId the track id.
|
||||
* @return the track doesn't have any trackPoints attached
|
||||
*/
|
||||
public Track getTrack(long trackId) {
|
||||
if (trackId < 0) {
|
||||
public Track getTrack(Track.Id trackId) {
|
||||
if (trackId == null || !trackId.isValid()) {
|
||||
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()) {
|
||||
return createTrack(cursor);
|
||||
}
|
||||
@@ -276,7 +307,7 @@ public class ContentProviderUtils {
|
||||
* @param track the 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) {
|
||||
@@ -284,9 +315,10 @@ public class ContentProviderUtils {
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
|
||||
// Value < 0 indicates no id is available
|
||||
if (track.getId() >= 0) {
|
||||
values.put(TracksColumns._ID, track.getId());
|
||||
if (track.getId() != null && track.getId().isValid()) {
|
||||
values.put(TracksColumns._ID, track.getId().getId());
|
||||
}
|
||||
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid()));
|
||||
values.put(TracksColumns.NAME, track.getName());
|
||||
values.put(TracksColumns.DESCRIPTION, track.getDescription());
|
||||
values.put(TracksColumns.CATEGORY, track.getCategory());
|
||||
@@ -350,7 +382,7 @@ public class ContentProviderUtils {
|
||||
Waypoint waypoint = new Waypoint(location);
|
||||
|
||||
if (!cursor.isNull(idIndex)) {
|
||||
waypoint.setId(cursor.getLong(idIndex));
|
||||
waypoint.setId(new Waypoint.Id(cursor.getLong(idIndex)));
|
||||
}
|
||||
if (!cursor.isNull(nameIndex)) {
|
||||
waypoint.setName(cursor.getString(nameIndex));
|
||||
@@ -365,7 +397,7 @@ public class ContentProviderUtils {
|
||||
waypoint.setIcon(cursor.getString(iconIndex));
|
||||
}
|
||||
if (!cursor.isNull(trackIdIndex)) {
|
||||
waypoint.setTrackId(cursor.getLong(trackIdIndex));
|
||||
waypoint.setTrackId(new Track.Id(cursor.getLong(trackIdIndex)));
|
||||
}
|
||||
if (!cursor.isNull(lengthIndex)) {
|
||||
waypoint.setLength(cursor.getFloat(lengthIndex));
|
||||
@@ -380,10 +412,10 @@ public class ContentProviderUtils {
|
||||
return waypoint;
|
||||
}
|
||||
|
||||
public void deleteWaypoint(Context context, long waypointId) {
|
||||
public void deleteWaypoint(Context context, Waypoint.Id waypointId) {
|
||||
final Waypoint waypoint = getWaypoint(waypointId);
|
||||
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
|
||||
* @return -1 if not able to get the next waypoint number.
|
||||
*/
|
||||
public int getNextWaypointNumber(long trackId) {
|
||||
if (trackId < 0) {
|
||||
public int getNextWaypointNumber(Track.Id trackId) {
|
||||
if (!trackId.isValid()) {
|
||||
return -1;
|
||||
}
|
||||
String[] projection = {WaypointsColumns._ID};
|
||||
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)) {
|
||||
if (cursor != null) {
|
||||
return cursor.getCount();
|
||||
@@ -407,12 +439,12 @@ public class ContentProviderUtils {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Waypoint getWaypoint(long waypointId) {
|
||||
if (waypointId < 0) {
|
||||
public Waypoint getWaypoint(Waypoint.Id waypointId) {
|
||||
if (!waypointId.isValid()) {
|
||||
return null;
|
||||
}
|
||||
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()) {
|
||||
return createWaypoint(cursor);
|
||||
}
|
||||
@@ -438,30 +470,30 @@ public class ContentProviderUtils {
|
||||
* The caller owns the returned cursor and is responsible for closing it.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public Cursor getWaypointCursor(long trackId, long minWaypointId, int maxWaypoints) {
|
||||
if (trackId < 0) {
|
||||
public Cursor getWaypointCursor(Track.Id trackId, @Nullable Waypoint.Id minWaypointId, int maxWaypoints) {
|
||||
if (!trackId.isValid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String selection;
|
||||
String[] selectionArgs;
|
||||
if (minWaypointId >= 0) {
|
||||
if (minWaypointId != null && minWaypointId.isValid()) {
|
||||
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 {
|
||||
selection = WaypointsColumns.TRACKID + "=?";
|
||||
selectionArgs = new String[]{Long.toString(trackId)};
|
||||
selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||
}
|
||||
return getWaypointCursor(null, selection, selectionArgs, WaypointsColumns._ID, maxWaypoints);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public List<Waypoint> getWaypoints(long trackId) {
|
||||
public List<Waypoint> getWaypoints(Track.Id trackId) {
|
||||
ArrayList<Waypoint> waypoints = new ArrayList<>();
|
||||
try (Cursor cursor = getWaypointCursor(trackId, -1L, -1)) {
|
||||
try (Cursor cursor = getWaypointCursor(trackId, null, -1)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
waypoints.add(createWaypoint(cursor));
|
||||
@@ -471,19 +503,34 @@ public class ContentProviderUtils {
|
||||
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.
|
||||
*
|
||||
* @param trackId the track id
|
||||
*/
|
||||
public int getWaypointCount(long trackId) {
|
||||
if (trackId < 0) {
|
||||
public int getWaypointCount(Track.Id trackId) {
|
||||
if (!trackId.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String[] projection = new String[]{"count(*) AS count"};
|
||||
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)) {
|
||||
if (cursor == null) {
|
||||
return 0;
|
||||
@@ -499,8 +546,8 @@ public class ContentProviderUtils {
|
||||
* @param waypoint the waypoint
|
||||
* @return the content provider URI of the inserted waypoint.
|
||||
*/
|
||||
public Uri insertWaypoint(Waypoint waypoint) {
|
||||
waypoint.setId(-1L);
|
||||
public Uri insertWaypoint(@NonNull Waypoint waypoint) {
|
||||
waypoint.setId(null);
|
||||
return contentResolver.insert(WaypointsColumns.CONTENT_URI, createContentValues(waypoint));
|
||||
}
|
||||
|
||||
@@ -535,22 +582,23 @@ public class ContentProviderUtils {
|
||||
if (!updatedWaypoint.hasPhoto()) {
|
||||
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;
|
||||
}
|
||||
|
||||
ContentValues createContentValues(Waypoint waypoint) {
|
||||
ContentValues createContentValues(@NonNull Waypoint waypoint) {
|
||||
ContentValues values = new ContentValues();
|
||||
|
||||
// Value < 0 indicates no id is available
|
||||
if (waypoint.getId() >= 0) {
|
||||
values.put(WaypointsColumns._ID, waypoint.getId());
|
||||
if (waypoint.getId() != null && waypoint.getId().isValid()) {
|
||||
values.put(WaypointsColumns._ID, waypoint.getId().getId());
|
||||
}
|
||||
values.put(WaypointsColumns.NAME, waypoint.getName());
|
||||
values.put(WaypointsColumns.DESCRIPTION, waypoint.getDescription());
|
||||
values.put(WaypointsColumns.CATEGORY, waypoint.getCategory());
|
||||
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.DURATION, waypoint.getDuration());
|
||||
|
||||
@@ -643,7 +691,7 @@ public class ContentProviderUtils {
|
||||
* @return the number of trackPoints inserted
|
||||
*/
|
||||
//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];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = createContentValues(trackPoints[i], trackId);
|
||||
@@ -653,23 +701,23 @@ public class ContentProviderUtils {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Deprecated
|
||||
public long getFirstTrackPointId(long trackId) {
|
||||
if (trackId < 0) {
|
||||
return -1L;
|
||||
public Track.Id getFirstTrackPointId(Track.Id trackId) {
|
||||
if (!trackId.isValid()) {
|
||||
return null;
|
||||
}
|
||||
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)) {
|
||||
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
|
||||
*/
|
||||
@Deprecated
|
||||
public long getLastTrackPointId(long trackId) {
|
||||
if (trackId < 0) {
|
||||
public long getLastTrackPointId(Track.Id trackId) {
|
||||
if (trackId == null || !trackId.isValid()) {
|
||||
Log.w(TAG, "Fix callers who do this.");
|
||||
return -1L;
|
||||
}
|
||||
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)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID));
|
||||
@@ -700,12 +749,12 @@ public class ContentProviderUtils {
|
||||
* @param location the location
|
||||
* @return trackPoint id if the location is in the track. -1L otherwise.
|
||||
*/
|
||||
public long getTrackPointId(long trackId, Location location) {
|
||||
if (trackId < 0) {
|
||||
public long getTrackPointId(Track.Id trackId, Location location) {
|
||||
if (!trackId.isValid()) {
|
||||
return -1L;
|
||||
}
|
||||
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)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
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 descending true to sort the result in descending order (latest location first)
|
||||
*/
|
||||
public Cursor getTrackPointCursor(long trackId, long startTrackPointId, int maxLocations, boolean descending) {
|
||||
if (trackId < 0) {
|
||||
public Cursor getTrackPointCursor(Track.Id trackId, long startTrackPointId, int maxLocations, boolean descending) {
|
||||
if (!trackId.isValid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -741,10 +790,10 @@ public class ContentProviderUtils {
|
||||
if (startTrackPointId >= 0) {
|
||||
String comparison = descending ? "<=" : ">=";
|
||||
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 {
|
||||
selection = TrackPointsColumns.TRACKID + "=?";
|
||||
selectionArgs = new String[]{Long.toString(trackId)};
|
||||
selectionArgs = new String[]{Long.toString(trackId.getId())};
|
||||
}
|
||||
|
||||
String sortOrder = TrackPointsColumns._ID;
|
||||
@@ -764,12 +813,12 @@ public class ContentProviderUtils {
|
||||
* @param trackId the track id
|
||||
*/
|
||||
@Deprecated
|
||||
public TrackPoint getLastValidTrackPoint(long trackId) {
|
||||
if (trackId < 0) {
|
||||
public TrackPoint getLastValidTrackPoint(Track.Id trackId) {
|
||||
if (!trackId.isValid()) {
|
||||
return null;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -780,7 +829,7 @@ public class ContentProviderUtils {
|
||||
* @param trackId the track id
|
||||
* @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));
|
||||
}
|
||||
|
||||
@@ -790,9 +839,9 @@ public class ContentProviderUtils {
|
||||
* @param trackPoint the trackPoint
|
||||
* @param trackId the track id
|
||||
*/
|
||||
private ContentValues createContentValues(TrackPoint trackPoint, long trackId) {
|
||||
private ContentValues createContentValues(TrackPoint trackPoint, Track.Id trackId) {
|
||||
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.LATITUDE, (int) (trackPoint.getLatitude() * 1E6));
|
||||
|
||||
@@ -833,7 +882,7 @@ public class ContentProviderUtils {
|
||||
* @param startTrackPointId the starting trackPoint id. -1L to ignore
|
||||
* @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);
|
||||
}
|
||||
|
||||
@@ -859,7 +908,7 @@ public class ContentProviderUtils {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public List<TrackPoint> getTrackPoints(long trackId) {
|
||||
public List<TrackPoint> getTrackPoints(Track.Id trackId) {
|
||||
List<TrackPoint> trackPoints = null;
|
||||
|
||||
try (Cursor trackPointCursor = getTrackPointCursor(trackId, -1L, -1, false)) {
|
||||
@@ -890,13 +939,23 @@ public class ContentProviderUtils {
|
||||
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
|
||||
*
|
||||
* @param ids array with IDs
|
||||
* @return comma separated list of ids
|
||||
*/
|
||||
public static String formatIdListForUri(long[] ids) {
|
||||
private static String formatIdListForUri(long[] ids) {
|
||||
StringBuilder idsPathSegment = new StringBuilder();
|
||||
for (long id : ids) {
|
||||
if (idsPathSegment.length() > 0) {
|
||||
@@ -910,5 +969,4 @@ public class ContentProviderUtils {
|
||||
public static String[] parseTrackIdsFromUri(Uri url) {
|
||||
return TextUtils.split(url.getLastPathSegment(), ID_SEPARATOR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
*/
|
||||
public abstract class CustomContentProvider extends ContentProvider {
|
||||
public class CustomContentProvider extends ContentProvider {
|
||||
|
||||
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_BY_ID.ordinal());
|
||||
uriMatcher.addURI(ContentProviderUtils.AUTHORITY_PACKAGE, WaypointsColumns.CONTENT_URI_BY_TRACKID.getPath() + "/*", UrlType.WAYPOINTS_BY_TRACKID.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,6 +141,7 @@ public abstract class CustomContentProvider extends ContentProvider {
|
||||
case WAYPOINTS:
|
||||
return WaypointsColumns.CONTENT_TYPE;
|
||||
case WAYPOINTS_BY_ID:
|
||||
case WAYPOINTS_BY_TRACKID:
|
||||
return WaypointsColumns.CONTENT_ITEMTYPE;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown URL " + url);
|
||||
@@ -219,6 +221,10 @@ public abstract class CustomContentProvider extends ContentProvider {
|
||||
queryBuilder.setTables(WaypointsColumns.TABLE_NAME);
|
||||
queryBuilder.appendWhere(WaypointsColumns._ID + "=" + ContentUris.parseId(url));
|
||||
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:
|
||||
throw new IllegalArgumentException("Unknown url " + url);
|
||||
}
|
||||
@@ -382,6 +388,7 @@ public abstract class CustomContentProvider extends ContentProvider {
|
||||
TRACKS,
|
||||
TRACKS_BY_ID,
|
||||
WAYPOINTS,
|
||||
WAYPOINTS_BY_ID
|
||||
WAYPOINTS_BY_ID,
|
||||
WAYPOINTS_BY_TRACKID
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,34 @@
|
||||
package de.dennisguse.opentracks.content.provider;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
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.TracksColumns;
|
||||
import de.dennisguse.opentracks.content.data.WaypointsColumns;
|
||||
import de.dennisguse.opentracks.util.UUIDUtils;
|
||||
|
||||
/**
|
||||
* Database helper for creating and upgrading the database.
|
||||
*/
|
||||
@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();
|
||||
|
||||
@VisibleForTesting
|
||||
private static final String DATABASE_NAME = "database.db";
|
||||
private static final int DATABASE_VERSION = 26;
|
||||
|
||||
@VisibleForTesting
|
||||
public static final String DATABASE_NAME = "database.db";
|
||||
|
||||
public CustomSQLiteOpenHelper(Context context) {
|
||||
this(context, DATABASE_NAME);
|
||||
@@ -45,6 +50,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL(TrackPointsColumns.CREATE_TABLE_INDEX);
|
||||
|
||||
db.execSQL(TracksColumns.CREATE_TABLE);
|
||||
db.execSQL(TracksColumns.CREATE_TABLE_INDEX);
|
||||
|
||||
db.execSQL(WaypointsColumns.CREATE_TABLE);
|
||||
db.execSQL(WaypointsColumns.CREATE_TABLE_INDEX);
|
||||
@@ -61,6 +67,9 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
case 25:
|
||||
upgradeFrom24to25(db);
|
||||
break;
|
||||
case 26:
|
||||
upgradeFrom25to26(db);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Not implemented: upgrade to " + toVersion);
|
||||
@@ -79,6 +88,9 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
case 24:
|
||||
downgradeFrom25to24(db);
|
||||
break;
|
||||
case 25:
|
||||
downgradeFrom26to25(db);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Not implemented: downgrade to " + toVersion);
|
||||
@@ -107,7 +119,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
|
||||
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.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)");
|
||||
@@ -142,4 +154,40 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
db.setTransactionSuccessful();
|
||||
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.MatrixCursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.util.Log;
|
||||
@@ -18,8 +17,11 @@ import androidx.annotation.Nullable;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import de.dennisguse.opentracks.android.IContentResolver;
|
||||
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.
|
||||
* 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}.
|
||||
*
|
||||
* <p>
|
||||
* 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}.
|
||||
* 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);
|
||||
}
|
||||
|
||||
public static Pair<Uri, String> createURI(long[] trackIds, String trackName, @NonNull TrackFileFormat trackFileFormat) {
|
||||
if (trackIds.length == 0) {
|
||||
public static Pair<Uri, String> createURI(Track.Id trackId, String trackName, @NonNull TrackFileFormat trackFileFormat) {
|
||||
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();
|
||||
}
|
||||
|
||||
StringBuilder trackIdBuilder = new StringBuilder();
|
||||
for (long trackId : trackIds) {
|
||||
trackIdBuilder.append(trackId).append(TRACKID_DELIMITER);
|
||||
for (Track.Id trackId : trackIds) {
|
||||
trackIdBuilder.append(trackId.getId()).append(TRACKID_DELIMITER);
|
||||
}
|
||||
trackIdBuilder.deleteCharAt(trackIdBuilder.lastIndexOf(TRACKID_DELIMITER));
|
||||
|
||||
@@ -90,18 +98,18 @@ public class ShareContentProvider extends CustomContentProvider implements ICont
|
||||
return new Pair<>(uri, mime);
|
||||
}
|
||||
|
||||
static long[] parseURI(Uri uri) {
|
||||
static Set<Track.Id> parseURI(Uri uri) {
|
||||
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.");
|
||||
return new long[]{};
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
String[] uriTrackIds = uriPaths.get(2).split(TRACKID_DELIMITER);
|
||||
|
||||
long[] trackIds = new long[uriTrackIds.length];
|
||||
for (int i = 0; i < trackIds.length; i++) {
|
||||
trackIds[i] = Long.parseLong(uriTrackIds[i]);
|
||||
Set<Track.Id> trackIds = new HashSet<>();
|
||||
for (String uriTrackId : uriTrackIds) {
|
||||
trackIds.add(new Track.Id(Long.parseLong(uriTrackId)));
|
||||
}
|
||||
return trackIds;
|
||||
}
|
||||
@@ -203,22 +211,19 @@ public class ShareContentProvider extends CustomContentProvider implements ICont
|
||||
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
|
||||
|
||||
long[] trackIds = parseURI(uri);
|
||||
final Track[] tracks = new Track[trackIds.length];
|
||||
for (int i = 0; i < trackIds.length; i++) {
|
||||
tracks[i] = contentProviderUtils.getTrack(trackIds[i]);
|
||||
Set<Track.Id> trackIds = parseURI(uri);
|
||||
final ArrayList<Track> tracks = new ArrayList<>();
|
||||
for (Track.Id trackId : trackIds) {
|
||||
tracks.add(contentProviderUtils.getTrack(trackId));
|
||||
}
|
||||
|
||||
final TrackExporter trackExporter = getTrackFileFormat(uri).newTrackExporter(getContext(), tracks);
|
||||
final TrackExporter trackExporter = getTrackFileFormat(uri).newTrackExporter(getContext());
|
||||
|
||||
PipeDataWriter pipeDataWriter = new PipeDataWriter<String>() {
|
||||
@Override
|
||||
public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri, @NonNull String mimeType, @Nullable Bundle opts, @Nullable String args) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(output.getFileDescriptor())) {
|
||||
trackExporter.writeTrack(getContext(), fileOutputStream);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "there occurred an error while sharing a file: " + e);
|
||||
}
|
||||
PipeDataWriter<String> pipeDataWriter = (output, uri1, mimeType, opts, args) -> {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(output.getFileDescriptor())) {
|
||||
trackExporter.writeTrack(tracks.toArray(new Track[0]), fileOutputStream);
|
||||
} 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.NoSuchElementException;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
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 final ContentProviderUtils contentProviderUtils;
|
||||
private final long trackId;
|
||||
private final Track.Id trackId;
|
||||
private final boolean descending;
|
||||
private final CachedTrackPointsIndexes indexes;
|
||||
private long lastTrackPointId = -1L;
|
||||
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.trackId = trackId;
|
||||
this.descending = descending;
|
||||
@@ -100,13 +101,4 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
if (cursor == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return cursor.getCount();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,10 +6,10 @@ import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager;
|
||||
|
||||
public class SensorData {
|
||||
|
||||
private String sensorAddress;
|
||||
private String sensorName;
|
||||
private final String sensorAddress;
|
||||
private final String sensorName;
|
||||
|
||||
private long timestamp_ms;
|
||||
private final long timestamp_ms;
|
||||
|
||||
SensorData(String sensorAddress, String sensorName) {
|
||||
this(sensorAddress, sensorName, System.currentTimeMillis());
|
||||
|
||||
@@ -25,8 +25,8 @@ public final class SensorDataCycling {
|
||||
|
||||
public static class Cadence extends SensorData {
|
||||
|
||||
private long crankRevolutionsCount; // UINT32
|
||||
private int crankRevolutionsTime; // UINT16; 1/1024s
|
||||
private final long crankRevolutionsCount; // UINT32
|
||||
private final int crankRevolutionsTime; // UINT16; 1/1024s
|
||||
private float cadence_rpm = INVALID_VALUE_FLOAT;
|
||||
|
||||
public Cadence(String sensorAddress, String sensorName, long crankRevolutionsCount, int crankRevolutionsTime) {
|
||||
@@ -93,8 +93,8 @@ public final class SensorDataCycling {
|
||||
|
||||
public static class Speed extends SensorData {
|
||||
|
||||
private int wheelRevolutionsCount; // UINT16
|
||||
private int wheelRevolutionsTime; // UINT16; 1/1024s
|
||||
private final int wheelRevolutionsCount; // UINT16
|
||||
private final int wheelRevolutionsTime; // UINT16; 1/1024s
|
||||
private float speed_mps = INVALID_VALUE_FLOAT;
|
||||
|
||||
public Speed(String sensorAddress, String sensorName, int wheelRevolutionsCount, int wheelRevolutionsTime) {
|
||||
@@ -154,8 +154,8 @@ public final class SensorDataCycling {
|
||||
|
||||
public static class CadenceAndSpeed extends SensorData {
|
||||
|
||||
private Cadence cadence;
|
||||
private Speed speed;
|
||||
private final Cadence cadence;
|
||||
private final Speed speed;
|
||||
|
||||
public CadenceAndSpeed(String sensorAddress, String sensorName, @NonNull Cadence cadence, @NonNull Speed speed) {
|
||||
super(sensorAddress, sensorName);
|
||||
|
||||
@@ -4,7 +4,7 @@ import androidx.annotation.NonNull;
|
||||
|
||||
public class SensorDataHeartRate extends SensorData {
|
||||
|
||||
private float heartRate_bpm;
|
||||
private final float heartRate_bpm;
|
||||
|
||||
public SensorDataHeartRate(String name, String address, float heartRate_bpm) {
|
||||
super(name, address);
|
||||
|
||||