Skip to content

Commit

Permalink
Massive UX improvement: pan/zoom to feature within *visible* area of …
Browse files Browse the repository at this point in the history
…the map canvas
  • Loading branch information
nirvn committed Jun 24, 2023
1 parent d5c74db commit f1ba257
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/core/featurelistextentcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void FeatureListExtentController::zoomToSelected( bool skipIfIntersects ) const

if ( layer && layer->geometryType() != Qgis::GeometryType::Unknown && layer->geometryType() != Qgis::GeometryType::Null )
{
QgsRectangle extent = FeatureUtils::extent( mMapSettings, layer, feat );
QgsRectangle extent = FeatureUtils::extent( mMapSettings, layer, feat, mFeatureForm ? mFeatureForm->x() : 0.0, mFeatureForm ? mFeatureForm->y() : 0.0 );
if ( !skipIfIntersects || !mMapSettings->extent().intersects( extent ) )
mMapSettings->setExtent( extent );
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/featurelistextentcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "qgsquickmapsettings.h"

#include <QObject>
#include <QQuickItem>

class FeatureListExtentController : public QObject
{
Expand All @@ -30,6 +31,7 @@ class FeatureListExtentController : public QObject
Q_PROPERTY( FeatureListModelSelection *selection MEMBER mSelection NOTIFY selectionChanged )
Q_PROPERTY( bool autoZoom MEMBER mAutoZoom NOTIFY autoZoomChanged )
Q_PROPERTY( QgsQuickMapSettings *mapSettings MEMBER mMapSettings NOTIFY mapSettingsChanged )
Q_PROPERTY( QQuickItem *featureForm MEMBER mFeatureForm NOTIFY featureFormChanged )

public:
explicit FeatureListExtentController( QObject *parent = nullptr );
Expand All @@ -54,6 +56,7 @@ class FeatureListExtentController : public QObject
void selectionChanged();
void modelChanged();
void mapSettingsChanged();
void featureFormChanged();
void featureFormStateRequested();

private slots:
Expand All @@ -64,6 +67,7 @@ class FeatureListExtentController : public QObject
MultiFeatureListModel *mModel = nullptr;
FeatureListModelSelection *mSelection = nullptr;
QgsQuickMapSettings *mMapSettings = nullptr;
QQuickItem *mFeatureForm = nullptr;
bool mAutoZoom = false;
};

Expand Down
2 changes: 1 addition & 1 deletion src/core/orderedrelationmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ QVariant OrderedRelationModel::data( const QModelIndex &index, int role ) const
return ReferencingFeatureListModel::data( index, role );
}

void OrderedRelationModel::onViewCurrentFeatureChanged( int index )
void OrderedRelationModel::triggerViewCurrentFeatureChange( int index )
{
if ( index < 0 || index >= rowCount( QModelIndex() ) )
return;
Expand Down
4 changes: 1 addition & 3 deletions src/core/orderedrelationmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class OrderedRelationModel : public ReferencingFeatureListModel
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
Q_INVOKABLE bool moveItems( const int fromIdx, const int toIdx );
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void triggerViewCurrentFeatureChange( int index );

signals:
void orderingFieldChanged();
Expand All @@ -60,9 +61,6 @@ class OrderedRelationModel : public ReferencingFeatureListModel
void currentFeatureChanged( QgsFeature feature );
void failedReorder();

private slots:
void onViewCurrentFeatureChanged( int index );

private:
bool beforeDeleteFeature( QgsVectorLayer *referencingLayer, QgsFeatureId referencingFeatureId ) override;
void sortEntries() override;
Expand Down
30 changes: 22 additions & 8 deletions src/core/utils/featureutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ QString FeatureUtils::displayName( QgsVectorLayer *layer, const QgsFeature &feat
return name;
}

QgsRectangle FeatureUtils::extent( QgsQuickMapSettings *mapSettings, QgsVectorLayer *layer, const QgsFeature &feature )
QgsRectangle FeatureUtils::extent( QgsQuickMapSettings *mapSettings, QgsVectorLayer *layer, const QgsFeature &feature, const double &rightEdge, const double &bottomEdge )
{
if ( mapSettings && layer && layer->geometryType() != Qgis::GeometryType::Unknown && layer->geometryType() != Qgis::GeometryType::Null )
{
Expand All @@ -63,20 +63,34 @@ QgsRectangle FeatureUtils::extent( QgsQuickMapSettings *mapSettings, QgsVectorLa
geom.transform( transf );

QgsRectangle extent;
const double rightPercentage = rightEdge / mapSettings->outputSize().width();
const double bottomPercentage = bottomEdge / mapSettings->outputSize().height();
if ( geom.type() == Qgis::GeometryType::Point )
{
QgsVector delta = QgsPointXY( geom.asPoint() ) - mapSettings->extent().center();
extent = mapSettings->extent();
extent.setXMinimum( extent.xMinimum() + delta.x() );
extent.setXMaximum( extent.xMaximum() + delta.x() );
extent.setYMinimum( extent.yMinimum() + delta.y() );
extent.setYMaximum( extent.yMaximum() + delta.y() );
QgsVector delta = QgsPointXY( geom.asPoint() ) - extent.center();
const double deltaX = delta.x() + ( rightEdge > 0.0 ? mapSettings->mapUnitsPerPoint() * mapSettings->outputSize().width() * ( 0.5 - ( 1.0 - rightPercentage ) / 2.0 ) : 0.0 );
const double deltaY = delta.y() - ( bottomEdge > 0.0 ? mapSettings->mapUnitsPerPoint() * mapSettings->outputSize().height() * ( 0.5 - ( 1.0 - bottomPercentage ) / 2.0 ) : 0.0 );
extent.setXMinimum( extent.xMinimum() + deltaX );
extent.setXMaximum( extent.xMaximum() + deltaX );
extent.setYMinimum( extent.yMinimum() + deltaY );
extent.setYMaximum( extent.yMaximum() + deltaY );
}
else
{
QgsRectangle featureExtent = geom.boundingBox();
extent = featureExtent.buffered( std::max( featureExtent.width(), featureExtent.height() ) / 4.0 );
extent = geom.boundingBox();
extent = extent.buffered( std::max( extent.width(), extent.height() ) / 6.0 );

if ( rightEdge > 0.0 )
{
extent.setXMaximum( extent.xMaximum() + ( extent.xMaximum() - extent.xMinimum() ) * rightPercentage );
}
if ( bottomEdge > 0.0 )
{
extent.setYMinimum( extent.yMinimum() - ( extent.yMaximum() - extent.yMinimum() ) * bottomPercentage * 2 );
}
}

return extent;
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/core/utils/featureutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ class QFIELD_CORE_EXPORT FeatureUtils : public QObject
* \param mapSettings the map settings used to determine the CRS
* \param layer the vector layer containing the feature
* \param feature the feature from which the geometry will be used
* \param righeEdge provide a right edge beyond which the canvas is hidden and extent shouldn't overlap with
* \param bottomEdge provide a bottom edge beyond which the canvas is hidden and extent shouldn't overlap with
* \returns a QgsRectangle extent
*/
static Q_INVOKABLE QgsRectangle extent( QgsQuickMapSettings *mapSettings, QgsVectorLayer *layer, const QgsFeature &feature );
static Q_INVOKABLE QgsRectangle extent( QgsQuickMapSettings *mapSettings, QgsVectorLayer *layer, const QgsFeature &feature, const double &rightEdge = 0.0, const double &bottomEdge = 0.0 );
};

#endif // FEATUREUTILS_H
1 change: 1 addition & 0 deletions src/qml/FeatureListForm.qml
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ Rectangle {
model: globalFeaturesList.model
selection: featureForm.selection
mapSettings: featureForm.mapSettings
featureForm: featureForm

onFeatureFormStateRequested: {
featureForm.state = "FeatureForm"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ EditorWidgetBase {
orderedRelationModel.moveItems(indexFrom, indexTo)
} else if (listView.currentIndex !== dragArea.DelegateModel.itemsIndex) {
listView.currentIndex = dragArea.DelegateModel.itemsIndex
orderedRelationModel.viewCurrentFeatureChanged(listView.currentIndex)
orderedRelationModel.triggerViewCurrentFeatureChange(listView.currentIndex)
}
}

Expand All @@ -174,7 +174,9 @@ EditorWidgetBase {
locatorHighlightItem.geometryWrapper.crs = orderedRelationModel.relation.referencingLayer.crs
mapCanvas.mapSettings.extent = FeatureUtils.extent(mapCanvas.mapSettings,
orderedRelationModel.relation.referencingLayer,
nmRelationId ? model.nmReferencingFeature : model.referencingFeature)
nmRelationId ? model.nmReferencingFeature : model.referencingFeature,
featureForm.x,
featureForm.y)
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/qml/editorwidgets/relationeditors/relation_editor.qml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ EditorWidgetBase {
locatorHighlightItem.geometryWrapper.crs = relationEditorModel.relation.referencingLayer.crs
mapCanvas.mapSettings.extent = FeatureUtils.extent(mapCanvas.mapSettings,
relationEditorModel.relation.referencingLayer,
nmRelationId ? model.nmReferencingFeature : model.referencingFeature)
nmRelationId ? model.nmReferencingFeature : model.referencingFeature,
featureForm.x,
featureForm.y)
}
}
}
Expand Down

0 comments on commit f1ba257

Please sign in to comment.