def _rectanglify(self, task: QgsTask): """Rectanglify active layer's features""" layer: QgsVectorLayer = self.iface.activeLayer() only_selected = layer.selectedFeatureCount() > 0 constant_area = self.settings.value("constantArea", True, bool) keep_rings = self.settings.value("keepRings", True, bool) rings_share_axes = self.settings.value("ringsShareAxes", True, bool) with BeginCommand( layer, self.tr("Rectanglify selected features") if only_selected else self.tr("Rectanglify all features"), ): if only_selected: features = layer.getSelectedFeatures( QgsFeatureRequest().setSubsetOfAttributes([]) ) total = layer.selectedFeatureCount() else: features = layer.getFeatures( QgsFeatureRequest().setSubsetOfAttributes([]) ) total = layer.featureCount() for i, feat in enumerate(features, 1): # Check if task is canceled. Raising an exception will revert any # change made up to this point, thanks to the BeginCommand __exit__ # method if task.isCanceled(): raise Exception("Canceled") if feat.geometry().isMultipart(): multi = [ rectanglify_geometry( QgsGeometry.fromPolygonXY(polygon), constant_area, keep_rings, rings_share_axes, ) for polygon in feat.geometry().asMultiPolygon() ] new_geom = QgsGeometry.collectGeometry(multi) else: new_geom = rectanglify_geometry( feat.geometry(), constant_area, keep_rings, rings_share_axes ) layer.changeGeometry(feat.id(), new_geom) # Report task progress task.setProgress(i * 100 / total)