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

Show dataset details for point clouds #196

Merged
merged 11 commits into from
May 10, 2023
1 change: 1 addition & 0 deletions koordinates/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
)
from .data_browser import DataBrowserQuery # NOQA
from .dataset import Dataset # NOQA
from .publisher import Publisher, PublisherTheme # NOQA
from .enums import ( # NOQA
DataType,
VectorFilter,
Expand Down
100 changes: 82 additions & 18 deletions koordinates/api/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,41 @@
QgsFields,
QgsMemoryProviderUtils,
QgsCoordinateReferenceSystem,
QgsFeature
QgsFeature,
QgsWkbTypes
)

from .enums import DataType
from .repo import Repo
from .utils import ApiUtils
from .publisher import Publisher


class Crs:
"""
Represents a CRS
"""

def __init__(self, details: Dict):
self.details = details

def name(self) -> Optional[str]:
"""
Returns the CRS name
"""
return self.details.get('name')

def id(self) -> Optional[str]:
"""
Returns the CRS ID
"""
return self.details.get('id')

def url_external(self) -> Optional[str]:
"""
Returns the external URL for the CRS
"""
return self.details.get('url_external')


class Dataset:
Expand All @@ -29,12 +58,16 @@ def __init__(self, details: Dict):
self.details = details
self.id = details['id']
self.datatype = ApiUtils.data_type_from_dataset_response(self.details)
self.geometry_type: QgsWkbTypes.GeometryType = \
ApiUtils.geometry_type_from_dataset_response(
self.details
)

self.capabilities = ApiUtils.capabilities_from_dataset_response(
self.details
)
self.access = ApiUtils.access_from_dataset_response(self.details)
self.repository: Optional[Repo] = None
self._repository: Optional[Repo] = None

self.gridded_extent: Optional[QgsGeometry] = None
if 'data' in self.details and self.details['data'].get(
Expand All @@ -43,24 +76,48 @@ def __init__(self, details: Dict):
self.details['data']['gridded_extent']
)

self.crs: Optional[Crs] = Crs(self.details['data']['crs']) \
if self.details.get('data', {}).get('crs') else None

def title(self) -> str:
"""
Returns the dataset's title
"""
return self.details.get("title", 'Layer')

def publisher_name(self) -> Optional[str]:
def html_description(self) -> str:
"""
Returns the publisher name
Returns the HTML dataset description
"""
return self.details.get("publisher", {}).get("name")
return self.details.get("description_html", '')

def url_canonical(self) -> Optional[str]:
"""
Returns the canonical URL for the dataset
"""
return self.details.get('url_canonical')

def publisher(self) -> Optional[Publisher]:
"""
Returns the publisher details
"""
if not self.details.get("publisher"):
return None

return Publisher(self.details["publisher"])

def is_starred(self) -> bool:
"""
Returns True if the dataset is starred
"""
return self.details.get('is_starred', False)

def thumbnail_url(self) -> Optional[str]:
"""
Returns the dataset's thumbnail URL
"""
return self.details.get('thumbnail_url')

def created_at_date(self) -> Optional[datetime.date]:
"""
Returns the created at / first published at date
Expand Down Expand Up @@ -89,28 +146,35 @@ def updated_at_date(self) -> Optional[datetime.date]:

return None

def clone_url(self) -> Optional[str]:
def number_downloads(self) -> int:
"""
Returns the number of dataset downloads
"""
return self.details.get("num_downloads", 0)

def number_views(self) -> int:
"""
Returns the clone URL for the dataset
Returns the number of dataset views
"""
if self.repository is not None:
return self.repository.clone_url()
return self.details.get("num_views", 0)

if isinstance(self.details.get("repository"), dict):
url = self.details["repository"].get("clone_location_https")
if url:
return url
def repository(self) -> Optional[Repo]:
"""
Returns the repository information for the dataset
"""
if self._repository is not None:
return self._repository

repo_detail_url = self.details.get('repository')
if repo_detail_url:
if repo_detail_url and isinstance(repo_detail_url, dict):
self._repository = Repo(repo_detail_url)
elif repo_detail_url:
from .client import KoordinatesClient
self.repository = KoordinatesClient.instance().retrieve_repository(
self._repository = KoordinatesClient.instance().retrieve_repository(
repo_detail_url
)
if self.repository:
return self.repository.clone_url()

return None
return self._repository

def to_map_layer(self) -> Optional[QgsMapLayer]:
"""
Expand Down
58 changes: 58 additions & 0 deletions koordinates/api/publisher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from typing import (
Dict,
Optional
)


class PublisherTheme:
"""
Represents a publisher theme
"""
def __init__(self, details: Dict):
self.details = details

def background_color(self) -> Optional[str]:
"""
Returns the background color
"""
return self.details.get('background_color')

def logo(self) -> Optional[str]:
"""
Returns the publisher's logo
"""
return self.details.get('logo')


class PublisherSite:
"""
Represents a publisher site
"""

def __init__(self, details: Dict):
self.details = details

def name(self) -> Optional[str]:
"""
Returns the site name
"""
return self.details.get("name")


class Publisher:
"""
Represents a publisher
"""

def __init__(self, details: Dict):
self.details = details
self.site = PublisherSite(self.details['site']) \
if self.details.get('site') else None
self.theme = PublisherTheme(self.details['theme']) \
if self.details.get('theme') else None

def name(self) -> Optional[str]:
"""
Returns the publisher's name
"""
return self.details.get("name")
11 changes: 10 additions & 1 deletion koordinates/api/repo.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from typing import Dict
from typing import (
Dict,
Optional
)


class Repo:
Expand All @@ -10,6 +13,12 @@ def __init__(self, definition: Dict):
self.definition = definition
self.id = definition['id']

def title(self) -> Optional[str]:
"""
Returns the repository title
"""
return self.definition.get('title')

def clone_url(self) -> str:
"""
Returns the clone URL for the repository
Expand Down
23 changes: 22 additions & 1 deletion koordinates/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

from qgis.PyQt.QtCore import QUrlQuery

from qgis.core import QgsGeometry
from qgis.core import (
QgsGeometry,
QgsWkbTypes
)

from .enums import (
DataType,
Expand Down Expand Up @@ -54,6 +57,24 @@ def data_type_from_dataset_response(dataset: dict) -> DataType:
elif dataset.get('type') == 'repo':
return DataType.Repositories

@staticmethod
def geometry_type_from_dataset_response(dataset: dict) \
-> QgsWkbTypes.GeometryType:
"""
Extracts geometry type from a dataset response
"""
if dataset.get('data', {}).get('geometry_type') in (
'polygon', 'multipolygon'):
return QgsWkbTypes.PolygonGeometry
elif dataset.get('data', {}).get('geometry_type') in (
'point', 'multipoint'):
return QgsWkbTypes.PointGeometry
elif dataset.get('data', {}).get('geometry_type') in (
'linestring', 'multilinestring'):
return QgsWkbTypes.LineGeometry

return QgsWkbTypes.UnknownGeometry

@staticmethod
def access_from_dataset_response(dataset: dict) -> PublicAccessType:
"""
Expand Down
35 changes: 21 additions & 14 deletions koordinates/gui/action_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@
)
from qgis.utils import iface

from ..core import (
KartUtils,
KartNotInstalledException
)
from .gui_utils import GuiUtils
from ..api import (
KoordinatesClient,
Expand All @@ -25,6 +21,10 @@
from ..core import (
KartOperationManager
)
from ..core import (
KartUtils,
KartNotInstalledException
)

COLOR_INDEX = 0

Expand Down Expand Up @@ -72,7 +72,8 @@ class CloneButton(ActionButton):
BUTTON_TEXT = "#323233"
BUTTON_HOVER = "#e4e4e6"

def __init__(self, dataset: Dataset, parent=None, close_parent_on_clone=False):
def __init__(self, dataset: Dataset, parent=None,
close_parent_on_clone=False):
super().__init__(parent)

self.dataset = dataset
Expand All @@ -95,9 +96,12 @@ def _update_state(self):
"""
Updates button state based on current operations
"""
is_cloning = KartOperationManager.instance().is_cloning(
self.dataset.clone_url()
)
is_cloning = \
self.dataset.repository() and \
KartOperationManager.instance().is_cloning(
self.dataset.repository().clone_url()
)

self.setEnabled(not is_cloning)
if is_cloning:
icon = GuiUtils.get_icon('cloning_button.svg')
Expand All @@ -115,9 +119,12 @@ def _update_state(self):
self.setText(self.tr('Clone'))

def cloneRepository(self):
if not self.dataset.repository():
return

if self._close_parent_on_clone:
self.parent().close()
url = self.dataset.clone_url()
url = self.dataset.repository().clone_url()
title = self.dataset.title()

from .action_dialog import ActionDialog
Expand All @@ -132,11 +139,11 @@ def cloneRepository(self):

try:
KartUtils.clone_kart_repo(
title=title,
url=url,
username="kart",
password=KoordinatesClient.instance().apiKey,
parent=iface.mainWindow()
title=title,
url=url,
username="kart",
password=KoordinatesClient.instance().apiKey,
parent=iface.mainWindow()
)
except KartNotInstalledException:
iface.messageBar().pushMessage(
Expand Down
Loading