Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: QT Positioning #285

Merged
merged 2 commits into from
Jun 19, 2024
Merged
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
78 changes: 52 additions & 26 deletions yin_yang/position.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,48 @@
import logging
from time import sleep

import requests
from PySide6.QtCore import QObject
from PySide6.QtPositioning import QGeoPositionInfoSource, QGeoCoordinate, QGeoPositionInfo
from PySide6.QtCore import QObject, Slot
from PySide6.QtPositioning import (
QGeoPositionInfoSource,
QGeoCoordinate,
QGeoPositionInfo,
)

logger = logging.getLogger(__name__)


class QTPositionReceiver(QObject):
"""Small handler for QT positioning service."""

def __init__(self):
super().__init__()

# Create the position service and hook it to us
self._positionSource = QGeoPositionInfoSource.createSource(
"geoclue2", {"desktopId": "Yin-Yang"}, self
)
self._positionSource.positionUpdated.connect(self.handlePosition)

# Start the position service.
# This will only work after the app calls `exec()`.
self._positionSource.startUpdates()

# Get the initial last position.
self._lastPosition = self._positionSource.lastKnownPosition()

@Slot(QGeoPositionInfo)
def handlePosition(self, position: QGeoPositionInfo):
"""Track the position provided by the service."""
self._lastPosition = position

def lastKnownPosition(self):
"""Return the last known position, if valid."""
return self._lastPosition


position_handler = QTPositionReceiver()


def get_current_location() -> QGeoCoordinate:
try:
return get_qt_position()
Expand All @@ -19,53 +54,44 @@ def get_current_location() -> QGeoCoordinate:
except TypeError as e:
logger.warning(e)

raise TypeError('Unable to get current location')


parent = QObject()
location_source = QGeoPositionInfoSource.createDefaultSource(parent)
raise TypeError("Unable to get current location")


def get_qt_position() -> QGeoCoordinate:
if location_source is None:
raise TypeError('Location source is none')

pos: QGeoPositionInfo = location_source.lastKnownPosition()
if pos is None:
location_source.requestUpdate(10)
tries = 0
while pos is None and tries < 10:
pos = location_source.lastKnownPosition()
tries += 1
sleep(1)
"""Get the position via QT service"""
# Fetch the last known position
global position_handler
pos: QGeoPositionInfo = position_handler.lastKnownPosition()

coordinate = pos.coordinate()

if not coordinate.isValid():
raise TypeError('Coordinates are not valid')
raise TypeError("Coordinates are not valid")

return coordinate


# there is a freedesktop portal for getting the location,
# but it's not implemented by KDE, so I have no use for it


def get_ipinfo_position() -> QGeoCoordinate:
# use the old method as a fallback
try:
response = requests.get('https://www.ipinfo.io/loc')
response = requests.get("https://www.ipinfo.io/loc")
except Exception as e:
logger.error(e)
raise TypeError('Error while sending a request to get location')
raise TypeError("Error while sending a request to get location")

if not response.ok:
raise TypeError('Failed to get location from ipinfo.io')
raise TypeError("Failed to get location from ipinfo.io")

loc_response = response.text.removesuffix('\n').split(',')
loc_response = response.text.removesuffix("\n").split(",")
loc: [float] = [float(coordinate) for coordinate in loc_response]
assert len(loc) == 2, 'The returned location should have exactly 2 values.'
assert len(loc) == 2, "The returned location should have exactly 2 values."
coordinate = QGeoCoordinate(loc[0], loc[1])

if not coordinate.isValid():
raise TypeError('Coordinates are not valid')
raise TypeError("Coordinates are not valid")

return coordinate