Skip to content

Commit

Permalink
Merge pull request #31951 from troopa81/feature_update_layer_selectio…
Browse files Browse the repository at this point in the history
…n_from_relation_editor

Feature update layer selection relation widgets
  • Loading branch information
m-kuhn committed Oct 29, 2019
2 parents 3daf24c + e8d1a23 commit 328f365
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 19 deletions.
12 changes: 11 additions & 1 deletion src/gui/attributetable/qgsvectorlayerselectionmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ QgsVectorLayerSelectionManager::QgsVectorLayerSelectionManager( QgsVectorLayer *
: QgsIFeatureSelectionManager( parent )
, mLayer( layer )
{
connect( mLayer, &QgsVectorLayer::selectionChanged, this, &QgsVectorLayerSelectionManager::selectionChanged );
connect( mLayer, &QgsVectorLayer::selectionChanged, this, &QgsVectorLayerSelectionManager::onSelectionChanged );
}

int QgsVectorLayerSelectionManager::selectedFeatureCount()
Expand All @@ -48,3 +48,13 @@ const QgsFeatureIds &QgsVectorLayerSelectionManager::selectedFeatureIds() const
{
return mLayer->selectedFeatureIds();
}

QgsVectorLayer *QgsVectorLayerSelectionManager::layer() const
{
return mLayer;
}

void QgsVectorLayerSelectionManager::onSelectionChanged( const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect )
{
emit selectionChanged( selected, deselected, clearAndSelect );
}
16 changes: 16 additions & 0 deletions src/gui/attributetable/qgsvectorlayerselectionmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ class GUI_EXPORT QgsVectorLayerSelectionManager : public QgsIFeatureSelectionMan
void setSelectedFeatures( const QgsFeatureIds &ids ) override;
const QgsFeatureIds &selectedFeatureIds() const override;

/**
* Returns the vector layer
*/
QgsVectorLayer *layer() const;

private slots:

/**
* Called whenever layer selection was changed
*
* \param selected Newly selected feature ids
* \param deselected Ids of all features which have previously been selected but are not any more
* \param clearAndSelect In case this is set to TRUE, the old selection was dismissed and the new selection corresponds to selected
*/
virtual void onSelectionChanged( const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect );

private:
QgsVectorLayer *mLayer = nullptr;
};
Expand Down
6 changes: 2 additions & 4 deletions src/gui/qgsfeatureselectiondlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

#include "qgsfeatureselectiondlg.h"

#include "qgsgenericfeatureselectionmanager.h"
#include "qgsvectorlayerselectionmanager.h"
#include "qgsdistancearea.h"
#include "qgsfeaturerequest.h"
#include "qgsattributeeditorcontext.h"
Expand All @@ -29,7 +29,7 @@ QgsFeatureSelectionDlg::QgsFeatureSelectionDlg( QgsVectorLayer *vl, QgsAttribute
{
setupUi( this );

mFeatureSelection = new QgsGenericFeatureSelectionManager( mDualView );
mFeatureSelection = new QgsVectorLayerSelectionManager( vl, mDualView );

mDualView->setFeatureSelectionManager( mFeatureSelection );

Expand Down Expand Up @@ -72,5 +72,3 @@ void QgsFeatureSelectionDlg::showEvent( QShowEvent *event )

QDialog::showEvent( event );
}


4 changes: 2 additions & 2 deletions src/gui/qgsfeatureselectiondlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#ifndef QGSFEATURESELECTIONDLG_H
#define QGSFEATURESELECTIONDLG_H

class QgsGenericFeatureSelectionManager;
class QgsVectorLayerSelectionManager;

#include "ui_qgsfeatureselectiondlg.h"
#include "qgis_sip.h"
Expand Down Expand Up @@ -67,7 +67,7 @@ class GUI_EXPORT QgsFeatureSelectionDlg : public QDialog, private Ui::QgsFeature
void setSelectedFeatures( const QgsFeatureIds &ids );

private:
QgsGenericFeatureSelectionManager *mFeatureSelection = nullptr;
QgsVectorLayerSelectionManager *mFeatureSelection = nullptr;
QgsVectorLayer *mVectorLayer = nullptr;

// QWidget interface
Expand Down
89 changes: 79 additions & 10 deletions src/gui/qgsrelationeditorwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,75 @@
#include "qgslogger.h"
#include "qgsvectorlayerutils.h"
#include "qgsmapcanvas.h"
#include "qgsvectorlayerselectionmanager.h"

#include <QHBoxLayout>
#include <QLabel>
#include <QMessageBox>

/// @cond PRIVATE

/**
* This class is used to filter the current vector layer selection to features matching the given request.
* Relation editor widget use it in order to get selected feature for the current relation.
*/
class QgsFilteredSelectionManager : public QgsVectorLayerSelectionManager
{
public:
QgsFilteredSelectionManager( QgsVectorLayer *layer, const QgsFeatureRequest &request, QObject *parent = nullptr )
: QgsVectorLayerSelectionManager( layer, parent )
, mRequest( request )
{
for ( auto fid : layer->selectedFeatureIds() )
if ( mRequest.acceptFeature( layer->getFeature( fid ) ) )
mSelectedFeatureIds << fid;

connect( layer, &QgsVectorLayer::selectionChanged, this, &QgsFilteredSelectionManager::onSelectionChanged );
}

const QgsFeatureIds &selectedFeatureIds() const override
{
return mSelectedFeatureIds;
}


int selectedFeatureCount() override
{
return mSelectedFeatureIds.count();
}

private slots:

void onSelectionChanged( const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect ) override
{
QgsFeatureIds lselected = selected;
if ( clearAndSelect )
{
mSelectedFeatureIds.clear();
}
else
{
for ( auto fid : deselected )
mSelectedFeatureIds.remove( fid );
}

for ( auto fid : selected )
if ( mRequest.acceptFeature( layer()->getFeature( fid ) ) )
mSelectedFeatureIds << fid;
else
lselected.remove( fid );

emit selectionChanged( lselected, deselected, clearAndSelect );
}

private:

QgsFeatureRequest mRequest;
QgsFeatureIds mSelectedFeatureIds;
};

/// @endcond

QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget *parent )
: QgsCollapsibleGroupBox( parent )
{
Expand Down Expand Up @@ -135,8 +199,6 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget *parent )

mDualView = new QgsDualView( this );
mDualView->setView( mViewMode );
mFeatureSelectionMgr = new QgsGenericFeatureSelectionManager( mDualView );
mDualView->setFeatureSelectionManager( mFeatureSelectionMgr );

mRelationLayout->addWidget( mDualView );

Expand All @@ -151,7 +213,6 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget *parent )
connect( mLinkFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::linkFeature );
connect( mUnlinkFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::unlinkSelectedFeatures );
connect( mZoomToFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::zoomToSelectedFeatures );
connect( mFeatureSelectionMgr, &QgsIFeatureSelectionManager::selectionChanged, this, &QgsRelationEditorWidget::updateButtons );

connect( mDualView, &QgsDualView::showContextMenuExternally, this, &QgsRelationEditorWidget::showContextMenu );

Expand Down Expand Up @@ -198,10 +259,19 @@ void QgsRelationEditorWidget::setRelationFeature( const QgsRelation &relation, c
if ( mVisible )
{
QgsFeatureRequest myRequest = mRelation.getRelatedFeaturesRequest( mFeature );
mDualView->init( mRelation.referencingLayer(), nullptr, myRequest, mEditorContext );
initDualView( mRelation.referencingLayer(), myRequest );
}
}

void QgsRelationEditorWidget::initDualView( QgsVectorLayer *layer, const QgsFeatureRequest &request )
{
mDualView->init( layer, nullptr, request, mEditorContext );
mFeatureSelectionMgr = new QgsFilteredSelectionManager( layer, request, mDualView );
mDualView->setFeatureSelectionManager( mFeatureSelectionMgr );
connect( mFeatureSelectionMgr, &QgsIFeatureSelectionManager::selectionChanged, this, &QgsRelationEditorWidget::updateButtons );
updateButtons();
}

void QgsRelationEditorWidget::setRelations( const QgsRelation &relation, const QgsRelation &nmrelation )
{
if ( mRelation.isValid() )
Expand Down Expand Up @@ -295,7 +365,7 @@ void QgsRelationEditorWidget::updateButtons()
{
bool editable = false;
bool linkable = false;
bool selectionNotEmpty = mFeatureSelectionMgr->selectedFeatureCount();
bool selectionNotEmpty = mFeatureSelectionMgr ? mFeatureSelectionMgr->selectedFeatureCount() : false;

if ( mRelation.isValid() )
{
Expand Down Expand Up @@ -447,9 +517,6 @@ void QgsRelationEditorWidget::linkFeature()
for ( const QgsFeature &f : constNewFeatures )
ids << f.id();
mRelation.referencingLayer()->selectByIds( ids );


updateUi();
}
else
{
Expand All @@ -473,6 +540,8 @@ void QgsRelationEditorWidget::linkFeature()
}
}
}

updateUi();
}
}

Expand Down Expand Up @@ -730,11 +799,11 @@ void QgsRelationEditorWidget::updateUi()

nmRequest.setFilterExpression( filters.join( QStringLiteral( " OR " ) ) );

mDualView->init( mNmRelation.referencedLayer(), nullptr, nmRequest, mEditorContext );
initDualView( mNmRelation.referencedLayer(), nmRequest );
}
else
{
mDualView->init( mRelation.referencingLayer(), nullptr, myRequest, mEditorContext );
initDualView( mRelation.referencingLayer(), myRequest );
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/gui/qgsrelationeditorwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "qgis_gui.h"

class QgsFeature;
class QgsGenericFeatureSelectionManager;
class QgsVectorLayerSelectionManager;
class QgsVectorLayer;
class QgsVectorLayerTools;

Expand Down Expand Up @@ -160,10 +160,11 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox

private:
void updateUi();
void initDualView( QgsVectorLayer *layer, const QgsFeatureRequest &request );

QgsDualView *mDualView = nullptr;
QgsDualView::ViewMode mViewMode = QgsDualView::AttributeEditor;
QgsGenericFeatureSelectionManager *mFeatureSelectionMgr = nullptr;
QgsVectorLayerSelectionManager *mFeatureSelectionMgr = nullptr;
QgsAttributeEditorContext mEditorContext;
QgsRelation mRelation;
QgsRelation mNmRelation;
Expand Down
31 changes: 31 additions & 0 deletions tests/src/python/test_qgsrelationeditwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,37 @@ def test_discover_relations(self):
self.assertEqual([2, 3], relation.referencingFields())
self.assertEqual([0, 1], relation.referencedFields())

def test_selection(self):

fbook = QgsFeature(self.vl_books.fields())
fbook.setAttributes([self.vl_books.dataProvider().defaultValueClause(0), 'The Hitchhiker\'s Guide to the Galaxy', 'Sputnik Editions', 1961])
self.vl_books.addFeature(fbook)

flink = QgsFeature(self.vl_link_books_authors.fields())
flink.setAttributes([fbook.id(), 5])
self.vl_link_books_authors.addFeature(flink)

self.createWrapper(self.vl_authors, '"name"=\'Douglas Adams\'')

self.zoomToButton = self.widget.findChild(QToolButton, "mDeleteFeatureButton")
self.assertTrue(self.zoomToButton)
self.assertTrue(not self.zoomToButton.isEnabled())

selectionMgr = self.widget.featureSelectionManager()
self.assertTrue(selectionMgr)

self.vl_books.select(fbook.id())
self.assertEqual([fbook.id()], selectionMgr.selectedFeatureIds())
self.assertTrue(self.zoomToButton.isEnabled())

selectionMgr.deselect([fbook.id()])
self.assertEqual([], selectionMgr.selectedFeatureIds())
self.assertTrue(not self.zoomToButton.isEnabled())

self.vl_books.select([1, fbook.id()])
self.assertEqual([fbook.id()], selectionMgr.selectedFeatureIds())
self.assertTrue(self.zoomToButton.isEnabled())

def startTransaction(self):
"""
Start a new transaction and set all layers into transaction mode.
Expand Down

0 comments on commit 328f365

Please sign in to comment.