Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ Lib: Use two decimal precision for average speed
Android: Fix sensor scanning state handling for internal and Ble sensors.
Android: Fix handling of unpaired power meters
GTK: Add support for Nominatim reverse
GTK: Add support for brouter API
43 changes: 43 additions & 0 deletions aat-gtk/src/main/kotlin/ch/bailu/aat_gtk/api/BrouterController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package ch.bailu.aat_gtk.api

import ch.bailu.aat_gtk.controller.UiControllerInterface
import ch.bailu.aat_lib.api.brouter.BrouterApi
import ch.bailu.aat_lib.app.AppContext
import ch.bailu.aat_lib.gpx.GpxList
import ch.bailu.aat_lib.gpx.information.GpxInformationProvider
import ch.bailu.aat_lib.gpx.information.InfoID
import ch.bailu.aat_lib.logger.AppLog
import ch.bailu.aat_lib.preferences.map.overlay.SolidBrouterOverlay
import ch.bailu.gtk.gtk.Application
import ch.bailu.gtk.lib.handler.action.ActionHandler

class BrouterController(app: Application, private val appContext: AppContext, private val gpxInformation: GpxInformationProvider, private val uiController: UiControllerInterface) {
val api = BrouterApi(SolidBrouterOverlay(appContext.dataDirectory))

init {
setAction(app, "brouter", { this.onAction() })
}

private fun onAction() {
val list = gpxInformation.getInfo().getGpxList()
if (validateList(list) && !api.isTaskRunning(appContext.services)) {
uiController.setOverlayEnabled(InfoID.BROUTER, true)
api.startTask(appContext, list)
}
}

private fun setAction(app: Application, action: String, onActivate: ()->Unit) {
ActionHandler.get(app, action).apply {
disconnectSignals()
onActivate(onActivate)
}
}

private fun validateList(list: GpxList): Boolean {
if (list.pointList.size() > 1 && list.pointList.size() <= 20) {
return true
}
AppLog.e(this, "Position count not supported: ${list.pointList.size()}. Must be between 2 and 20")
return false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ch.bailu.aat_gtk.api

import ch.bailu.aat_gtk.config.Strings
import ch.bailu.aat_gtk.controller.UiControllerInterface
import ch.bailu.aat_gtk.view.menu.MenuHelper
import ch.bailu.aat_lib.api.nominatim.NominatimReverseApi
import ch.bailu.aat_lib.app.AppContext
import ch.bailu.aat_lib.dispatcher.DispatcherInterface
import ch.bailu.aat_lib.dispatcher.TargetInterface
import ch.bailu.aat_lib.gpx.GpxPointNode
import ch.bailu.aat_lib.gpx.attributes.GpxAttributes
import ch.bailu.aat_lib.gpx.attributes.Keys
import ch.bailu.aat_lib.gpx.information.GpxInformation
import ch.bailu.aat_lib.gpx.information.InfoID
import ch.bailu.aat_lib.logger.AppLog
import ch.bailu.aat_lib.preferences.map.overlay.SolidNominatimReverseOverlay
import ch.bailu.gtk.gtk.Application
import org.mapsforge.map.view.MapView

class NominatimReverseController(app: Application,
private val appContext: AppContext,
private val mapView: MapView,
private val uiController: UiControllerInterface): TargetInterface {

private val soverlay = SolidNominatimReverseOverlay(appContext.dataDirectory)
private val reverseApi = NominatimReverseApi(soverlay)
private var isUpdated = false


init {
MenuHelper.setAction(app, Strings.ACTION_LOCATION_REVERSE) { onQueryAction() }
MenuHelper.setAction(app, Strings.ACTION_LOCATION_REVERSE_CENTER) {
uiController.centerInMap(soverlay.getIID())
}
}


private fun onQueryAction() {
if (!reverseApi.isTaskRunning(appContext.services)) {
reverseApi.startTask(
appContext,
uiController.getMapBounding().center,
mapView.model.mapViewPosition.zoomLevel.toInt()
)
soverlay.setEnabled(true)
isUpdated = true
}
}
private fun getMessage(attributes: GpxAttributes): String {
return attributes[Keys.toIndex("name")].ifEmpty {
attributes[Keys.toIndex("city")].ifEmpty {
attributes[Keys.toIndex("label")]
}
}
}

override fun onContentUpdated(iid: Int, info: GpxInformation) {
if (isUpdated) {
val firstNode = info.getGpxList().pointList.first
if (firstNode is GpxPointNode) {
AppLog.i(this, getMessage(firstNode.getAttributes()))
}
isUpdated = false
}
}

fun addToDispatcher(dispatcher: DispatcherInterface) {
dispatcher.addTarget(this, InfoID.NOMINATIM_REVERSE)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ch.bailu.aat_gtk.view.menu.provider

import ch.bailu.aat_lib.api.brouter.BrouterApi
import ch.bailu.aat_lib.dispatcher.EditorSourceInterface
import ch.bailu.aat_lib.gpx.interfaces.GpxType
import ch.bailu.aat_lib.resources.Res
Expand All @@ -13,6 +14,7 @@ class EditorMenu(private val edit: EditorSourceInterface): MenuProviderInterface
append(Res.str().edit_save(), "app.editSave")
append(Res.str().edit_save_copy(), "app.editCopy")
append(Res.str().edit_save_copy_to(), "app.editCopyTo")
append(BrouterApi.NAME, "app.brouter")
append(Res.str().edit_inverse(), "app.editInverse")
appendSubmenu(Res.str().edit_change_type(), Menu().apply {
append("Track", "app.editTypeTrack")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
package ch.bailu.aat_gtk.view.menu.provider

import ch.bailu.aat_gtk.api.NominatimReverseController
import ch.bailu.aat_gtk.app.GtkAppContext
import ch.bailu.aat_gtk.config.Strings
import ch.bailu.aat_gtk.controller.ClipboardController
import ch.bailu.aat_gtk.controller.UiControllerInterface
import ch.bailu.aat_gtk.view.map.GtkCustomMapView
import ch.bailu.aat_gtk.view.menu.MenuHelper
import ch.bailu.aat_lib.api.cm.CmApi
import ch.bailu.aat_lib.api.nominatim.NominatimReverseApi
import ch.bailu.aat_lib.app.AppContext
import ch.bailu.aat_lib.dispatcher.DispatcherInterface
import ch.bailu.aat_lib.gpx.GpxPointNode
import ch.bailu.aat_lib.gpx.attributes.GpxAttributes
import ch.bailu.aat_lib.gpx.attributes.Keys
import ch.bailu.aat_lib.gpx.information.GpxInformation
import ch.bailu.aat_lib.gpx.information.InfoID
import ch.bailu.aat_lib.logger.AppLog
import ch.bailu.aat_lib.preferences.StorageInterface
import ch.bailu.aat_lib.preferences.map.SolidMapGrid
import ch.bailu.aat_lib.preferences.map.overlay.SolidNominatimReverseOverlay
import ch.bailu.aat_lib.preferences.system.SolidDataDirectory
import ch.bailu.aat_lib.resources.Res
import ch.bailu.aat_lib.resources.ToDo
Expand All @@ -27,7 +21,6 @@ import ch.bailu.gtk.gio.Menu
import ch.bailu.gtk.gtk.Application
import ch.bailu.gtk.type.Str
import org.mapsforge.map.view.MapView
import kotlin.text.ifEmpty

class LocationMenu : MenuProviderInterface {
override fun createMenu(): Menu {
Expand Down Expand Up @@ -83,7 +76,9 @@ class LocationMenu : MenuProviderInterface {
) {

createActionsClipboard(app, appContext.storage, display, uiController)
createActionsNominatimReverse(app, appContext, mapView, uiController, dispatcher)
NominatimReverseController(app, appContext, mapView, uiController).addToDispatcher(
dispatcher
)
createActionsCm(app, appContext.dataDirectory)

}
Expand Down Expand Up @@ -121,52 +116,5 @@ class LocationMenu : MenuProviderInterface {
}

}

private fun createActionsNominatimReverse(
app: Application,
appContext: AppContext,
mapView: MapView,
uiController: UiControllerInterface,
dispatcher: DispatcherInterface
) {
val soverlay = SolidNominatimReverseOverlay(appContext.dataDirectory)
val reverseApi = NominatimReverseApi(soverlay)
var isUpdated = false

MenuHelper.setAction(app, Strings.ACTION_LOCATION_REVERSE) {
if (!reverseApi.isTaskRunning(GtkAppContext.services)) {
reverseApi.startTask(
GtkAppContext,
uiController.getMapBounding().center,
mapView.model.mapViewPosition.zoomLevel.toInt()
)
soverlay.setEnabled(true)
isUpdated = true
}
}

MenuHelper.setAction(app, Strings.ACTION_LOCATION_REVERSE_CENTER) {
uiController.centerInMap(soverlay.getIID())
}


dispatcher.addTarget({ iid: Int, info: GpxInformation ->
if (isUpdated) {
val firstNode = info.getGpxList().pointList.first
if (firstNode is GpxPointNode) {
AppLog.i(this, getMessage(firstNode.getAttributes()))
}
isUpdated = false
}
}, InfoID.NOMINATIM_REVERSE)
}

private fun getMessage(attributes: GpxAttributes): String {
return attributes[Keys.toIndex("name")].ifEmpty {
attributes[Keys.toIndex("city")].ifEmpty {
attributes[Keys.toIndex("label")]
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ch.bailu.aat_gtk.view.toplevel

import ch.bailu.aat_gtk.api.BrouterController
import ch.bailu.aat_gtk.app.GtkAppConfig
import ch.bailu.aat_gtk.app.GtkAppContext
import ch.bailu.aat_gtk.app.exit
Expand Down Expand Up @@ -115,6 +116,8 @@ class MainWindow(private val app: Application, private val appContext: AppContex
window.onDestroy {
exit(dispatcher, 0)
}

BrouterController(app, appContext, editorSource, this)
}

private fun clearEditor(onCleared: ()->Unit) {
Expand Down Expand Up @@ -252,6 +255,7 @@ class MainWindow(private val app: Application, private val appContext: AppContex
dispatcher.addOverlaySources(appContext, usageTrackers)
dispatcher.addSource(FixedOverlaySource.createDraftSource(appContext, usageTrackers))
dispatcher.addSource(FixedOverlaySource.createPoiSource(appContext, usageTrackers))
dispatcher.addSource(FixedOverlaySource.createBrouterSource(appContext, usageTrackers))
dispatcher.addSource(FixedOverlaySource.createCmSource(appContext, usageTrackers))
dispatcher.addSource(FixedOverlaySource.createNominatimReverseSource(appContext, usageTrackers))
dispatcher.addSource(editorSource)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ class BrouterApi(overlay: SolidOverlayInterface) : Api(overlay) {
}
return builder.toString()
}

companion object {
const val NAME = "Brouter"
}
}
1 change: 1 addition & 0 deletions aat-lib/src/main/java/ch/bailu/aat_lib/api/cm/CmApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ class CmApi(baseDirectory: SolidDataDirectory) : Api(SolidCriticalMapOverlay(bas
}
companion object {
const val ENABLED = false // TODO handle as experimental feature and enable via env variable
const val NAME = "Critical Map"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ abstract class NominatimApi(context: AppContext) : DownloadApi(SolidNominatimOve
}

companion object {
const val POST = "&format=xml"
const val POST = "&format=xml"
const val NAME = "Nominatim"

private fun toString(b: BoundingBoxE6): String {
return if (b.latitudeSpanE6 > 0 && b.longitudeSpanE6 > 0) {
"&bounded=1&viewbox=" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ class NominatimReverseApi(overlay: SolidOverlayInterface) : Api(overlay) {
}
}

companion object {
const val NAME = "Reverse"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class EditorSource(private val appContext: AppContext, usageTracker: UsageTracke
EditorSourceInterface {

private var target = TargetInterface.NULL
private val edit: EditorHelper = EditorHelper(appContext)
private val edit = EditorHelper(appContext)
private val onFileEdited = BroadcastReceiver { args ->
if (BroadcastData.has(args, edit.vID)) {
requestUpdate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ch.bailu.aat_lib.dispatcher.source
import ch.bailu.aat_lib.app.AppContext
import ch.bailu.aat_lib.dispatcher.usage.UsageTrackerInterface
import ch.bailu.aat_lib.preferences.StorageInterface
import ch.bailu.aat_lib.preferences.map.overlay.SolidBrouterOverlay
import ch.bailu.aat_lib.preferences.map.overlay.SolidCriticalMapOverlay
import ch.bailu.aat_lib.preferences.map.overlay.SolidDraftOverlay
import ch.bailu.aat_lib.preferences.map.overlay.SolidFixedOverlay
Expand Down Expand Up @@ -51,6 +52,11 @@ class FixedOverlaySource(context: AppContext, usageTracker: UsageTrackerInterfac
return FixedOverlaySource(context, usageTracker, overlay)
}

fun createBrouterSource(context: AppContext, usageTracker: UsageTrackerInterface): FileSource {
val overlay = SolidBrouterOverlay(context.dataDirectory)
return FixedOverlaySource(context, usageTracker, overlay)
}

fun createCmSource(context: AppContext, usageTracker: UsageTrackerInterface): FileSource {
val overlay = SolidCriticalMapOverlay(context.dataDirectory)
return FixedOverlaySource(context, usageTracker, overlay)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package ch.bailu.aat_lib.gpx.information

import ch.bailu.aat_lib.api.brouter.BrouterApi
import ch.bailu.aat_lib.api.cm.CmApi
import ch.bailu.aat_lib.api.nominatim.NominatimApi
import ch.bailu.aat_lib.api.nominatim.NominatimReverseApi
import ch.bailu.aat_lib.preferences.map.overlay.SolidCustomOverlayList
import ch.bailu.aat_lib.resources.Res
import ch.bailu.aat_lib.resources.ToDo
Expand All @@ -12,14 +15,14 @@ object InformationUtil {
InfoID.POI -> return Res.str().p_mapsforge_poi()
InfoID.EDITOR_DRAFT -> return ToDo.translate("Draft")
InfoID.TRACKER -> return Res.str().tracker()
InfoID.NOMINATIM -> return "Nominatim"
InfoID.NOMINATIM -> return NominatimApi.NAME
InfoID.OVERPASS -> return Res.str().query_overpass()
InfoID.EDITOR_OVERLAY -> return ToDo.translate("Editor")
InfoID.FILE_VIEW -> return ToDo.translate("Selected File")
InfoID.LIST_SUMMARY -> return ToDo.translate("List Summary")
InfoID.CRITICAL_MAP -> return "Critical Map"
InfoID.NOMINATIM_REVERSE -> return "Reverse"
InfoID.BROUTER -> return "Brouter"
InfoID.CRITICAL_MAP -> return CmApi.NAME
InfoID.NOMINATIM_REVERSE -> return NominatimReverseApi.NAME
InfoID.BROUTER -> return BrouterApi.NAME
}
if (isOverlay(iid)) {
return "${ToDo.translate("Overlay")} ${getOverlayIndex(iid)}"
Expand All @@ -46,6 +49,7 @@ object InformationUtil {
add(InfoID.TRACKER)
add(InfoID.LIST_SUMMARY)
add(InfoID.NOMINATIM_REVERSE)
add(InfoID.BROUTER)
if (CmApi.ENABLED) {
add(InfoID.CRITICAL_MAP)
}
Expand Down