diff --git a/felt/core/layer_exporter.py b/felt/core/layer_exporter.py index a36807f..36424ec 100644 --- a/felt/core/layer_exporter.py +++ b/felt/core/layer_exporter.py @@ -18,7 +18,10 @@ import zipfile from dataclasses import dataclass from pathlib import Path -from typing import Optional +from typing import ( + Optional, + Tuple +) from qgis.PyQt.QtCore import ( QVariant, @@ -27,7 +30,6 @@ from qgis.PyQt.QtXml import ( QDomDocument ) - from qgis.core import ( QgsFeedback, QgsMapLayer, @@ -53,8 +55,8 @@ ) from .enums import LayerExportResult -from .layer_style import LayerStyle from .exceptions import LayerPackagingException +from .layer_style import LayerStyle from .logger import Logger @@ -87,20 +89,32 @@ def __del__(self): self.temp_dir.cleanup() @staticmethod - def can_export_layer(layer: QgsMapLayer) -> bool: + def can_export_layer(layer: QgsMapLayer) -> Tuple[bool, str]: """ - Returns True if a layer can be exported + Returns True if a layer can be exported, and an explanatory + string if not """ if isinstance(layer, QgsVectorLayer): - return True + # Vector layers must have some features + if layer.featureCount() == 0: + return False, 'Layer is empty' + + return True, '' if isinstance(layer, QgsRasterLayer): - return layer.providerType() in ( - 'gdal', - 'virtualraster' + if layer.providerType() in ( + 'gdal', + 'virtualraster' + ): + return True, '' + + return False, '{} raster layers are not yet supported'.format( + layer.providerType() ) - return False + return False, '{} layers are not yet supported'.format( + layer.__class__.__name__ + ) @staticmethod def representative_layer_style(layer: QgsVectorLayer) -> LayerStyle: @@ -168,7 +182,8 @@ def generate_file_name(self, suffix: str) -> str: Generates a temporary file name with the given suffix """ return (Path(str(self.temp_dir.name)) / ('qgis_export_' + - (uuid.uuid4().hex + suffix))).as_posix() + ( + uuid.uuid4().hex + suffix))).as_posix() def export_layer_for_felt( self, @@ -269,7 +284,7 @@ def export_vector_layer( { 'type': Logger.PACKAGING_VECTOR, 'error': 'Error packaging layer: {}'.format(error_message) - } + } ) raise LayerPackagingException(error_message) @@ -393,7 +408,7 @@ def export_raster_layer( { 'type': Logger.PACKAGING_RASTER, 'error': 'Error packaging layer: {}'.format(error_message) - } + } ) raise LayerPackagingException(error_message) diff --git a/felt/core/map_uploader.py b/felt/core/map_uploader.py index 4332cca..86e71fb 100644 --- a/felt/core/map_uploader.py +++ b/felt/core/map_uploader.py @@ -18,7 +18,8 @@ from pathlib import Path from typing import ( Optional, - List + List, + Tuple ) from qgis.PyQt.QtCore import ( @@ -71,7 +72,7 @@ def __init__(self, ) project = project or QgsProject.instance() - self.unsupported_layers = [] + self.unsupported_layers: List[Tuple[str, str]] = [] if layers: self.current_map_crs = QgsCoordinateReferenceSystem('EPSG:4326') self.current_map_extent = QgsMapLayerUtils.combinedExtent( @@ -101,7 +102,7 @@ def __init__(self, self.layers = [ layer.clone() for layer in visible_layers if - LayerExporter.can_export_layer(layer) + LayerExporter.can_export_layer(layer)[0] ] self._build_unsupported_layer_details(project, visible_layers) @@ -149,11 +150,14 @@ def _build_unsupported_layer_details(self, these to users and to Felt """ unsupported_layer_type_count = defaultdict(int) + unsupported_layer_names = set() for layer in layers: - if LayerExporter.can_export_layer(layer): + can_export, reason = LayerExporter.can_export_layer(layer) + if can_export: continue - self.unsupported_layers.append(layer.name()) + unsupported_layer_names.add(layer.name()) + self.unsupported_layers.append((layer.name(), reason)) if layer.type() == QgsMapLayer.PluginLayer: id_string = layer.pluginLayerType() else: @@ -169,8 +173,8 @@ def _build_unsupported_layer_details(self, for layer_tree_layer in project.layerTreeRoot().findLayers(): if layer_tree_layer.isVisible() and \ not layer_tree_layer.layer() and \ - not layer_tree_layer.name() in self.unsupported_layers: - self.unsupported_layers.append(layer_tree_layer.name()) + not layer_tree_layer.name() in unsupported_layer_names: + self.unsupported_layers.append((layer_tree_layer.name(), '')) def default_map_title(self) -> str: """ @@ -199,7 +203,13 @@ def warning_message(self) -> Optional[str]: msg = '
' + self.tr('The following layers are not supported ' 'and won\'t be uploaded:') + '