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

85 plugin main dialog button should not be enabled by default #88

Merged
Show file tree
Hide file tree
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Disable plugin main dialog by default
- Add button for opening output dir upon successful completion
- Drop support for point layers in the main plugin dialog
- Fix node connection method always being set to 'edge distance' when running
via the main plugin dialog
- Start autogenerated node ids from one rather than zero


## [2.0.0-rc3] - 2024-07-17

Expand Down
16 changes: 10 additions & 6 deletions src/qgis_conefor/coneforinputsprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ def get_numeric_attribute(
f"attribute {attribute_name!r} does not exist")


def autogenerate_feature_id(feature: qgis.core.QgsFeature) -> int:
return feature.id() + 1


def get_output_path(tentative_path: Path) -> Path:
"""
Rename the output name if it is already present in the directory.
Expand Down Expand Up @@ -102,7 +106,7 @@ def generate_node_file_by_attribute(
level=qgis.core.Qgis.Warning
)
id_ = (
feat.id() if node_id_field_name is None
autogenerate_feature_id(feat) if node_id_field_name is None
else get_numeric_attribute(feat, node_id_field_name)
)
attr = get_numeric_attribute(feat, node_attribute_field_name)
Expand Down Expand Up @@ -161,7 +165,7 @@ def generate_node_file_by_area(
geom = feat.geometry()
feat_area = area_measurer.measureArea(geom)
id_ = (
feat.id() if node_id_field_name is None
autogenerate_feature_id(feat) if node_id_field_name is None
else get_numeric_attribute(feat, node_id_field_name)
)
if id_ is not None:
Expand Down Expand Up @@ -208,7 +212,7 @@ def generate_connection_file_with_centroid_distances(
seen_ids = set()
for feat in feature_iterator_factory():
feat_id = (
feat.id() if node_id_field_name is None
autogenerate_feature_id(feat) if node_id_field_name is None
else get_numeric_attribute(feat, node_id_field_name)
)
if feat_id is not None:
Expand All @@ -223,7 +227,7 @@ def generate_connection_file_with_centroid_distances(
break
if pair_feat.id() > feat.id():
pair_feat_id = (
pair_feat.id() if node_id_field_name is None
autogenerate_feature_id(pair_feat) if node_id_field_name is None
else get_numeric_attribute(pair_feat, node_id_field_name)
)
if pair_feat_id is not None:
Expand Down Expand Up @@ -295,7 +299,7 @@ def generate_connection_file_with_edge_distances(
seen_ids = set()
for feat in feature_iterator_factory():
feat_id = (
feat.id() if node_id_field_name is None
autogenerate_feature_id(feat) if node_id_field_name is None
else get_numeric_attribute(feat, node_id_field_name)
)
if feat_id is not None:
Expand All @@ -312,7 +316,7 @@ def generate_connection_file_with_edge_distances(
break
if pair_feat.id() > feat.id():
pair_feat_id = (
pair_feat.id() if node_id_field_name is None
autogenerate_feature_id(pair_feat) if node_id_field_name is None
else get_numeric_attribute(pair_feat, node_id_field_name)
)
if pair_feat_id is not None:
Expand Down
92 changes: 26 additions & 66 deletions src/qgis_conefor/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import qgis.gui
from processing.tools.dataobjects import createContext
from qgis.PyQt import (
QtCore,
QtGui,
QtWidgets,
)
Expand All @@ -28,7 +29,10 @@
ConeforInputsPoint,
ConeforInputsPolygon,
)
from .utilities import log
from .utilities import (
log,
load_settings_key,
)


class QgisConefor:
Expand All @@ -38,7 +42,6 @@ class QgisConefor:
action: QtWidgets.QAction
dialog: Optional[QtWidgets.QDialog]
processing_provider: ProcessingConeforProvider
inputs_from_points_algorithm: Optional[qgis.core.QgsProcessingAlgorithm]
inputs_from_polygons_algorithm: Optional[qgis.core.QgsProcessingAlgorithm]
edge_distance_processing_model: Optional[qgis.core.QgsProcessingAlgorithm]
centroid_distance_processing_model: Optional[qgis.core.QgsProcessingAlgorithm]
Expand All @@ -63,7 +66,6 @@ def __init__(self, iface: qgis.gui.QgisInterface):
)
self.processing_provider = ProcessingConeforProvider()
self.processing_context = None
self.inputs_from_points_algorithm = None
self.inputs_from_polygons_algorithm = None
self.edge_distance_processing_model = None
self.centroid_distance_processing_model = None
Expand All @@ -77,8 +79,6 @@ def init_processing(self):
def initGui(self):
self.init_processing()
processing_registry = qgis.core.QgsApplication.processingRegistry()
self.inputs_from_points_algorithm = processing_registry.createAlgorithmById(
"conefor:inputsfrompoint")
self.inputs_from_polygons_algorithm = processing_registry.createAlgorithmById(
"conefor:inputsfrompolygon")
self.edge_distance_processing_model = processing_registry.createAlgorithmById(
Expand All @@ -96,6 +96,7 @@ def initGui(self):
self.iface.mainWindow()
)
self.action.triggered.connect(self.run)
self.action.setEnabled(False)
self.iface.addPluginToVectorMenu(f"&{self._action_title}", self.action)
self.iface.addVectorToolBarIcon(self.action)
qgis_project = qgis.core.QgsProject.instance()
Expand Down Expand Up @@ -216,53 +217,6 @@ def _enqueue_edge_distance_generation_task(
task_manager = qgis.core.QgsApplication.taskManager()
task_manager.addTask(task)

def _process_point_layer(
self,
layer_params: schemas.ConeforInputParameters,
create_distance_file: bool,
output_dir: str,
use_selected_features: bool
):
process_id = schemas.PROCESSING_TASK_ID_SEPARATOR.join((
str(uuid.uuid4()),
layer_params.layer.name()
))
input_layer_param = qgis.core.QgsProcessingFeatureSourceDefinition(
source=layer_params.layer.id(),
selectedFeaturesOnly=use_selected_features,
featureLimit=-1,
geometryCheck=self.processing_context.invalidGeometryCheck(),
)
task = qgis.core.QgsProcessingAlgRunnerTask(
algorithm=self.inputs_from_points_algorithm,
parameters={
ConeforInputsPolygon.INPUT_NODE_IDENTIFIER_NAME[0]: (
layer_params.id_attribute_field_name or ""),
ConeforInputsPolygon.INPUT_NODE_ATTRIBUTE_NAME[0]: (
layer_params.attribute_field_name or ""),
ConeforInputsPolygon.INPUT_DISTANCE_THRESHOLD[0]: "",
ConeforInputsPolygon.INPUT_OUTPUT_DIRECTORY[0]: output_dir,
ConeforInputsPoint.INPUT_POINT_LAYER[0]: input_layer_param,
},
context=self.processing_context
)
task.executed.connect(
functools.partial(
self.finalize_task_execution, process_id, layer_params)
)
self._processing_tasks[process_id] = task
task_manager = qgis.core.QgsApplication.taskManager()
log(f"About to enqueue task with process_id: {process_id!r}")
task_manager.addTask(task)
if create_distance_file:
self._enqueue_centroid_distance_generation_task(
layer_params,
schemas.PROCESSING_TASK_ID_SEPARATOR.join((
process_id,
"centroid_distance",
)),
)

def _process_polygon_layer(
self,
layer_params: schemas.ConeforInputParameters,
Expand All @@ -280,6 +234,12 @@ def _process_polygon_layer(
featureLimit=-1,
geometryCheck=self.processing_context.invalidGeometryCheck(),
)
connection_method = ConeforInputsPolygon._NODE_DISTANCE_CHOICES.index(
layer_params.connections_method.value)
log(
f"About to use {connection_method!r} as the node "
f"connection distance value"
)
task = qgis.core.QgsProcessingAlgRunnerTask(
algorithm=self.inputs_from_polygons_algorithm,
parameters={
Expand All @@ -294,7 +254,7 @@ def _process_polygon_layer(
ConeforInputsPolygon.INPUT_POLYGON_LAYER[0]: (
input_layer_param),
ConeforInputsPolygon.INPUT_NODE_CONNECTION_DISTANCE_METHOD[0]: (
layer_params.connections_method.value),
connection_method),
},
context=self.processing_context
)
Expand Down Expand Up @@ -329,7 +289,6 @@ def _process_polygon_layer(
raise NotImplementedError()

def prepare_conefor_inputs(self):
log(f"Inside prepare_conefor_inputs, now we need data to work with")
layer_inputs = set()
output_dir = str(self.dialog.output_dir_le.text())
only_selected_features = self.dialog.use_selected_features_chb.isChecked()
Expand Down Expand Up @@ -358,15 +317,6 @@ def prepare_conefor_inputs(self):
output_dir,
only_selected_features,
)

elif layer_to_process.layer.geometryType() == qgis.core.Qgis.GeometryType.Point:
self._process_point_layer(
layer_to_process,
self.dialog.create_distances_file_chb.isChecked(),
output_dir,
only_selected_features,
)
raise NotImplementedError
else:
raise RuntimeError(
f"layer: {layer_to_process.layer.name()!r} has invalid "
Expand Down Expand Up @@ -437,9 +387,14 @@ def finalize_task_execution(
level=qgis.core.Qgis.Critical
)
else:
self.iface.messageBar().pushMessage(
"Conefor inputs",
"Plugin finished execution",
message_widget = self.iface.messageBar().createMessage(
"Conefor inputs", "Plugin finished execution")
open_output_dir_btn = QtWidgets.QPushButton(message_widget)
open_output_dir_btn.setText("Open output directory")
open_output_dir_btn.pressed.connect(self.open_output_dir)
message_widget.layout().addWidget(open_output_dir_btn)
self.iface.messageBar().pushWidget(
message_widget,
level=qgis.core.Qgis.Info
)
self._task_results = {}
Expand All @@ -452,6 +407,11 @@ def check_for_removed_layers(self, removed_layer_ids: list[str]):
log("inside check_for_removed_layers")
self.start_analyzing_layers(disregard_ids=removed_layer_ids)

def open_output_dir(self):
output_dir = load_settings_key(
schemas.QgisConeforSettingsKey.OUTPUT_DIR)
QtGui.QDesktopServices.openUrl(QtCore.QUrl(f"file://{output_dir}"))



class NoUniqueFieldError(Exception):
Expand Down
9 changes: 1 addition & 8 deletions src/qgis_conefor/processing/algorithms/coneforinputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,7 @@ def processAlgorithm(self, parameters, context, feedback):

class ConeforInputsPolygon(ConeforInputsBase):
INPUT_POLYGON_LAYER = ("vector_layer", "Polygon layer",)
# INPUT_NODE_IDENTIFIER_NAME = (
# "node_identifier", "Node identifier (will autogenerate if not set)")
# INPUT_NODE_ATTRIBUTE_NAME = ("node_attribute", "Node attribute (will calculate area if not set)")
INPUT_NODE_CONNECTION_DISTANCE_METHOD = ("node_connection", "Node connection distance method")
# INPUT_DISTANCE_THRESHOLD = ("distance_threshold", "Distance threshold")
# INPUT_OUTPUT_DIRECTORY = ("output_dir", "Output directory for generated Conefor input files")
# OUTPUT_CONEFOR_NODES_FILE_PATH = ("output_path", "Conefor nodes file")
# OUTPUT_CONEFOR_CONNECTIONS_FILE_PATH = ("output_connections_path", "Conefor connections file")
_NODE_DISTANCE_CHOICES = [
NodeConnectionType.EDGE_DISTANCE.value,
NodeConnectionType.CENTROID_DISTANCE.value,
Expand Down Expand Up @@ -326,14 +319,14 @@ def processAlgorithm(self, parameters, context, feedback):
node_id_field_name = None
else:
node_id_field_name = raw_node_id_field_name
feedback.pushInfo(f"{self.parameterAsEnum(parameters, self.INPUT_NODE_CONNECTION_DISTANCE_METHOD[0], context)=} ")
connections_distance_method = NodeConnectionType(
self._NODE_DISTANCE_CHOICES[
self.parameterAsEnum(
parameters, self.INPUT_NODE_CONNECTION_DISTANCE_METHOD[0], context
)
]
)
feedback.pushInfo(f"{connections_distance_method.value=} ")
raw_distance_threshold = self.parameterAsString(
parameters, self.INPUT_DISTANCE_THRESHOLD[0], context)
if raw_distance_threshold == "":
Expand Down
1 change: 0 additions & 1 deletion src/qgis_conefor/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ class LayerAnalyzerTask(qgis.core.QgsTask):
relevant_layer_ids: dict[str, list[str]]

_relevant_geometry_types = (
qgis.core.Qgis.GeometryType.Point,
qgis.core.Qgis.GeometryType.Polygon,
)

Expand Down