Date: Tue, 9 May 2023 21:24:33 +1000
Subject: [PATCH 06/11] Cleanup
---
koordinates/gui/dataset_dialog.py | 73 +++++++++++++++----------------
1 file changed, 36 insertions(+), 37 deletions(-)
diff --git a/koordinates/gui/dataset_dialog.py b/koordinates/gui/dataset_dialog.py
index 11cf100..6c963d6 100644
--- a/koordinates/gui/dataset_dialog.py
+++ b/koordinates/gui/dataset_dialog.py
@@ -72,11 +72,10 @@ class DatasetDialog(QDialog):
def __init__(self, parent, dataset: Dataset):
super().__init__(parent)
- self.dataset = dataset.details
- self.dataset_obj = dataset
+ self.dataset = dataset
self.details = KoordinatesClient.instance().dataset_details(
- self.dataset_obj)
+ self.dataset)
if self.details.get('attachments'):
self.attachments = KoordinatesClient.instance().get_json(self.details['attachments'])
@@ -84,7 +83,7 @@ def __init__(self, parent, dataset: Dataset):
self.attachments = []
self.setWindowTitle('Dataset Details - {}'.format(
- self.dataset_obj.title())
+ self.dataset.title())
)
self.setStyleSheet('DatasetDialog {background-color: white; }')
@@ -92,7 +91,7 @@ def __init__(self, parent, dataset: Dataset):
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 20)
- self.header_widget = HeaderWidget(self.dataset_obj)
+ self.header_widget = HeaderWidget(self.dataset)
layout.addWidget(self.header_widget)
title_hl = QHBoxLayout()
@@ -111,11 +110,11 @@ def __init__(self, parent, dataset: Dataset):
f""""""
- f"""{self.dataset_obj.title()}"""
+ f"""{self.dataset.title()}"""
)
title_hl.addWidget(self.label_title)
- if self.dataset_obj.access == PublicAccessType.none:
+ if self.dataset.access == PublicAccessType.none:
private_icon = QSvgWidget(GuiUtils.get_icon_svg('private.svg'))
private_icon.setFixedSize(QSize(24, 24))
private_icon.setToolTip(self.tr('Private'))
@@ -123,18 +122,18 @@ def __init__(self, parent, dataset: Dataset):
title_hl.addStretch()
- self.star_button = StarButton(self.dataset_obj)
+ self.star_button = StarButton(self.dataset)
title_hl.addWidget(self.star_button)
- if Capability.Clone in self.dataset_obj.capabilities:
- self.clone_button = CloneButton(self.dataset_obj,
+ if Capability.Clone in self.dataset.capabilities:
+ self.clone_button = CloneButton(self.dataset,
close_parent_on_clone=True)
title_hl.addWidget(self.clone_button)
else:
self.clone_button = None
- if Capability.Add in self.dataset_obj.capabilities:
- self.add_button = AddButton(self.dataset_obj)
+ if Capability.Add in self.dataset.capabilities:
+ self.add_button = AddButton(self.dataset)
title_hl.addWidget(self.add_button)
else:
self.add_button = None
@@ -154,13 +153,13 @@ def __init__(self, parent, dataset: Dataset):
self.thumbnail_label.setFixedSize(256, 195)
thumbnail_svg = DatasetGuiUtils.thumbnail_icon_for_dataset(
- self.dataset_obj
+ self.dataset
)
if thumbnail_svg:
self.setThumbnail(GuiUtils.get_svg_as_image(thumbnail_svg,
195, 195))
else:
- thumbnail_url = self.dataset_obj.thumbnail_url()
+ thumbnail_url = self.dataset.thumbnail_url()
if thumbnail_url:
downloadThumbnail(thumbnail_url, self)
@@ -173,7 +172,7 @@ def __init__(self, parent, dataset: Dataset):
base_details_right_pane_layout = QHBoxLayout()
base_details_right_pane_layout.setContentsMargins(12, 0, 0, 0)
- icon_name = DatasetGuiUtils.get_icon_for_dataset(self.dataset_obj,
+ icon_name = DatasetGuiUtils.get_icon_for_dataset(self.dataset,
IconStyle.Dark)
icon_label = SvgLabel(icon_name, 24, 24)
base_details_right_pane_layout.addWidget(icon_label)
@@ -181,8 +180,8 @@ def __init__(self, parent, dataset: Dataset):
summary_label = QLabel()
summary_label.setAlignment(Qt.AlignmentFlag.AlignTop)
- description = DatasetGuiUtils.get_type_description(self.dataset_obj)
- subtitle = DatasetGuiUtils.get_subtitle(self.dataset_obj,
+ description = DatasetGuiUtils.get_type_description(self.dataset)
+ subtitle = DatasetGuiUtils.get_subtitle(self.dataset,
short_format=False)
summary_label.setText(""" List[Tuple]:
def get_history_details(self) -> List[Tuple]:
res = []
- first_published = self.dataset_obj.created_at_date()
+ first_published = self.dataset.created_at_date()
if first_published:
res.append(('Date Added', self.format_date(first_published)))
- last_updated = self.dataset_obj.updated_at_date()
+ last_updated = self.dataset.updated_at_date()
if last_updated:
res.append(('Last updated', self.format_date(last_updated)))
- if Capability.RevisionCount in self.dataset_obj.capabilities:
+ if Capability.RevisionCount in self.dataset.capabilities:
data_revisions_count = \
KoordinatesClient.instance().data_revisions_count(
- self.dataset_obj.id)
+ self.dataset.id)
total_revisions_count = \
KoordinatesClient.instance().total_revisions_count(
- self.dataset_obj.id)
+ self.dataset.id)
if data_revisions_count is not None or total_revisions_count is not None:
res.append(
From b1e7c556167bf39439b9ed824072d5e4000b1227 Mon Sep 17 00:00:00 2001
From: Nyall Dawson
Date: Tue, 9 May 2023 21:57:50 +1000
Subject: [PATCH 07/11] Show more point cloud details
---
koordinates/gui/dataset_dialog.py | 36 +++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/koordinates/gui/dataset_dialog.py b/koordinates/gui/dataset_dialog.py
index 6c963d6..2ac07a3 100644
--- a/koordinates/gui/dataset_dialog.py
+++ b/koordinates/gui/dataset_dialog.py
@@ -414,10 +414,38 @@ def get_technical_details(self) -> List[Tuple]:
self.format_number(empty_count))
res.append(('Feature count', feature_count_label))
- fields = self.dataset.details.get('data', {}).get('fields', [])
- if fields:
- res.append(('_Attributes', ", ".join(
- [f.get("name", '') for f in fields])))
+ if self.dataset.datatype == DataType.PointClouds:
+ point_count = self.dataset.details.get("data", {}).get(
+ "point_count") or 0
+ res.append(('Point count', self.format_number(point_count)))
+ tile_count = self.dataset.details.get("data", {}).get(
+ "feature_count") or 0
+ res.append(('Tile count', self.format_number(tile_count)))
+ density = self.dataset.details.get("data", {}).get("point_density_sqm", {}) or 0
+ res.append(('Point density', '{:.2f} points per m² • {:.2f} points per US ft²'.format(density,
+ density / 10.7639)))
+ las_version = self.dataset.details.get("data", {}).get('tile_format_stored', {}).get(
+ "lasVersion") or 0
+ pdrf = self.dataset.details.get("data", {}).get('tile_format_stored', {}).get(
+ "pointDataRecordFormat") or 0
+ res.append(('Point cloud type', 'LAZ {} PDRF{}'.format(las_version, pdrf)))
+
+ format_as_stored = self.dataset.details.get("data", {}).get('tile_format_stored', {}).get(
+ "format") or ''
+ if format_as_stored == 'las':
+ format_as_stored = 'LAZ'
+ optimization = self.dataset.details.get("data", {}).get('tile_format_stored', {}).get(
+ "optimization") or ''
+ if optimization == 'copc':
+ optimization = 'COPc'
+
+ res.append(('Format as stored', '{} {}'.format(format_as_stored, optimization)))
+
+ else:
+ fields = self.dataset.details.get('data', {}).get('fields', [])
+ if fields:
+ res.append(('_Attributes', ", ".join(
+ [f.get("name", '') for f in fields])))
primary_key_fields = self.dataset.details.get('data', {}).get('primary_key_fields', [])
if primary_key_fields:
From 536cf58741c3b7e5ed63f184f337fdaa1a446b40 Mon Sep 17 00:00:00 2001
From: Nyall Dawson
Date: Wed, 10 May 2023 13:23:51 +1000
Subject: [PATCH 08/11] Show point cloud detail tables
---
koordinates/gui/dataset_dialog.py | 70 +++++++++++++++++-
koordinates/gui/detail_widgets/__init__.py | 1 +
.../gui/detail_widgets/table_widget.py | 74 +++++++++++++++++++
3 files changed, 144 insertions(+), 1 deletion(-)
create mode 100644 koordinates/gui/detail_widgets/table_widget.py
diff --git a/koordinates/gui/dataset_dialog.py b/koordinates/gui/dataset_dialog.py
index 2ac07a3..c5267c5 100644
--- a/koordinates/gui/dataset_dialog.py
+++ b/koordinates/gui/dataset_dialog.py
@@ -56,7 +56,8 @@
HeaderWidget,
DetailsTable,
AttachmentWidget,
- MetadataWidget
+ MetadataWidget,
+ TableWidget
)
pluginPath = os.path.split(os.path.dirname(__file__))[0]
@@ -335,6 +336,8 @@ def __init__(self, parent, dataset: Dataset):
tech_details_grid.set_details(self.get_technical_details())
contents_layout.addLayout(tech_details_grid)
+ self.append_dataset_tables(contents_layout)
+
contents_layout.addSpacing(40)
history_grid = DetailsTable('History & Version Control')
@@ -544,3 +547,68 @@ def setThumbnail(self, img):
thumbnail.setDevicePixelRatio(scale_factor)
self.thumbnail_label.setPixmap(thumbnail)
+
+ def append_dataset_tables(self, layout):
+ """
+ Appends dataset specific tables to the layout
+ """
+ heading_font_size = 10
+ if platform.system() == 'Darwin':
+ heading_font_size = 14
+
+ if self.dataset.datatype == DataType.PointClouds:
+ heading = QLabel(
+ """{}""".format(self.tr('Classifications'))
+ )
+ layout.addSpacing(20)
+ layout.addWidget(heading)
+ layout.addSpacing(10)
+
+ headings = ['',
+ self.tr('Class'),
+ self.tr('Point count'),
+ self.tr('% of dataset')
+ ]
+
+ point_count = self.dataset.details.get("data", {}).get(
+ "point_count") or 1
+
+ contents = []
+ for classification in self.dataset.details.get('data', {}).get('classifications', []):
+ row = [
+ str(classification.get('id')),
+ str(classification.get('name')),
+ self.format_number(classification.get('count', 0)),
+ '{:.2f}%'.format(100*classification.get('count', 0) / point_count),
+ ]
+ contents.append(row)
+
+ table = TableWidget(headings, contents)
+ layout.addWidget(table)
+
+ heading = QLabel(
+ """{}""".format(self.tr('Dimensions'))
+ )
+ layout.addSpacing(20)
+ layout.addWidget(heading)
+ layout.addSpacing(10)
+
+ headings = [self.tr('Name'),
+ self.tr('Data type')
+ ]
+
+ contents = []
+ for field in self.dataset.details.get('data', {}).get(
+ 'fields', []):
+ row = [
+ str(field.get('name')),
+ str(field.get('type'))
+ ]
+ contents.append(row)
+
+ table = TableWidget(headings, contents)
+ layout.addWidget(table)
diff --git a/koordinates/gui/detail_widgets/__init__.py b/koordinates/gui/detail_widgets/__init__.py
index c1e60dc..b840c66 100644
--- a/koordinates/gui/detail_widgets/__init__.py
+++ b/koordinates/gui/detail_widgets/__init__.py
@@ -8,3 +8,4 @@
from .horizontal_line_widget import HorizontalLine # NOQA
from .metadata_widget import MetadataWidget # NOQA
from .statistic_widget import StatisticWidget # NOQA
+from .table_widget import TableWidget # NOQA
diff --git a/koordinates/gui/detail_widgets/table_widget.py b/koordinates/gui/detail_widgets/table_widget.py
new file mode 100644
index 0000000..7d8e047
--- /dev/null
+++ b/koordinates/gui/detail_widgets/table_widget.py
@@ -0,0 +1,74 @@
+import platform
+from typing import (
+ Optional,
+ List
+)
+
+from qgis.PyQt.QtWidgets import (
+ QWidget,
+ QVBoxLayout,
+ QLabel
+)
+
+from ..gui_utils import FONT_FAMILIES
+
+
+class TableWidget(QWidget):
+ """
+ Displays a styled table of data
+ """
+
+ BACKGROUND_COLOR = "#ffffff"
+ HEADING_BACKGROUND_COLOR = "#f5f5f7"
+ BORDER_COLOR = "#eaeaea"
+
+ def __init__(self,
+ headings: List[str],
+ contents: List[List[str]],
+ parent: Optional[QWidget] = None):
+ super().__init__(parent)
+
+ vl = QVBoxLayout()
+ vl.setContentsMargins(0, 0, 0, 0)
+
+ self.table_label = QLabel()
+
+ base_font_size = 10
+ if platform.system() == 'Darwin':
+ base_font_size = 14
+
+ padding = int(base_font_size * 0.75)
+
+ html = f"""
+
+ """
+ if headings:
+ html += ""
+ for cell in headings:
+ html += f"""{cell} | """
+ html += "
"
+
+ for row in contents:
+ html += ""
+ for cell in row:
+ html += f"""{cell} | """
+
+ html += "
"
+
+ html += """
+
+ """
+ self.table_label.setText(html)
+
+ vl.addWidget(self.table_label)
+ self.setLayout(vl)
From faaec9cffacdc7517f0bae79a2cb486f8bc86ad3 Mon Sep 17 00:00:00 2001
From: Nyall Dawson
Date: Wed, 10 May 2023 13:34:22 +1000
Subject: [PATCH 09/11] Move toward horizontal table layout
---
koordinates/gui/dataset_dialog.py | 40 ++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/koordinates/gui/dataset_dialog.py b/koordinates/gui/dataset_dialog.py
index c5267c5..ac9b083 100644
--- a/koordinates/gui/dataset_dialog.py
+++ b/koordinates/gui/dataset_dialog.py
@@ -24,6 +24,7 @@
QDialog,
QVBoxLayout,
QScrollArea,
+ QGridLayout,
)
from qgis.PyQt.QtSvg import QSvgWidget
@@ -560,11 +561,28 @@ def append_dataset_tables(self, layout):
heading = QLabel(
"""{}""".format(self.tr('Classifications'))
+ """color: black">{}""".format(
+ self.tr('Point Cloud Characteristics')
+ )
)
layout.addSpacing(20)
layout.addWidget(heading)
- layout.addSpacing(10)
+ layout.addWidget(HorizontalLine())
+ layout.addSpacing(7)
+
+ gl = QGridLayout()
+ heading = QLabel(
+ """{}""".format(
+ self.tr('Classifications')
+ )
+ )
+ heading.setAlignment(Qt.AlignLeft | Qt.AlignTop)
+ vl = QVBoxLayout()
+ vl.setContentsMargins(0, 5, 10, 0)
+ vl.addWidget(heading)
+ gl.addLayout(vl, 0, 0)
headings = ['',
self.tr('Class'),
@@ -586,16 +604,18 @@ def append_dataset_tables(self, layout):
contents.append(row)
table = TableWidget(headings, contents)
- layout.addWidget(table)
+ gl.addWidget(table, 0, 1)
heading = QLabel(
- """{}""".format(self.tr('Dimensions'))
+ """color: #868889">{}""".format(self.tr('Dimensions'))
)
- layout.addSpacing(20)
- layout.addWidget(heading)
- layout.addSpacing(10)
+ heading.setAlignment(Qt.AlignLeft | Qt.AlignTop)
+ vl = QVBoxLayout()
+ vl.setContentsMargins(0, 5, 10, 0)
+ vl.addWidget(heading)
+ gl.addLayout(vl, 1, 0)
headings = [self.tr('Name'),
self.tr('Data type')
@@ -611,4 +631,6 @@ def append_dataset_tables(self, layout):
contents.append(row)
table = TableWidget(headings, contents)
- layout.addWidget(table)
+ gl.addWidget(table, 1, 1)
+ gl.setColumnStretch(1, 1)
+ layout.addLayout(gl)
From b466dd5b1492ee1dc19ee0efeddff46530a21482 Mon Sep 17 00:00:00 2001
From: Nyall Dawson
Date: Wed, 10 May 2023 13:47:52 +1000
Subject: [PATCH 10/11] Allow dynamic table expansion
---
.../gui/detail_widgets/table_widget.py | 46 +++++++++++++++++--
1 file changed, 41 insertions(+), 5 deletions(-)
diff --git a/koordinates/gui/detail_widgets/table_widget.py b/koordinates/gui/detail_widgets/table_widget.py
index 7d8e047..9d2af08 100644
--- a/koordinates/gui/detail_widgets/table_widget.py
+++ b/koordinates/gui/detail_widgets/table_widget.py
@@ -4,6 +4,11 @@
List
)
+from qgis.PyQt.QtCore import (
+ Qt,
+ QUrl
+)
+from qgis.PyQt.QtGui import QDesktopServices
from qgis.PyQt.QtWidgets import (
QWidget,
QVBoxLayout,
@@ -22,6 +27,8 @@ class TableWidget(QWidget):
HEADING_BACKGROUND_COLOR = "#f5f5f7"
BORDER_COLOR = "#eaeaea"
+ INITIAL_VISIBLE_ROWS = 4
+
def __init__(self,
headings: List[str],
contents: List[List[str]],
@@ -32,7 +39,17 @@ def __init__(self,
vl.setContentsMargins(0, 0, 0, 0)
self.table_label = QLabel()
+ self.headings = headings
+ self.contents = contents
+
+ self.rebuild_table()
+ self.table_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
+ self.table_label.linkActivated.connect(self.link_clicked)
+
+ vl.addWidget(self.table_label)
+ self.setLayout(vl)
+ def rebuild_table(self, expand=False):
base_font_size = 10
if platform.system() == 'Darwin':
base_font_size = 14
@@ -45,9 +62,9 @@ def __init__(self,
border-collapse: collapse;
">
"""
- if headings:
+ if self.headings:
html += ""
- for cell in headings:
+ for cell in self.headings:
html += f"""{cell} | """
html += "
"
- for row in contents:
+ if not expand:
+ visible_rows = self.contents[:self.INITIAL_VISIBLE_ROWS]
+ else:
+ visible_rows = self.contents[:]
+
+ for row in visible_rows:
html += ""
for cell in row:
html += f""""
+ if len(self.contents) > self.INITIAL_VISIBLE_ROWS and not expand:
+ html += " |
"
+ html += """ | """
+ html += "
"
+
html += """
"""
self.table_label.setText(html)
- vl.addWidget(self.table_label)
- self.setLayout(vl)
+ def link_clicked(self, link):
+ if link == 'more':
+ self.rebuild_table(True)
+ else:
+ QDesktopServices.openUrl(QUrl(link))
From f02c97cb15472925d57e9bb6eece6194c7df9ea5 Mon Sep 17 00:00:00 2001
From: Nyall Dawson
Date: Thu, 11 May 2023 08:32:02 +1000
Subject: [PATCH 11/11] Lint
---
koordinates/gui/action_button.py | 31 ++---
koordinates/gui/dataset_browser_items.py | 6 +-
koordinates/gui/dataset_dialog.py | 108 +++++++++++-------
koordinates/gui/dataset_utils.py | 37 +++---
.../gui/detail_widgets/header_widget.py | 10 +-
.../gui/detail_widgets/table_widget.py | 2 +-
6 files changed, 116 insertions(+), 78 deletions(-)
diff --git a/koordinates/gui/action_button.py b/koordinates/gui/action_button.py
index f048d8f..c2a44d6 100644
--- a/koordinates/gui/action_button.py
+++ b/koordinates/gui/action_button.py
@@ -11,10 +11,6 @@
)
from qgis.utils import iface
-from ..core import (
- KartUtils,
- KartNotInstalledException
-)
from .gui_utils import GuiUtils
from ..api import (
KoordinatesClient,
@@ -25,6 +21,10 @@
from ..core import (
KartOperationManager
)
+from ..core import (
+ KartUtils,
+ KartNotInstalledException
+)
COLOR_INDEX = 0
@@ -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
@@ -95,10 +96,12 @@ def _update_state(self):
"""
Updates button state based on current operations
"""
- is_cloning = self.dataset.repository() and \
- KartOperationManager.instance().is_cloning(
- self.dataset.repository().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')
@@ -136,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(
diff --git a/koordinates/gui/dataset_browser_items.py b/koordinates/gui/dataset_browser_items.py
index 9802b7c..f016e58 100644
--- a/koordinates/gui/dataset_browser_items.py
+++ b/koordinates/gui/dataset_browser_items.py
@@ -660,9 +660,9 @@ def process_thumbnail(self, img: Optional[QImage]) -> QImage:
if img is not None:
resized = img.scaled(image_size.width(),
- image_size.height(),
- Qt.KeepAspectRatioByExpanding,
- Qt.SmoothTransformation)
+ image_size.height(),
+ Qt.KeepAspectRatioByExpanding,
+ Qt.SmoothTransformation)
if resized.width() > image_size.width():
left = int((resized.width() - image_size.width())/2)
diff --git a/koordinates/gui/dataset_dialog.py b/koordinates/gui/dataset_dialog.py
index ac9b083..77c4926 100644
--- a/koordinates/gui/dataset_dialog.py
+++ b/koordinates/gui/dataset_dialog.py
@@ -1,8 +1,11 @@
+import datetime
import locale
import os
import platform
-import datetime
-from typing import Dict, List, Tuple
+from typing import (
+ List,
+ Tuple
+)
from qgis.PyQt import uic
from qgis.PyQt.QtCore import (
@@ -17,6 +20,7 @@
QBrush,
QColor
)
+from qgis.PyQt.QtSvg import QSvgWidget
from qgis.PyQt.QtWidgets import (
QFrame,
QLabel,
@@ -26,7 +30,6 @@
QScrollArea,
QGridLayout,
)
-from qgis.PyQt.QtSvg import QSvgWidget
from .action_button import (
AddButton,
@@ -36,6 +39,15 @@
DatasetGuiUtils,
IconStyle
)
+from .detail_widgets import (
+ HorizontalLine,
+ StatisticWidget,
+ HeaderWidget,
+ DetailsTable,
+ AttachmentWidget,
+ MetadataWidget,
+ TableWidget
+)
from .gui_utils import (
GuiUtils,
FONT_FAMILIES,
@@ -44,22 +56,12 @@
from .svg_label import SvgLabel
from .thumbnails import downloadThumbnail
from ..api import (
- ApiUtils,
DataType,
PublicAccessType,
Capability,
KoordinatesClient,
Dataset
)
-from .detail_widgets import (
- HorizontalLine,
- StatisticWidget,
- HeaderWidget,
- DetailsTable,
- AttachmentWidget,
- MetadataWidget,
- TableWidget
-)
pluginPath = os.path.split(os.path.dirname(__file__))[0]
@@ -80,7 +82,8 @@ def __init__(self, parent, dataset: Dataset):
self.dataset)
if self.details.get('attachments'):
- self.attachments = KoordinatesClient.instance().get_json(self.details['attachments'])
+ self.attachments = KoordinatesClient.instance().get_json(
+ self.details['attachments'])
else:
self.attachments = []
@@ -200,13 +203,15 @@ def __init__(self, parent, dataset: Dataset):
base_details_right_pane_layout_vl = QVBoxLayout()
base_details_right_pane_layout_vl.setContentsMargins(0, 0, 0, 0)
- base_details_right_pane_layout_vl.addLayout(base_details_right_pane_layout)
+ base_details_right_pane_layout_vl.addLayout(
+ base_details_right_pane_layout)
if self.dataset.repository():
base_details_right_pane_layout = QHBoxLayout()
base_details_right_pane_layout.setContentsMargins(12, 0, 0, 0)
- icon_label = SvgLabel(GuiUtils.get_icon_svg('repo-book.svg'), 24, 24)
+ icon_label = SvgLabel(GuiUtils.get_icon_svg('repo-book.svg'), 24,
+ 24)
base_details_right_pane_layout.addWidget(icon_label)
summary_label = QLabel()
@@ -226,7 +231,8 @@ def __init__(self, parent, dataset: Dataset):
base_details_right_pane_layout.addSpacing(10)
base_details_right_pane_layout.addWidget(summary_label, 1)
- base_details_right_pane_layout_vl.addLayout(base_details_right_pane_layout)
+ base_details_right_pane_layout_vl.addLayout(
+ base_details_right_pane_layout)
base_details_right_pane_layout_vl.addStretch()
@@ -317,8 +323,9 @@ def __init__(self, parent, dataset: Dataset):
contents_layout.addSpacing(40)
- if self.details.get('metadata') and (self.details['metadata'].get('iso') or
- self.details['metadata'].get('dc')):
+ if self.details.get('metadata') and (
+ self.details['metadata'].get('iso') or
+ self.details['metadata'].get('dc')):
heading = QLabel(
"""{}""".format(
FONT_FAMILIES,
@@ -329,7 +336,8 @@ def __init__(self, parent, dataset: Dataset):
for source in ('iso', 'dc'):
if self.details['metadata'].get(source):
contents_layout.addWidget(
- MetadataWidget(source, self.details['metadata'][source]))
+ MetadataWidget(source,
+ self.details['metadata'][source]))
contents_layout.addSpacing(40)
@@ -356,7 +364,8 @@ def __init__(self, parent, dataset: Dataset):
scroll_area.setWidgetResizable(True)
scroll_area_layout.addWidget(scroll_area)
- scroll_area.viewport().setStyleSheet("#qt_scrollarea_viewport{ background: transparent; }")
+ scroll_area.viewport().setStyleSheet(
+ "#qt_scrollarea_viewport{ background: transparent; }")
layout.addLayout(scroll_area_layout, 1)
@@ -410,8 +419,10 @@ def get_technical_details(self) -> List[Tuple]:
crs_id
)))
- feature_count = self.dataset.details.get("data", {}).get("feature_count", 0)
- empty_count = self.dataset.details.get("data", {}).get('empty_geometry_count', 0)
+ feature_count = self.dataset.details.get("data", {}).get(
+ "feature_count", 0)
+ empty_count = self.dataset.details.get("data", {}).get(
+ 'empty_geometry_count', 0)
feature_count_label = self.format_number(feature_count)
if empty_count:
feature_count_label += ' • {} with empty or null geometries'.format(
@@ -425,25 +436,34 @@ def get_technical_details(self) -> List[Tuple]:
tile_count = self.dataset.details.get("data", {}).get(
"feature_count") or 0
res.append(('Tile count', self.format_number(tile_count)))
- density = self.dataset.details.get("data", {}).get("point_density_sqm", {}) or 0
- res.append(('Point density', '{:.2f} points per m² • {:.2f} points per US ft²'.format(density,
- density / 10.7639)))
- las_version = self.dataset.details.get("data", {}).get('tile_format_stored', {}).get(
+ density = self.dataset.details.get("data", {}).get(
+ "point_density_sqm", {}) or 0
+ res.append(('Point density',
+ '{:.2f} points per m² • {:.2f} points per US ft²'.format(
+ density,
+ density / 10.7639)))
+ las_version = self.dataset.details.get("data", {}).get(
+ 'tile_format_stored', {}).get(
"lasVersion") or 0
- pdrf = self.dataset.details.get("data", {}).get('tile_format_stored', {}).get(
+ pdrf = self.dataset.details.get("data", {}).get(
+ 'tile_format_stored', {}).get(
"pointDataRecordFormat") or 0
- res.append(('Point cloud type', 'LAZ {} PDRF{}'.format(las_version, pdrf)))
+ res.append(('Point cloud type',
+ 'LAZ {} PDRF{}'.format(las_version, pdrf)))
- format_as_stored = self.dataset.details.get("data", {}).get('tile_format_stored', {}).get(
+ format_as_stored = self.dataset.details.get("data", {}).get(
+ 'tile_format_stored', {}).get(
"format") or ''
if format_as_stored == 'las':
format_as_stored = 'LAZ'
- optimization = self.dataset.details.get("data", {}).get('tile_format_stored', {}).get(
+ optimization = self.dataset.details.get("data", {}).get(
+ 'tile_format_stored', {}).get(
"optimization") or ''
if optimization == 'copc':
optimization = 'COPc'
- res.append(('Format as stored', '{} {}'.format(format_as_stored, optimization)))
+ res.append(('Format as stored',
+ '{} {}'.format(format_as_stored, optimization)))
else:
fields = self.dataset.details.get('data', {}).get('fields', [])
@@ -451,7 +471,8 @@ def get_technical_details(self) -> List[Tuple]:
res.append(('_Attributes', ", ".join(
[f.get("name", '') for f in fields])))
- primary_key_fields = self.dataset.details.get('data', {}).get('primary_key_fields', [])
+ primary_key_fields = self.dataset.details.get('data', {}).get(
+ 'primary_key_fields', [])
if primary_key_fields:
res.append(('_Primary key', ", ".join(primary_key_fields)))
@@ -503,7 +524,8 @@ def setThumbnail(self, img):
painter.setPen(Qt.NoPen)
painter.setBrush(QBrush(QColor(255, 0, 0)))
- painter.drawRoundedRect(0, 0, image_size.width(), image_size.height(), 9, 9)
+ painter.drawRoundedRect(0, 0, image_size.width(), image_size.height(),
+ 9, 9)
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
painter.setBrush(QBrush(QColor('#dddddd')))
@@ -529,12 +551,14 @@ def setThumbnail(self, img):
top = 0
if left > 0 or top > 0:
- cropped = resized.copy(QRect(left, top, image_size.width(), image_size.height()))
+ cropped = resized.copy(QRect(left, top, image_size.width(),
+ image_size.height()))
painter.drawImage(0, 0, cropped)
else:
- painter.drawImage(int((image_size.width() - resized.width()) / 2),
- int((image_size.height() - resized.height()) / 2),
- resized)
+ painter.drawImage(
+ int((image_size.width() - resized.width()) / 2),
+ int((image_size.height() - resized.height()) / 2),
+ resized)
else:
painter.drawImage(0, 0, img)
else:
@@ -594,13 +618,15 @@ def append_dataset_tables(self, layout):
"point_count") or 1
contents = []
- for classification in self.dataset.details.get('data', {}).get('classifications', []):
+ for classification in self.dataset.details.get('data', {}).get(
+ 'classifications', []):
row = [
str(classification.get('id')),
str(classification.get('name')),
self.format_number(classification.get('count', 0)),
- '{:.2f}%'.format(100*classification.get('count', 0) / point_count),
- ]
+ '{:.2f}%'.format(
+ 100 * classification.get('count', 0) / point_count),
+ ]
contents.append(row)
table = TableWidget(headings, contents)
diff --git a/koordinates/gui/dataset_utils.py b/koordinates/gui/dataset_utils.py
index 04c9b4d..a0598f9 100644
--- a/koordinates/gui/dataset_utils.py
+++ b/koordinates/gui/dataset_utils.py
@@ -1,7 +1,6 @@
from enum import Enum
from typing import (
- Optional,
- Dict
+ Optional
)
from qgis.core import (
@@ -10,7 +9,6 @@
)
from ..api import (
- ApiUtils,
DataType,
Dataset
)
@@ -70,17 +68,23 @@ def get_icon_for_dataset(dataset: Dataset, style: IconStyle) \
@staticmethod
def get_data_type(dataset: Dataset) -> Optional[str]:
if dataset.datatype == DataType.Vectors:
- if dataset.details.get('data', {}).get('geometry_type') == 'polygon':
+ if dataset.details.get('data', {}).get(
+ 'geometry_type') == 'polygon':
return 'Vector polygon'
- elif dataset.details.get('data', {}).get('geometry_type') == 'multipolygon':
+ elif dataset.details.get('data', {}).get(
+ 'geometry_type') == 'multipolygon':
return 'Vector multipolygon'
- elif dataset.details.get('data', {}).get('geometry_type') == 'point':
+ elif dataset.details.get('data', {}).get(
+ 'geometry_type') == 'point':
return 'Vector point'
- elif dataset.details.get('data', {}).get('geometry_type') == 'multipoint':
+ elif dataset.details.get('data', {}).get(
+ 'geometry_type') == 'multipoint':
return 'Vector multipoint'
- elif dataset.details.get('data', {}).get('geometry_type') == 'linestring':
+ elif dataset.details.get('data', {}).get(
+ 'geometry_type') == 'linestring':
return 'Vector line'
- elif dataset.details.get('data', {}).get('geometry_type') == 'multilinestring':
+ elif dataset.details.get('data', {}).get(
+ 'geometry_type') == 'multilinestring':
return 'Vector multiline'
elif dataset.datatype == DataType.Rasters:
return 'Raster'
@@ -126,13 +130,18 @@ def get_type_description(dataset: Dataset) -> Optional[str]:
return None
@staticmethod
- def get_subtitle(dataset: Dataset, short_format: bool = True) -> Optional[str]:
+ def get_subtitle(dataset: Dataset, short_format: bool = True) \
+ -> Optional[str]:
+ """
+ Return a subtitle to use for a Dataset
+ """
if dataset.datatype == DataType.Vectors:
count = dataset.details.get("data", {}).get("feature_count") or 0
if dataset.geometry_type == QgsWkbTypes.PolygonGeometry:
- return '{} Polygons'.format(DatasetGuiUtils.format_count(count))
+ return '{} Polygons'.format(
+ DatasetGuiUtils.format_count(count))
elif dataset.geometry_type == QgsWkbTypes.PointGeometry:
return '{} Points'.format(DatasetGuiUtils.format_count(count))
elif dataset.geometry_type == QgsWkbTypes.LineGeometry:
@@ -149,7 +158,8 @@ def get_subtitle(dataset: Dataset, short_format: bool = True) -> Optional[str]:
ext = dataset.details.get('extension', '').upper()
file_size = dataset.details.get('file_size')
if file_size:
- return '{} {}'.format(ext, QgsFileUtils.representFileSize(file_size))
+ return '{} {}'.format(ext, QgsFileUtils.representFileSize(
+ file_size))
return ext
elif dataset.datatype == DataType.Sets:
return None
@@ -157,7 +167,8 @@ def get_subtitle(dataset: Dataset, short_format: bool = True) -> Optional[str]:
return None
elif dataset.datatype == DataType.PointClouds:
count = dataset.details.get("data", {}).get("feature_count") or 0
- point_count = dataset.details.get("data", {}).get("point_count") or 0
+ point_count = dataset.details.get("data", {}).get(
+ "point_count") or 0
if short_format:
return '{} Tiles'.format(
DatasetGuiUtils.format_count(count)
diff --git a/koordinates/gui/detail_widgets/header_widget.py b/koordinates/gui/detail_widgets/header_widget.py
index 0826987..b7e1b1f 100644
--- a/koordinates/gui/detail_widgets/header_widget.py
+++ b/koordinates/gui/detail_widgets/header_widget.py
@@ -1,5 +1,3 @@
-from typing import Optional
-
from qgis.PyQt.QtCore import (
Qt
)
@@ -11,12 +9,12 @@
QApplication
)
-from koordinates.gui.gui_utils import FONT_FAMILIES
from koordinates.gui.detail_widgets.svg_framed_button import SvgFramedButton
-from koordinates.gui.detail_widgets.thumbnail_label_widget import ThumbnailLabel
+from koordinates.gui.detail_widgets.thumbnail_label_widget import \
+ ThumbnailLabel
+from koordinates.gui.gui_utils import FONT_FAMILIES
from ...api import (
- Dataset,
- PublisherTheme
+ Dataset
)
diff --git a/koordinates/gui/detail_widgets/table_widget.py b/koordinates/gui/detail_widgets/table_widget.py
index 9d2af08..b2eb810 100644
--- a/koordinates/gui/detail_widgets/table_widget.py
+++ b/koordinates/gui/detail_widgets/table_widget.py
@@ -90,7 +90,7 @@ def rebuild_table(self, expand=False):
if len(self.contents) > self.INITIAL_VISIBLE_ROWS and not expand:
html += ""
html += """ |