Skip to main content

QCustomMapView

QCustomMapView

Engine-agnostic map facade.

The facade owns all the STATE (centre, zoom, markers, routes, focus) and a backend renders it. That split is deliberate:

  • the state is plain Python and fully testable headlessly, which is what the project plan said a map could not be - it can, as long as the engine is not tangled into it
  • the engine can be swapped (QtLocation today, MapLibre/WebEngine later) without touching a line of application code

Every mutation is applied to the state first and then pushed to the backend, so a view created before the engine loads still shows the right thing once it attaches, and a headless test needs no engine at all.

See docs/design/qcustommapview-project-plan.md for why this is an optional extra rather than a core widget.

At a glance​

TierFree (GPLv3)
Importfrom Custom_Widgets.QCustomMapView import QCustomMapView
Qt DesignerCode only

Quick start​

from Custom_Widgets.QCustomMapView import QCustomMapView

widget = QCustomMapView()
widget.loadDefaultEngine()
widget.setCenter(-1.286389, 36.817223) # Nairobi
widget.setZoom(13)
_pump(2.5)

That is the exact code behind the screenshot above.

Dark theme​

Colours come from the design tokens, so the widget follows the app theme with no extra work.

QCustomMapView in dark theme

Properties​

Every property below is settable in code and in Qt Designer.

PropertyTypeDefault
latitudefloat—
longitudefloat—
zoomLevelfloat—
tileProviderNamestring—
interactivebool—

Signals​

Signal
centerChanged(double,double)
engineFailed(QString)
markerClicked(QString)
zoomChanged(double)

Methods​

MethodDescription
addMarker(id, latitude, longitude, label='', color='#2563eb', heading=None, icon='')Add a marker.
attachEngine(engine)Attach a backend and replay the current state into it.
center()Center.
centerChanged(...)Center changed.
clearFocus()Clear the focus.
clearMarkers()Clear the markers.
clearRoutes()Clear the routes.
engine()Engine.
engineFailed(...)Engine failed.
fitMarkers(padding=0.15)Centre on the markers and pick a zoom that contains them all.
focusMarker(id, glow=True, recenter=True)Focus marker.
focusedMarker()Focused marker.
hasEngine()Return whether it has engine.
interactive(*args, **kwargs)Interactive.
latitude(*args, **kwargs)Latitude.
loadDefaultEngine()Load the shipped QtLocation backend.
longitude(*args, **kwargs)Longitude.
mapStyle()Map style.
mapStyles()Style names the engine reports, or [] before it has resolved them.
marker(id)Marker.
markerClicked(...)Marker clicked.
markerCount()Marker count.
markers()Markers.
providerOptions()Provider options.
removeMarker(id)Remove a marker.
removeRoute(id)Remove a route.
route(id)Route.
routeCount()Route count.
routes()Routes.
setCenter(latitude, longitude)Set the center.
setMapStyle(index)Pick one of mapStyles() by index.
setRoute(id, points, color='#dc2626', width=4.0)Set the route.
setTileProvider(provider, **options)Choose the tile provider. Options are passed to the engine.
setZoom(zoom)Set the zoom.
showPlaceholder(message)Show why the map is blank, instead of leaving an empty rectangle.
tileProvider()Tile provider.
tileProviderName(*args, **kwargs)Tile provider name.
updateMarker(id, latitude=None, longitude=None, **kwargs)Move or restyle a marker in place. Returns False if unknown.
zoom()Zoom.
zoomChanged(...)Zoom changed.
zoomIn(step=1.0)Zoom in.
zoomLevel(*args, **kwargs)Zoom level.
zoomOut(step=1.0)Zoom out.

Runnable example​

A complete app using this widget lives at examples/PySide6/QCustomMapView/main.py.