mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Digitize the geometry from the relation reference widget add button (#30905)
* [FEATURE] [needs-docs] Add the possibility to digitize the geometry when creating a feature from the plus button on the relation reference widget
This commit is contained in:
parent
c1cce181b4
commit
3abbc0f178
@ -160,6 +160,13 @@ Determines if a button for adding new features should be shown.
|
||||
%Docstring
|
||||
Returns the current relation, which might be invalid
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
void setFormFeature( const QgsFeature &formFeature );
|
||||
%Docstring
|
||||
Set the current form feature (from the referencing layer)
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
|
@ -94,6 +94,32 @@ Returns the associated map canvas (e.g. to zoom to related features).
|
||||
.. seealso:: :py:func:`setMapCanvas`
|
||||
|
||||
.. versionadded:: 3.2
|
||||
%End
|
||||
|
||||
void setCadDockWidget( QgsAdvancedDigitizingDockWidget *cadDockWidget );
|
||||
%Docstring
|
||||
Sets the associated CAD dock widget, ``cadDockWidget``, (e.g. to be used in map tools).
|
||||
|
||||
.. note::
|
||||
|
||||
Unstable API. This method is unstable API and may be modified or removed at any time.
|
||||
|
||||
.. seealso:: :py:func:`cadDockWidget`
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
QgsAdvancedDigitizingDockWidget *cadDockWidget() const;
|
||||
%Docstring
|
||||
Returns the associated CAD dock widget (e.g. to be used in map tools).
|
||||
|
||||
.. note::
|
||||
|
||||
Unstable API. This method is unstable API and may be modified or removed at any time.
|
||||
|
||||
.. seealso:: :py:func:`setCadDockWidget`
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
void setVectorLayerTools( QgsVectorLayerTools *vlTools );
|
||||
@ -234,7 +260,6 @@ Returns given ``attributeFormMode`` as string
|
||||
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
|
89
python/gui/auto_generated/qgsmaptooldigitizefeature.sip.in
Normal file
89
python/gui/auto_generated/qgsmaptooldigitizefeature.sip.in
Normal file
@ -0,0 +1,89 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgsmaptooldigitizefeature.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
class QgsMapToolDigitizeFeature : QgsMapToolCapture
|
||||
{
|
||||
%Docstring
|
||||
This tool digitizes geometry of new point/line/polygon features on already existing vector layers
|
||||
Once the map tool is enabled, user can digitize the feature geometry.
|
||||
A signal will then be emitted.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsmaptooldigitizefeature.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsMapToolDigitizeFeature( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget, CaptureMode mode = QgsMapToolCapture::CaptureNone );
|
||||
%Docstring
|
||||
QgsMapToolDigitizeFeature is a map tool to digitize a feature geometry
|
||||
|
||||
:param canvas: the map canvas
|
||||
:param cadDockWidget: widget to setup advanced digitizing parameters
|
||||
:param mode: type of geometry to capture (point/line/polygon), QgsMapToolCapture.CaptureNone to autodetect geometry
|
||||
%End
|
||||
|
||||
virtual void cadCanvasReleaseEvent( QgsMapMouseEvent *e );
|
||||
|
||||
|
||||
void setLayer( QgsMapLayer *vl );
|
||||
%Docstring
|
||||
Change the layer edited by the map tool
|
||||
|
||||
:param vl: the layer to be edited by the map tool
|
||||
%End
|
||||
|
||||
virtual void activate();
|
||||
|
||||
virtual void deactivate();
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
void digitizingCompleted( const QgsFeature &feature );
|
||||
%Docstring
|
||||
Emitted whenever the digitizing has been successfully completed
|
||||
|
||||
:param feature: the new digitized feature
|
||||
%End
|
||||
|
||||
void digitizingFinished( );
|
||||
%Docstring
|
||||
Emitted whenever the digitizing has been ended without digitizing
|
||||
any feature
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
bool checkGeometryType() const;
|
||||
%Docstring
|
||||
Check if CaptureMode matches layer type. Default is true.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
void setCheckGeometryType( bool checkGeometryType );
|
||||
%Docstring
|
||||
Check if CaptureMode matches layer type. Default is true.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgsmaptooldigitizefeature.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -155,6 +155,7 @@
|
||||
%Include auto_generated/qgsmaptooladvanceddigitizing.sip
|
||||
%Include auto_generated/qgsmaptoolcapture.sip
|
||||
%Include auto_generated/qgsmaptooledit.sip
|
||||
%Include auto_generated/qgsmaptooldigitizefeature.sip
|
||||
%Include auto_generated/qgsmaptoolemitpoint.sip
|
||||
%Include auto_generated/qgsmaptoolextent.sip
|
||||
%Include auto_generated/qgsmaptoolidentify.sip
|
||||
|
@ -82,7 +82,6 @@ SET(QGIS_APP_SRCS
|
||||
qgswelcomepage.cpp
|
||||
|
||||
qgsmaptooladdfeature.cpp
|
||||
qgsmaptooldigitizefeature.cpp
|
||||
qgsmaptooladdpart.cpp
|
||||
qgsmaptooladdring.cpp
|
||||
qgsmaptoolfillring.cpp
|
||||
@ -327,7 +326,6 @@ SET (QGIS_APP_MOC_HDRS
|
||||
qgswelcomepage.h
|
||||
|
||||
qgsmaptooladdfeature.h
|
||||
qgsmaptooldigitizefeature.h
|
||||
qgsmaptoolannotation.h
|
||||
qgsmaptoolcircularstringradius.h
|
||||
qgsmaptooladdpart.h
|
||||
|
@ -14672,7 +14672,8 @@ QgsFeature QgisApp::duplicateFeatureDigitized( QgsMapLayer *mlayer, const QgsFea
|
||||
return QgsFeature();
|
||||
}
|
||||
|
||||
QgsMapToolDigitizeFeature *digitizeFeature = new QgsMapToolDigitizeFeature( mMapCanvas, mlayer, QgsMapToolCapture::CaptureNone );
|
||||
QgsMapToolDigitizeFeature *digitizeFeature = new QgsMapToolDigitizeFeature( mMapCanvas, mAdvancedDigitizingDockWidget, QgsMapToolCapture::CaptureNone );
|
||||
digitizeFeature->setLayer( layer );
|
||||
|
||||
mMapCanvas->setMapTool( digitizeFeature );
|
||||
mMapCanvas->window()->raise();
|
||||
|
@ -158,6 +158,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
|
||||
|
||||
mEditorContext.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() );
|
||||
mEditorContext.setMapCanvas( QgisApp::instance()->mapCanvas() );
|
||||
mEditorContext.setCadDockWidget( QgisApp::instance()->cadDockWidget() );
|
||||
|
||||
QgsFeatureRequest r;
|
||||
bool needsGeom = false;
|
||||
|
@ -37,18 +37,21 @@
|
||||
#include <QSettings>
|
||||
|
||||
QgsMapToolAddFeature::QgsMapToolAddFeature( QgsMapCanvas *canvas, CaptureMode mode )
|
||||
: QgsMapToolDigitizeFeature( canvas, canvas->currentLayer(), mode )
|
||||
: QgsMapToolDigitizeFeature( canvas, QgisApp::instance()->cadDockWidget(), mode )
|
||||
, mCheckGeometryType( true )
|
||||
{
|
||||
setLayer( canvas->currentLayer() );
|
||||
|
||||
mToolName = tr( "Add feature" );
|
||||
connect( QgisApp::instance(), &QgisApp::newProject, this, &QgsMapToolAddFeature::stopCapturing );
|
||||
connect( QgisApp::instance(), &QgisApp::projectRead, this, &QgsMapToolAddFeature::stopCapturing );
|
||||
}
|
||||
|
||||
bool QgsMapToolAddFeature::addFeature( QgsVectorLayer *vlayer, QgsFeature *f, bool showModal )
|
||||
bool QgsMapToolAddFeature::addFeature( QgsVectorLayer *vlayer, const QgsFeature &f, bool showModal )
|
||||
{
|
||||
QgsFeature feat( f );
|
||||
QgsExpressionContextScope *scope = QgsExpressionContextUtils::mapToolCaptureScope( snappingMatches() );
|
||||
QgsFeatureAction *action = new QgsFeatureAction( tr( "add feature" ), *f, vlayer, QString(), -1, this );
|
||||
QgsFeatureAction *action = new QgsFeatureAction( tr( "add feature" ), feat, vlayer, QString(), -1, this );
|
||||
QgsRubberBand *rb = takeRubberBand();
|
||||
connect( action, &QgsFeatureAction::addFeatureFinished, rb, &QgsRubberBand::deleteLater );
|
||||
bool res = action->addFeature( QgsAttributeMap(), showModal, scope );
|
||||
@ -57,10 +60,10 @@ bool QgsMapToolAddFeature::addFeature( QgsVectorLayer *vlayer, QgsFeature *f, bo
|
||||
return res;
|
||||
}
|
||||
|
||||
void QgsMapToolAddFeature::digitized( QgsFeature &f )
|
||||
void QgsMapToolAddFeature::digitized( const QgsFeature &f )
|
||||
{
|
||||
QgsVectorLayer *vlayer = currentVectorLayer();
|
||||
bool res = addFeature( vlayer, &f, false );
|
||||
bool res = addFeature( vlayer, f, false );
|
||||
|
||||
if ( res && ( mode() == CaptureLine || mode() == CapturePolygon ) )
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsmaptooldigitizefeature.h"
|
||||
#include "qgis_app.h"
|
||||
|
||||
//! This tool adds new point/line/polygon features to already existing vector layers
|
||||
class APP_EXPORT QgsMapToolAddFeature : public QgsMapToolDigitizeFeature
|
||||
@ -23,12 +24,12 @@ class APP_EXPORT QgsMapToolAddFeature : public QgsMapToolDigitizeFeature
|
||||
//! \since QGIS 2.12
|
||||
QgsMapToolAddFeature( QgsMapCanvas *canvas, CaptureMode mode );
|
||||
|
||||
bool addFeature( QgsVectorLayer *vlayer, QgsFeature *f, bool showModal = true );
|
||||
|
||||
void digitized( QgsFeature &f ) override;
|
||||
|
||||
private:
|
||||
|
||||
bool addFeature( QgsVectorLayer *vlayer, const QgsFeature &f, bool showModal = true );
|
||||
|
||||
void digitized( const QgsFeature &f ) override;
|
||||
|
||||
/**
|
||||
* Check if CaptureMode matches layer type. Default is true.
|
||||
* \since QGIS 2.12 */
|
||||
|
@ -234,6 +234,7 @@ SET(QGIS_GUI_SRCS
|
||||
qgsaggregatetoolbutton.cpp
|
||||
qgsalignmentcombobox.cpp
|
||||
qgsattributedialog.cpp
|
||||
qgsattributeeditorcontext.cpp
|
||||
qgsattributeform.cpp
|
||||
qgsattributeformeditorwidget.cpp
|
||||
qgsattributeforminterface.cpp
|
||||
@ -337,6 +338,7 @@ SET(QGIS_GUI_SRCS
|
||||
qgsmaptooladvanceddigitizing.cpp
|
||||
qgsmaptoolcapture.cpp
|
||||
qgsmaptooledit.cpp
|
||||
qgsmaptooldigitizefeature.cpp
|
||||
qgsmaptoolemitpoint.cpp
|
||||
qgsmaptoolextent.cpp
|
||||
qgsmaptoolidentify.cpp
|
||||
@ -522,6 +524,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
qgsmaptooladvanceddigitizing.h
|
||||
qgsmaptoolcapture.h
|
||||
qgsmaptooledit.h
|
||||
qgsmaptooldigitizefeature.h
|
||||
qgsmaptoolemitpoint.h
|
||||
qgsmaptoolextent.h
|
||||
qgsmaptoolidentify.h
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsattributetablemodel.h"
|
||||
#include "qgsmaptoolidentifyfeature.h"
|
||||
#include "qgsmaptooldigitizefeature.h"
|
||||
#include "qgsfeatureiterator.h"
|
||||
#include "qgsfeaturelistcombobox.h"
|
||||
#include "qgsexpressioncontextutils.h"
|
||||
@ -169,7 +170,6 @@ QgsRelationReferenceWidget::~QgsRelationReferenceWidget()
|
||||
{
|
||||
deleteHighlight();
|
||||
unsetMapTool();
|
||||
delete mMapTool;
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidget::updateIndex()
|
||||
@ -254,7 +254,9 @@ void QgsRelationReferenceWidget::setRelation( const QgsRelation &relation, bool
|
||||
void QgsRelationReferenceWidget::setRelationEditable( bool editable )
|
||||
{
|
||||
if ( !editable )
|
||||
{
|
||||
unsetMapTool();
|
||||
}
|
||||
|
||||
mFilterContainer->setEnabled( editable );
|
||||
mComboBox->setEnabled( editable );
|
||||
@ -452,9 +454,11 @@ void QgsRelationReferenceWidget::setEditorContext( const QgsAttributeEditorConte
|
||||
mCanvas = canvas;
|
||||
mMessageBar = messageBar;
|
||||
|
||||
delete mMapTool;
|
||||
mMapTool = new QgsMapToolIdentifyFeature( mCanvas );
|
||||
mMapTool->setButton( mMapIdentificationButton );
|
||||
mMapToolIdentify.reset( new QgsMapToolIdentifyFeature( mCanvas ) );
|
||||
mMapToolIdentify->setButton( mMapIdentificationButton );
|
||||
|
||||
mMapToolDigitize.reset( new QgsMapToolDigitizeFeature( mCanvas, context.cadDockWidget() ) );
|
||||
mMapToolDigitize->setButton( mAddEntryButton );
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidget::setEmbedForm( bool display )
|
||||
@ -717,17 +721,10 @@ void QgsRelationReferenceWidget::mapIdentification()
|
||||
if ( !mCanvas )
|
||||
return;
|
||||
|
||||
mMapTool->setLayer( mReferencedLayer );
|
||||
mCanvas->setMapTool( mMapTool );
|
||||
mMapToolIdentify->setLayer( mReferencedLayer );
|
||||
setMapTool( mMapToolIdentify );
|
||||
|
||||
mWindowWidget = window();
|
||||
|
||||
mCanvas->window()->raise();
|
||||
mCanvas->activateWindow();
|
||||
mCanvas->setFocus();
|
||||
|
||||
connect( mMapTool, static_cast<void ( QgsMapToolIdentifyFeature::* )( const QgsFeature & )>( &QgsMapToolIdentifyFeature::featureIdentified ), this, &QgsRelationReferenceWidget::featureIdentified );
|
||||
connect( mMapTool, &QgsMapTool::deactivated, this, &QgsRelationReferenceWidget::mapToolDeactivated );
|
||||
connect( mMapToolIdentify, qgis::overload<const QgsFeature &>::of( &QgsMapToolIdentifyFeature::featureIdentified ), this, &QgsRelationReferenceWidget::featureIdentified );
|
||||
|
||||
if ( mMessageBar )
|
||||
{
|
||||
@ -809,13 +806,44 @@ void QgsRelationReferenceWidget::featureIdentified( const QgsFeature &feature )
|
||||
unsetMapTool();
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidget::setMapTool( QgsMapTool *mapTool )
|
||||
{
|
||||
mCurrentMapTool = mapTool;
|
||||
mCanvas->setMapTool( mapTool );
|
||||
|
||||
mWindowWidget = window();
|
||||
|
||||
mCanvas->window()->raise();
|
||||
mCanvas->activateWindow();
|
||||
mCanvas->setFocus();
|
||||
connect( mapTool, &QgsMapTool::deactivated, this, &QgsRelationReferenceWidget::mapToolDeactivated );
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidget::unsetMapTool()
|
||||
{
|
||||
// deactivate map tool if activated
|
||||
if ( mCanvas && mMapTool )
|
||||
// deactivate map tools if activated
|
||||
if ( mCurrentMapTool )
|
||||
{
|
||||
/* this will call mapToolDeactivated */
|
||||
mCanvas->unsetMapTool( mMapTool );
|
||||
mCanvas->unsetMapTool( mCurrentMapTool );
|
||||
|
||||
if ( mCurrentMapTool == mMapToolDigitize )
|
||||
{
|
||||
disconnect( mCanvas, &QgsMapCanvas::keyPressed, this, &QgsRelationReferenceWidget::onKeyPressed );
|
||||
disconnect( mMapToolDigitize, &QgsMapToolDigitizeFeature::digitizingCompleted, this, &QgsRelationReferenceWidget::entryAdded );
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect( mMapToolIdentify, qgis::overload<const QgsFeature &>::of( &QgsMapToolIdentifyFeature::featureIdentified ), this, &QgsRelationReferenceWidget::featureIdentified );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidget::onKeyPressed( QKeyEvent *e )
|
||||
{
|
||||
if ( e->key() == Qt::Key_Escape )
|
||||
{
|
||||
unsetMapTool();
|
||||
}
|
||||
}
|
||||
|
||||
@ -940,7 +968,53 @@ void QgsRelationReferenceWidget::filterChanged()
|
||||
|
||||
void QgsRelationReferenceWidget::addEntry()
|
||||
{
|
||||
QgsFeature f( mReferencedLayer->fields() );
|
||||
if ( !mReferencedLayer )
|
||||
return;
|
||||
|
||||
const QgsVectorLayerTools *tools = mEditorContext.vectorLayerTools();
|
||||
if ( !tools )
|
||||
return;
|
||||
if ( !mCanvas )
|
||||
return;
|
||||
|
||||
// no geometry, skip the digitizing
|
||||
if ( mReferencedLayer->geometryType() == QgsWkbTypes::UnknownGeometry || mReferencedLayer->geometryType() == QgsWkbTypes::NullGeometry )
|
||||
{
|
||||
QgsFeature f( mReferencedLayer->fields() );
|
||||
entryAdded( f );
|
||||
return;
|
||||
}
|
||||
|
||||
mMapToolDigitize->setLayer( mReferencedLayer );
|
||||
setMapTool( mMapToolDigitize );
|
||||
|
||||
connect( mMapToolDigitize, &QgsMapToolDigitizeFeature::digitizingCompleted, this, &QgsRelationReferenceWidget::entryAdded );
|
||||
connect( mCanvas, &QgsMapCanvas::keyPressed, this, &QgsRelationReferenceWidget::onKeyPressed );
|
||||
|
||||
if ( mMessageBar )
|
||||
{
|
||||
QString title = tr( "Relation %1 for %2." ).arg( mRelation.name(), mReferencingLayer->name() );
|
||||
|
||||
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mReferencingLayer ) );
|
||||
if ( mCanvas )
|
||||
context.appendScope( QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() ) );
|
||||
|
||||
QgsExpression exp( mReferencingLayer->displayExpression() );
|
||||
context.setFeature( mFormFeature );
|
||||
exp.prepare( &context );
|
||||
QString displayString = exp.evaluate( &context ).toString();
|
||||
|
||||
QString msg = tr( "Link feature to %1 \"%2\" : Digitize the geometry for the new feature on layer %3. Press <ESC> to cancel." )
|
||||
.arg( mReferencingLayer->name(), displayString, mReferencedLayer->name() );
|
||||
mMessageBarItem = QgsMessageBar::createMessage( title, msg, this );
|
||||
mMessageBar->pushItem( mMessageBarItem );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidget::entryAdded( const QgsFeature &feat )
|
||||
{
|
||||
QgsFeature f( feat );
|
||||
QgsAttributeMap attributes;
|
||||
|
||||
// if custom text is in the combobox and the displayExpression is simply a field, use the current text for the new feature
|
||||
@ -954,7 +1028,7 @@ void QgsRelationReferenceWidget::addEntry()
|
||||
}
|
||||
}
|
||||
|
||||
if ( mEditorContext.vectorLayerTools()->addFeature( mReferencedLayer, attributes, QgsGeometry(), &f ) )
|
||||
if ( mEditorContext.vectorLayerTools()->addFeature( mReferencedLayer, attributes, f.geometry(), &f ) )
|
||||
{
|
||||
QVariantList attrs;
|
||||
for ( const QString &fieldName : qgis::as_const( mReferencedFields ) )
|
||||
@ -964,6 +1038,8 @@ void QgsRelationReferenceWidget::addEntry()
|
||||
|
||||
mAddEntryButton->setEnabled( false );
|
||||
}
|
||||
|
||||
unsetMapTool();
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidget::updateAddEntryButton()
|
||||
@ -1009,3 +1085,8 @@ void QgsRelationReferenceWidget::emitForeignKeysChanged( const QVariantList &for
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
emit foreignKeysChanged( foreignKeys );
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidget::setFormFeature( const QgsFeature &formFeature )
|
||||
{
|
||||
mFormFeature = formFeature;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "qgsattributeeditorcontext.h"
|
||||
#include "qgis_sip.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qobjectuniqueptr.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QToolButton>
|
||||
@ -32,7 +33,9 @@ class QgsVectorLayerTools;
|
||||
class QgsMapCanvas;
|
||||
class QgsMessageBar;
|
||||
class QgsHighlight;
|
||||
class QgsMapTool;
|
||||
class QgsMapToolIdentifyFeature;
|
||||
class QgsMapToolDigitizeFeature;
|
||||
class QgsMessageBarItem;
|
||||
class QgsFeatureListComboBox;
|
||||
class QgsCollapsibleGroupBox;
|
||||
@ -181,6 +184,13 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
|
||||
*/
|
||||
QgsRelation relation() const;
|
||||
|
||||
/**
|
||||
* Set the current form feature (from the referencing layer)
|
||||
*
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
void setFormFeature( const QgsFeature &formFeature );
|
||||
|
||||
public slots:
|
||||
//! open the form of the related feature in a new dialog
|
||||
void openForm();
|
||||
@ -215,11 +225,14 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
|
||||
void deleteHighlight();
|
||||
void comboReferenceChanged( int index );
|
||||
void featureIdentified( const QgsFeature &feature );
|
||||
void setMapTool( QgsMapTool *mapTool );
|
||||
void unsetMapTool();
|
||||
void mapToolDeactivated();
|
||||
void filterChanged();
|
||||
void addEntry();
|
||||
void updateAddEntryButton();
|
||||
void entryAdded( const QgsFeature &f );
|
||||
void onKeyPressed( QKeyEvent *e );
|
||||
|
||||
/**
|
||||
* Updates the FK index as soon as the underlying model is updated when
|
||||
@ -239,11 +252,14 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
|
||||
QgsMessageBar *mMessageBar = nullptr;
|
||||
QVariantList mForeignKeys;
|
||||
QgsFeature mFeature;
|
||||
QgsFeature mFormFeature;
|
||||
// Index of the referenced layer key
|
||||
QStringList mReferencedFields;
|
||||
bool mAllowNull = true;
|
||||
QgsHighlight *mHighlight = nullptr;
|
||||
QgsMapToolIdentifyFeature *mMapTool = nullptr;
|
||||
QgsMapTool *mCurrentMapTool = nullptr;
|
||||
QObjectUniquePtr<QgsMapToolIdentifyFeature> mMapToolIdentify;
|
||||
QObjectUniquePtr<QgsMapToolDigitizeFeature> mMapToolDigitize;
|
||||
QgsMessageBarItem *mMessageBarItem = nullptr;
|
||||
QgsAttributeForm *mReferencedAttributeForm = nullptr;
|
||||
QgsVectorLayer *mReferencedLayer = nullptr;
|
||||
|
@ -196,6 +196,7 @@ void QgsRelationReferenceWidgetWrapper::updateValues( const QVariant &val, const
|
||||
Q_ASSERT( values.count() == fieldPairs.count() );
|
||||
|
||||
mWidget->setForeignKeys( values );
|
||||
mWidget->setFormFeature( formFeature() );
|
||||
}
|
||||
|
||||
void QgsRelationReferenceWidgetWrapper::setEnabled( bool enabled )
|
||||
|
21
src/gui/qgsattributeeditorcontext.cpp
Normal file
21
src/gui/qgsattributeeditorcontext.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
/***************************************************************************
|
||||
qgsattributeeditorcontext.cpp
|
||||
--------------------------------------
|
||||
Date : 19.8.2019
|
||||
Copyright : (C) 201 Julien Cabieces
|
||||
Email : julien dot cabieces at oslandia dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsattributeeditorcontext.h"
|
||||
|
||||
void QgsAttributeEditorContext::setCadDockWidget( QgsAdvancedDigitizingDockWidget *cadDockWidget )
|
||||
{
|
||||
mCadDockWidget = cadDockWidget;
|
||||
}
|
@ -27,6 +27,7 @@
|
||||
#include "qgsproject.h"
|
||||
|
||||
class QgsMapCanvas;
|
||||
class QgsAdvancedDigitizingDockWidget;
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
@ -132,6 +133,22 @@ class GUI_EXPORT QgsAttributeEditorContext
|
||||
*/
|
||||
inline QgsMapCanvas *mapCanvas() const { return mMapCanvas; }
|
||||
|
||||
/**
|
||||
* Sets the associated CAD dock widget, \a cadDockWidget, (e.g. to be used in map tools).
|
||||
* \note Unstable API. This method is unstable API and may be modified or removed at any time.
|
||||
* \see cadDockWidget()
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
void setCadDockWidget( QgsAdvancedDigitizingDockWidget *cadDockWidget );
|
||||
|
||||
/**
|
||||
* Returns the associated CAD dock widget (e.g. to be used in map tools).
|
||||
* \note Unstable API. This method is unstable API and may be modified or removed at any time.
|
||||
* \see setCadDockWidget()
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
QgsAdvancedDigitizingDockWidget *cadDockWidget() const { return mCadDockWidget; }
|
||||
|
||||
/**
|
||||
* Sets the associated vector layer tools.
|
||||
* \param vlTools vector layer tools
|
||||
@ -247,6 +264,7 @@ class GUI_EXPORT QgsAttributeEditorContext
|
||||
QgsVectorLayer *mLayer = nullptr;
|
||||
QgsVectorLayerTools *mVectorLayerTools = nullptr;
|
||||
QgsMapCanvas *mMapCanvas = nullptr;
|
||||
QgsAdvancedDigitizingDockWidget *mCadDockWidget = nullptr;
|
||||
QgsDistanceArea mDistanceArea;
|
||||
QgsRelation mRelation;
|
||||
RelationMode mRelationMode = Undefined;
|
||||
@ -258,4 +276,3 @@ class GUI_EXPORT QgsAttributeEditorContext
|
||||
};
|
||||
|
||||
#endif // QGSATTRIBUTEEDITORCONTEXT_H
|
||||
|
||||
|
@ -31,22 +31,19 @@
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsfeatureaction.h"
|
||||
#include "qgisapp.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
QgsMapToolDigitizeFeature::QgsMapToolDigitizeFeature( QgsMapCanvas *canvas, QgsMapLayer *layer, CaptureMode mode )
|
||||
: QgsMapToolCapture( canvas, QgisApp::instance()->cadDockWidget(), mode )
|
||||
QgsMapToolDigitizeFeature::QgsMapToolDigitizeFeature( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget, CaptureMode mode )
|
||||
: QgsMapToolCapture( canvas, cadDockWidget, mode )
|
||||
, mCheckGeometryType( true )
|
||||
{
|
||||
mLayer = layer;
|
||||
mToolName = tr( "Digitize feature" );
|
||||
connect( QgisApp::instance(), &QgisApp::newProject, this, &QgsMapToolDigitizeFeature::stopCapturing );
|
||||
connect( QgisApp::instance(), &QgisApp::projectRead, this, &QgsMapToolDigitizeFeature::stopCapturing );
|
||||
connect( QgsProject::instance(), &QgsProject::cleared, this, &QgsMapToolDigitizeFeature::stopCapturing );
|
||||
connect( QgsProject::instance(), &QgsProject::readProject, this, &QgsMapToolDigitizeFeature::stopCapturing );
|
||||
}
|
||||
|
||||
void QgsMapToolDigitizeFeature::digitized( QgsFeature &f )
|
||||
void QgsMapToolDigitizeFeature::digitized( const QgsFeature &f )
|
||||
{
|
||||
emit digitizingCompleted( f );
|
||||
}
|
||||
@ -344,3 +341,8 @@ void QgsMapToolDigitizeFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolDigitizeFeature::setLayer( QgsMapLayer *vl )
|
||||
{
|
||||
mLayer = vl;
|
||||
}
|
@ -17,27 +17,54 @@
|
||||
#define QGSMAPTOOLDIGITIZEFEATURE_H
|
||||
|
||||
#include "qgsmaptoolcapture.h"
|
||||
#include "qgis_app.h"
|
||||
#include "qgis_gui.h"
|
||||
|
||||
class QgsFeature;
|
||||
|
||||
//! This tool digitizes geometry of new point/line/polygon features on already existing vector layers
|
||||
class APP_EXPORT QgsMapToolDigitizeFeature : public QgsMapToolCapture
|
||||
/**
|
||||
* \ingroup gui
|
||||
* \brief This tool digitizes geometry of new point/line/polygon features on already existing vector layers
|
||||
* Once the map tool is enabled, user can digitize the feature geometry.
|
||||
* A signal will then be emitted.
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
class GUI_EXPORT QgsMapToolDigitizeFeature : public QgsMapToolCapture
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! \since QGIS 3.2
|
||||
QgsMapToolDigitizeFeature( QgsMapCanvas *canvas, QgsMapLayer *layer, CaptureMode mode );
|
||||
|
||||
/**
|
||||
* \brief QgsMapToolDigitizeFeature is a map tool to digitize a feature geometry
|
||||
* \param canvas the map canvas
|
||||
* \param cadDockWidget widget to setup advanced digitizing parameters
|
||||
* \param mode type of geometry to capture (point/line/polygon), QgsMapToolCapture::CaptureNone to autodetect geometry
|
||||
*/
|
||||
QgsMapToolDigitizeFeature( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget, CaptureMode mode = QgsMapToolCapture::CaptureNone );
|
||||
|
||||
void cadCanvasReleaseEvent( QgsMapMouseEvent *e ) override;
|
||||
|
||||
virtual void digitized( QgsFeature &f );
|
||||
/**
|
||||
* Change the layer edited by the map tool
|
||||
* \param vl the layer to be edited by the map tool
|
||||
*/
|
||||
void setLayer( QgsMapLayer *vl );
|
||||
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
signals:
|
||||
void digitizingCompleted( const QgsFeature & );
|
||||
|
||||
/**
|
||||
* Emitted whenever the digitizing has been successfully completed
|
||||
* \param feature the new digitized feature
|
||||
*/
|
||||
void digitizingCompleted( const QgsFeature &feature );
|
||||
|
||||
/**
|
||||
* Emitted whenever the digitizing has been ended without digitizing
|
||||
* any feature
|
||||
*/
|
||||
void digitizingFinished( );
|
||||
|
||||
protected:
|
||||
@ -56,6 +83,12 @@ class APP_EXPORT QgsMapToolDigitizeFeature : public QgsMapToolCapture
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Called when the feature has been digitized.
|
||||
* \param f the new created feature
|
||||
*/
|
||||
virtual void digitized( const QgsFeature &f );
|
||||
|
||||
/**
|
||||
* individual layer per digitizing session
|
||||
* \since QGIS 3.0 */
|
||||
@ -70,6 +103,8 @@ class APP_EXPORT QgsMapToolDigitizeFeature : public QgsMapToolCapture
|
||||
* Check if CaptureMode matches layer type. Default is true.
|
||||
* \since QGIS 2.12 */
|
||||
bool mCheckGeometryType;
|
||||
|
||||
friend class TestQgsRelationReferenceWidget;
|
||||
};
|
||||
|
||||
#endif // QGSMAPTOOLDIGITIZEFEATURE_H
|
@ -88,7 +88,7 @@ QgsRubberBand *QgsMapToolEdit::createRubberBand( QgsWkbTypes::GeometryType geome
|
||||
|
||||
QgsVectorLayer *QgsMapToolEdit::currentVectorLayer()
|
||||
{
|
||||
return qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
|
||||
return mCanvas ? qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ) : nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "qgsgui.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsvectorlayertools.h"
|
||||
#include "qgsadvanceddigitizingdockwidget.h"
|
||||
#include "qgsmaptooldigitizefeature.h"
|
||||
|
||||
class TestQgsRelationReferenceWidget : public QObject
|
||||
{
|
||||
@ -50,6 +52,7 @@ class TestQgsRelationReferenceWidget : public QObject
|
||||
void testSetGetForeignKey();
|
||||
void testIdentifyOnMap();
|
||||
void testAddEntry();
|
||||
void testAddEntryNoGeom();
|
||||
|
||||
private:
|
||||
std::unique_ptr<QgsVectorLayer> mLayer1;
|
||||
@ -376,50 +379,98 @@ void TestQgsRelationReferenceWidget::testIdentifyOnMap()
|
||||
mLayer1->rollBack();
|
||||
}
|
||||
|
||||
// Monkey patch gui vector layer tool in order to simple add a new feature in
|
||||
// referenced layer
|
||||
class DummyVectorLayerTools : public QgsVectorLayerTools
|
||||
{
|
||||
bool addFeature( QgsVectorLayer *layer, const QgsAttributeMap &, const QgsGeometry &, QgsFeature *feat = nullptr ) const override
|
||||
{
|
||||
feat->setAttribute( QStringLiteral( "pk" ), 13 );
|
||||
feat->setAttribute( QStringLiteral( "material" ), QStringLiteral( "steel" ) );
|
||||
feat->setAttribute( QStringLiteral( "diameter" ), 140 );
|
||||
feat->setAttribute( QStringLiteral( "raccord" ), "collar" );
|
||||
layer->addFeature( *feat );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool startEditing( QgsVectorLayer * ) const override {return true;}
|
||||
|
||||
bool stopEditing( QgsVectorLayer *, bool = true ) const override {return true;};
|
||||
|
||||
bool saveEdits( QgsVectorLayer * ) const override {return true;};
|
||||
};
|
||||
|
||||
void TestQgsRelationReferenceWidget::testAddEntry()
|
||||
{
|
||||
// check that a new added entry in referenced layer populate correctly the
|
||||
// referencing combobox
|
||||
QWidget parentWidget;
|
||||
QgsRelationReferenceWidget w( &parentWidget );
|
||||
QgsMapCanvas canvas;
|
||||
QgsRelationReferenceWidget w( &canvas );
|
||||
QVERIFY( mLayer1->startEditing() );
|
||||
w.setRelation( *mRelation, true );
|
||||
w.init();
|
||||
|
||||
// Monkey patch gui vector layer tool in order to simple add a new feature in
|
||||
// referenced layer
|
||||
class DummyVectorLayerTools : public QgsVectorLayerTools
|
||||
{
|
||||
bool addFeature( QgsVectorLayer *layer, const QgsAttributeMap &, const QgsGeometry &, QgsFeature *feat = nullptr ) const override
|
||||
{
|
||||
feat->setAttribute( QStringLiteral( "pk" ), 13 );
|
||||
feat->setAttribute( QStringLiteral( "material" ), "steel" );
|
||||
feat->setAttribute( QStringLiteral( "diameter" ), 140 );
|
||||
feat->setAttribute( QStringLiteral( "raccord" ), "collar" );
|
||||
layer->addFeature( *feat );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool startEditing( QgsVectorLayer * ) const override {return true;}
|
||||
|
||||
bool stopEditing( QgsVectorLayer *, bool = true ) const override {return true;}
|
||||
|
||||
bool saveEdits( QgsVectorLayer * ) const override {return true;}
|
||||
};
|
||||
|
||||
QgsAdvancedDigitizingDockWidget cadDockWidget( &canvas );
|
||||
QgsAttributeEditorContext context;
|
||||
DummyVectorLayerTools tools;
|
||||
context.setVectorLayerTools( &tools );
|
||||
w.setEditorContext( context, nullptr, nullptr );
|
||||
context.setCadDockWidget( &cadDockWidget );
|
||||
w.setEditorContext( context, &canvas, nullptr );
|
||||
w.addEntry();
|
||||
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
QCOMPARE( w.mComboBox->identifierValue().toInt(), 13 );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
QVERIFY( w.mCurrentMapTool );
|
||||
QgsFeature feat( mLayer1->fields() );
|
||||
w.mMapToolDigitize->digitized( feat );
|
||||
|
||||
QCOMPARE( w.mComboBox->identifierValues().at( 0 ).toInt(), 13 );
|
||||
}
|
||||
|
||||
void TestQgsRelationReferenceWidget::testAddEntryNoGeom()
|
||||
{
|
||||
QgsVectorLayer mLayer1( QStringLiteral( "Point?crs=epsg:3111&field=pk:int&field=fk:int" ), QStringLiteral( "vl1" ), QStringLiteral( "memory" ) );
|
||||
QgsProject::instance()->addMapLayer( &mLayer1, false, false );
|
||||
|
||||
QgsVectorLayer mLayer2( QStringLiteral( "None?field=pk:int&field=material:string" ), QStringLiteral( "vl2" ), QStringLiteral( "memory" ) );
|
||||
QgsProject::instance()->addMapLayer( &mLayer2, false, false );
|
||||
|
||||
// create relation
|
||||
QgsRelation mRelation;
|
||||
mRelation.setId( QStringLiteral( "vl1.vl2" ) );
|
||||
mRelation.setName( QStringLiteral( "vl1.vl2" ) );
|
||||
mRelation.setReferencingLayer( mLayer1.id() );
|
||||
mRelation.setReferencedLayer( mLayer2.id() );
|
||||
mRelation.addFieldPair( QStringLiteral( "fk" ), QStringLiteral( "pk" ) );
|
||||
QVERIFY( mRelation.isValid() );
|
||||
QgsProject::instance()->relationManager()->addRelation( mRelation );
|
||||
|
||||
// add feature
|
||||
QgsFeature ft0( mLayer1.fields() );
|
||||
ft0.setAttribute( QStringLiteral( "pk" ), 0 );
|
||||
ft0.setAttribute( QStringLiteral( "fk" ), 0 );
|
||||
mLayer1.startEditing();
|
||||
mLayer1.addFeature( ft0 );
|
||||
mLayer1.commitChanges();
|
||||
|
||||
// check that a new added entry in referenced layer populate correctly the
|
||||
// referencing combobox
|
||||
QgsMapCanvas canvas;
|
||||
QgsRelationReferenceWidget w( &canvas );
|
||||
QVERIFY( mLayer1.startEditing() );
|
||||
w.setRelation( mRelation, true );
|
||||
w.init();
|
||||
|
||||
QgsAdvancedDigitizingDockWidget cadDockWidget( &canvas );
|
||||
QgsAttributeEditorContext context;
|
||||
DummyVectorLayerTools tools;
|
||||
context.setVectorLayerTools( &tools );
|
||||
context.setCadDockWidget( &cadDockWidget );
|
||||
w.setEditorContext( context, &canvas, nullptr );
|
||||
w.addEntry();
|
||||
|
||||
QVERIFY( !w.mCurrentMapTool );
|
||||
|
||||
QCOMPARE( w.mComboBox->identifierValues().at( 0 ).toInt(), 13 );
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsRelationReferenceWidget )
|
||||
#include "testqgsrelationreferencewidget.moc"
|
||||
|
@ -28,6 +28,7 @@ from qgis.gui import (
|
||||
QgsAttributeForm,
|
||||
QgsGui,
|
||||
QgsEditorWidgetWrapper,
|
||||
QgsMapCanvas
|
||||
)
|
||||
|
||||
|
||||
@ -38,7 +39,8 @@ class TestQgsAttributeForm(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
QgsGui.editorWidgetRegistry().initEditors()
|
||||
cls.mCanvas = QgsMapCanvas()
|
||||
QgsGui.editorWidgetRegistry().initEditors(cls.mCanvas)
|
||||
|
||||
@classmethod
|
||||
def createLayerWithOnePoint(cls, field_type):
|
||||
|
Loading…
x
Reference in New Issue
Block a user