Skip to content

Commit

Permalink
Contextmenu with individual actions
Browse files Browse the repository at this point in the history
Individual actions in the contextmenu of the attributetable and the relationeditorwidget.
It's unlink and delete feature in the relationeditorwidget.
It's delete feature in the attributetable (form view)
  • Loading branch information
signedav committed Jan 8, 2018
1 parent 9e704eb commit 2eaf4de
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 16 deletions.
8 changes: 8 additions & 0 deletions python/gui/attributetable/qgsdualview.sip
Expand Up @@ -245,6 +245,14 @@ Is emitted when a filter expression is set using the view.
Emitted when the form changes mode.

:param mode: new mode
%End

void showContextMenuExternally( QgsActionMenu *menu, const QgsFeatureId fid );
%Docstring
Emitted when selecting context menu on the feature list to create the context menu individually

:param menu: context menu
:param fid: feature id of the selected feature
%End

protected:
Expand Down
8 changes: 8 additions & 0 deletions python/gui/attributetable/qgsfeaturelistview.sip
Expand Up @@ -128,6 +128,14 @@ Is emitted, whenever the display expression is successfully changed
%End


void willShowContextMenu( QgsActionMenu *menu, const QModelIndex &atIndex );
%Docstring
Is emitted, when the context menu is created to add the specific actions to it

:param menu: is the already created context menu
:param atIndex: is the position of the current feature in the model
%End

public slots:

void setEditSelection( const QgsFeatureIds &fids );
Expand Down
16 changes: 16 additions & 0 deletions src/app/qgsattributetabledialog.cpp
Expand Up @@ -105,6 +105,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
connect( mMainView, &QgsDualView::currentChanged, this, &QgsAttributeTableDialog::mMainView_currentChanged );
connect( mActionAddFeature, &QAction::triggered, this, &QgsAttributeTableDialog::mActionAddFeature_triggered );
connect( mActionExpressionSelect, &QAction::triggered, this, &QgsAttributeTableDialog::mActionExpressionSelect_triggered );
connect( mMainView, &QgsDualView::showContextMenuExternally, this, &QgsAttributeTableDialog::showContextMenu );

Q_FOREACH ( const QgsField &field, mLayer->fields() )
{
Expand Down Expand Up @@ -1042,6 +1043,21 @@ void QgsAttributeTableDialog::setFilterExpression( const QString &filterString,
}


void QgsAttributeTableDialog::deleteFeature( const QgsFeatureId fid )
{
QgsDebugMsg( QString( "Delete %1" ).arg( fid ) );
mLayer->deleteFeature( fid );
}

void QgsAttributeTableDialog::showContextMenu( QgsActionMenu *menu, const QgsFeatureId fid )
{
if ( mLayer->isEditable() )
{
QAction *qAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteSelected.svg" ) ), tr( "Delete feature" ) );
connect( qAction, &QAction::triggered, this, [this, fid]() { deleteFeature( fid ); } );
}
}

//
// QgsAttributeTableDock
//
Expand Down
2 changes: 2 additions & 0 deletions src/app/qgsattributetabledialog.h
Expand Up @@ -219,6 +219,7 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
void updateFieldFromExpressionSelected();
void viewModeChanged( QgsAttributeForm::Mode mode );
void formFilterSet( const QString &filter, QgsAttributeForm::FilterType type );
void showContextMenu( QgsActionMenu *menu, const QgsFeatureId fid );

private:
QMenu *mMenuActions = nullptr;
Expand All @@ -236,6 +237,7 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
QgsAttributeEditorContext mEditorContext;

void updateMultiEditButtonState();
void deleteFeature( const QgsFeatureId fid );

friend class TestQgsAttributeTable;
};
Expand Down
10 changes: 8 additions & 2 deletions src/gui/attributetable/qgsdualview.cpp
Expand Up @@ -74,6 +74,7 @@ void QgsDualView::init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const Qg
mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, &QgsDualView::showViewHeaderMenu );
connect( mTableView, &QgsAttributeTableView::columnResized, this, &QgsDualView::tableColumnResized );
connect( mFeatureList, &QgsFeatureListView::willShowContextMenu, this, &QgsDualView::widgetWillShowContextMenu );

initLayerCache( !( request.flags() & QgsFeatureRequest::NoGeometry ) || !request.filterRect().isNull() );
initModels( mapCanvas, request, loadFeatures );
Expand Down Expand Up @@ -401,7 +402,6 @@ void QgsDualView::insertRecentlyUsedDisplayExpression( const QString &expression
mLastDisplayExpressionAction = previewAction;
}


void QgsDualView::mFeatureList_aboutToChangeEditSelection( bool &ok )
{
if ( mLayer->isEditable() && !mAttributeForm->save() )
Expand Down Expand Up @@ -543,7 +543,6 @@ void QgsDualView::viewWillShowContextMenu( QMenu *menu, const QModelIndex &atInd
return;
}


QModelIndex sourceIndex = mFilterModel->mapToSource( atIndex );

QAction *copyContentAction = new QAction( tr( "Copy cell content" ), this );
Expand Down Expand Up @@ -608,6 +607,13 @@ void QgsDualView::viewWillShowContextMenu( QMenu *menu, const QModelIndex &atInd
#endif
}


void QgsDualView::widgetWillShowContextMenu( QgsActionMenu *menu, const QModelIndex &atIndex )
{
emit showContextMenuExternally( menu, mFilterModel->rowToId( atIndex ) );
}


void QgsDualView::showViewHeaderMenu( QPoint point )
{
int col = mTableView->columnAt( point.x() );
Expand Down
9 changes: 9 additions & 0 deletions src/gui/attributetable/qgsdualview.h
Expand Up @@ -269,6 +269,13 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
*/
void formModeChanged( QgsAttributeForm::Mode mode );

/**
* Emitted when selecting context menu on the feature list to create the context menu individually
* \param menu context menu
* \param fid feature id of the selected feature
*/
void showContextMenuExternally( QgsActionMenu *menu, const QgsFeatureId fid );

protected:
void hideEvent( QHideEvent *event ) override;

Expand All @@ -289,6 +296,8 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas

void viewWillShowContextMenu( QMenu *menu, const QModelIndex &atIndex );

void widgetWillShowContextMenu( QgsActionMenu *menu, const QModelIndex &atIndex );

void showViewHeaderMenu( QPoint point );

void organizeColumns();
Expand Down
4 changes: 3 additions & 1 deletion src/gui/attributetable/qgsfeaturelistview.cpp
Expand Up @@ -19,7 +19,6 @@
#include <QSet>
#include <QSettings>

#include "qgsactionmenu.h"
#include "qgsattributetabledelegate.h"
#include "qgsattributetablefiltermodel.h"
#include "qgsattributetablemodel.h"
Expand Down Expand Up @@ -302,6 +301,9 @@ void QgsFeatureListView::contextMenuEvent( QContextMenuEvent *event )
QgsFeature feature = mModel->data( index, QgsFeatureListModel::FeatureRole ).value<QgsFeature>();

QgsActionMenu *menu = new QgsActionMenu( mModel->layerCache()->layer(), feature, QStringLiteral( "Feature" ), this );

emit willShowContextMenu( menu, index );

menu->exec( event->globalPos() );
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/gui/attributetable/qgsfeaturelistview.h
Expand Up @@ -20,6 +20,7 @@
#include "qgis_sip.h"
#include "qgis.h"
#include <qdebug.h>
#include "qgsactionmenu.h"

#include "qgsfeature.h" // For QgsFeatureIds
#include "qgis_gui.h"
Expand Down Expand Up @@ -146,6 +147,13 @@ class GUI_EXPORT QgsFeatureListView : public QListView
//! \note not available in Python bindings
void aboutToChangeEditSelection( bool &ok ) SIP_SKIP;

/**
* Is emitted, when the context menu is created to add the specific actions to it
* \param menu is the already created context menu
* \param atIndex is the position of the current feature in the model
*/
void willShowContextMenu( QgsActionMenu *menu, const QModelIndex &atIndex );

public slots:

/**
Expand Down Expand Up @@ -191,6 +199,7 @@ class GUI_EXPORT QgsFeatureListView : public QListView
bool mEditSelectionDrag = false; // Is set to true when the user initiated a left button click over an edit button and still keeps pressing //!< TODO
int mRowAnchor = 0;
QItemSelectionModel::SelectionFlags mCtrlDragSelectionFlag;

};

#endif
66 changes: 55 additions & 11 deletions src/gui/qgsrelationeditorwidget.cpp
Expand Up @@ -138,11 +138,13 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget *parent )
connect( mSaveEditsButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::saveEdits );
connect( mAddFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::addFeature );
connect( mDuplicateFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::duplicateFeature );
connect( mDeleteFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::deleteFeature );
connect( mDeleteFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::deleteSelectedFeatures );
connect( mLinkFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::linkFeature );
connect( mUnlinkFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::unlinkFeature );
connect( mUnlinkFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::unlinkSelectedFeatures );
connect( mFeatureSelectionMgr, &QgsIFeatureSelectionManager::selectionChanged, this, &QgsRelationEditorWidget::updateButtons );

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

// Set initial state for add/remove etc. buttons
updateButtons();
}
Expand Down Expand Up @@ -447,27 +449,55 @@ void QgsRelationEditorWidget::duplicateFeature()
}
}

void QgsRelationEditorWidget::deleteFeature()
void QgsRelationEditorWidget::deleteFeature( const QgsFeatureId featureid )
{
QgsVectorLayer *layer = nullptr;
QgsFeatureIds featureids;

featureids << featureid;

deleteFeatures( featureids );

}

void QgsRelationEditorWidget::deleteSelectedFeatures( )
{
deleteFeatures( mFeatureSelectionMgr->selectedFeatureIds() );
}

void QgsRelationEditorWidget::deleteFeatures( const QgsFeatureIds &featureids )
{
QgsVectorLayer *layer = nullptr;
if ( mNmRelation.isValid() )
// So far we expect the database to take care of cleaning up the linking table or restricting
// TODO: add more options for the behavior here
layer = mNmRelation.referencedLayer();
else
layer = mRelation.referencingLayer();
QgsDebugMsg( QString( "Delete %1" ).arg( mFeatureSelectionMgr->selectedFeatureIds().size() ) );
layer->deleteFeatures( mFeatureSelectionMgr->selectedFeatureIds() );

QgsDebugMsg( QString( "Delete %1" ).arg( featureids.size() ) );
layer->deleteFeatures( featureids );
}


void QgsRelationEditorWidget::unlinkFeature( const QgsFeatureId featureid )
{
QgsFeatureIds featureids;

featureids << featureid;

unlinkFeatures( featureids );
}

void QgsRelationEditorWidget::unlinkSelectedFeatures( )
{
unlinkFeatures( mFeatureSelectionMgr->selectedFeatureIds() );
}

void QgsRelationEditorWidget::unlinkFeature()
void QgsRelationEditorWidget::unlinkFeatures( const QgsFeatureIds &featureids )
{
if ( mNmRelation.isValid() )
{
QgsFeatureIterator selectedIterator = mNmRelation.referencedLayer()->getFeatures(
QgsFeatureRequest()
.setFilterFids( mFeatureSelectionMgr->selectedFeatureIds() )
.setFilterFids( featureids )
.setSubsetOfAttributes( mNmRelation.referencedFields() ) );

QgsFeature f;
Expand Down Expand Up @@ -514,7 +544,7 @@ void QgsRelationEditorWidget::unlinkFeature()
keyFields.insert( idx, fld );
}

Q_FOREACH ( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeatureIds() )
Q_FOREACH ( QgsFeatureId fid, featureids )
{
QMapIterator<int, QgsField> it( keyFields );
while ( it.hasNext() )
Expand Down Expand Up @@ -630,3 +660,17 @@ void QgsRelationEditorWidget::setShowLabel( bool showLabel )
else
setTitle( QString() );
}

void QgsRelationEditorWidget::showContextMenu( QgsActionMenu *menu, const QgsFeatureId fid )
{
if ( mRelation.referencingLayer()->isEditable() )
{
QAction *qAction = nullptr;

qAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteSelected.svg" ) ), tr( "Delete feature" ) );
connect( qAction, &QAction::triggered, this, [this, fid]() { deleteFeature( fid ); } );

qAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUnlink.svg" ) ), tr( "Unlink feature" ) );
connect( qAction, &QAction::triggered, this, [this, fid]() { unlinkFeature( fid ); } );
}
}
21 changes: 19 additions & 2 deletions src/gui/qgsrelationeditorwidget.h
Expand Up @@ -148,11 +148,14 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox
void addFeature();
void duplicateFeature();
void linkFeature();
void deleteFeature();
void unlinkFeature();
void deleteFeature( const QgsFeatureId featureid = QgsFeatureId() );
void deleteSelectedFeatures();
void unlinkFeature( const QgsFeatureId featureid = QgsFeatureId() );
void unlinkSelectedFeatures();
void saveEdits();
void toggleEditing( bool state );
void onCollapsedStateChanged( bool collapsed );
void showContextMenu( QgsActionMenu *menu, const QgsFeatureId fid );

private:
void updateUi();
Expand All @@ -179,6 +182,20 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox

bool mShowLabel = true;
bool mVisible = false;

/**
* Deletes the features
* \param featureids features to delete
* \since QGIS 3.00
*/
void deleteFeatures( const QgsFeatureIds &featureids );

/**
* Unlinks the features
* \param featureids features to unlink
* \since QGIS 3.00
*/
void unlinkFeatures( const QgsFeatureIds &featureids );
};

#endif // QGSRELATIONEDITOR_H

0 comments on commit 2eaf4de

Please sign in to comment.