Skip to content

Commit

Permalink
Add action menu to attribute dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
m-kuhn authored and 3nids committed Sep 16, 2014
1 parent e5f078e commit ba7f0a3
Show file tree
Hide file tree
Showing 10 changed files with 307 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ layertree/qgslayertreeviewdefaultactions.cpp
qgisgui.cpp
qgisinterface.cpp
qgsannotationitem.cpp
qgsactionmenu.cpp
qgsattributedialog.cpp
qgsattributeeditor.cpp
qgsattributeform.cpp
Expand Down Expand Up @@ -322,6 +323,7 @@ layertree/qgslayertreeview.h
layertree/qgslayertreeviewdefaultactions.h

qgisinterface.h
qgsactionmenu.h
qgsattributedialog.h
qgsattributeeditor.h
qgsattributeform.h
Expand Down Expand Up @@ -417,6 +419,7 @@ ENDIF(MSVC)
SET(QGIS_GUI_HDRS
qgisgui.h
qgisinterface.h
qgsactionmenu.h
qgsattributeeditor.h
qgsattributedialog.h
qgsattributeeditorcontext.h
Expand Down
12 changes: 3 additions & 9 deletions src/gui/attributetable/qgsattributetableview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )

QgsAttributeTableView::~QgsAttributeTableView()
{
if ( mActionPopup )
{
delete mActionPopup;
}
delete mActionPopup;
}
#if 0
void QgsAttributeTableView::setCanvasAndLayerCache( QgsMapCanvas *canvas, QgsVectorLayerCache *layerCache )
Expand Down Expand Up @@ -222,11 +219,8 @@ void QgsAttributeTableView::selectAll()

void QgsAttributeTableView::contextMenuEvent( QContextMenuEvent* event )
{
if ( mActionPopup )
{
delete mActionPopup;
mActionPopup = 0;
}
delete mActionPopup;
mActionPopup = 0;

QModelIndex idx = indexAt( event->pos() );
if ( !idx.isValid() )
Expand Down
10 changes: 9 additions & 1 deletion src/gui/attributetable/qgsfeaturelistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ QVariant QgsFeatureListModel::data( const QModelIndex &index, int role ) const
return mExpression->evaluate( &feat, fields );
}

if ( role == Qt::UserRole )
if ( role == FeatureInfoRole )
{
FeatureInfo featInfo;

Expand All @@ -91,6 +91,14 @@ QVariant QgsFeatureListModel::data( const QModelIndex &index, int role ) const

return QVariant::fromValue( featInfo );
}
else if ( role == FeatureRole )
{
QgsFeature feat;

mFilterModel->layerCache()->featureAtId( idxToFid( index ), feat );

return QVariant::fromValue( feat );
}

return sourceModel()->data( mapToSource( index ), role );
}
Expand Down
6 changes: 6 additions & 0 deletions src/gui/attributetable/qgsfeaturelistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ class GUI_EXPORT QgsFeatureListModel : public QAbstractProxyModel, public QgsFea
bool isEdited;
};

enum Role
{
FeatureInfoRole = Qt::UserRole,
FeatureRole
};

public:
explicit QgsFeatureListModel( QgsAttributeTableFilterModel *sourceModel, QObject* parent = NULL );
virtual ~QgsFeatureListModel();
Expand Down
14 changes: 14 additions & 0 deletions src/gui/attributetable/qgsfeaturelistview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <QSet>
#include <QSettings>

#include "qgsactionmenu.h"
#include "qgsattributetabledelegate.h"
#include "qgsattributetablefiltermodel.h"
#include "qgsattributetablemodel.h"
Expand Down Expand Up @@ -298,6 +299,19 @@ void QgsFeatureListView::keyPressEvent( QKeyEvent *event )
}
}

void QgsFeatureListView::contextMenuEvent( QContextMenuEvent *event )
{
QModelIndex index = indexAt( event->pos() );

if ( index.isValid() )
{
QgsFeature feature = mModel->data( index, QgsFeatureListModel::FeatureRole ).value<QgsFeature>();

QgsActionMenu menu( mModel->layerCache()->layer(), &feature, this );
menu.exec( event->globalPos() );
}
}

void QgsFeatureListView::selectRow( const QModelIndex& index, bool anchor )
{
QItemSelectionModel::SelectionFlags command = selectionCommand( index );
Expand Down
1 change: 1 addition & 0 deletions src/gui/attributetable/qgsfeaturelistview.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class GUI_EXPORT QgsFeatureListView : public QListView
virtual void mousePressEvent( QMouseEvent *event );
virtual void mouseReleaseEvent( QMouseEvent *event );
virtual void keyPressEvent( QKeyEvent *event );
virtual void contextMenuEvent( QContextMenuEvent *event );

signals:
/**
Expand Down
168 changes: 168 additions & 0 deletions src/gui/qgsactionmenu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/***************************************************************************
qgsactionmenu.cpp
--------------------------------------
Date : 11.8.2014
Copyright : (C) 2014 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsactionmenu.h"
#include "qgsvectorlayer.h"

#include <QMenuItem>

QgsActionMenu::QgsActionMenu( QgsVectorLayer* layer, const QgsFeature* feature, QWidget* parent )
: QMenu( parent )
, mLayer( layer )
, mAttributeActionSignalMapper( 0 )
, mMapLayerActionSignalMapper( 0 )
, mActions( 0 )
, mFeature( feature )
, mOwnsFeature( false )
{
init();
}

QgsActionMenu::QgsActionMenu( QgsVectorLayer* layer, const QgsFeatureId fid, QWidget* parent )
: QMenu( parent )
, mLayer( layer )
, mAttributeActionSignalMapper( 0 )
, mMapLayerActionSignalMapper( 0 )
, mActions( 0 )
, mFeature( 0 )
, mFeatureId( fid )
, mOwnsFeature( false )
{
init();
}

void QgsActionMenu::init()
{
setTitle( tr( "&Actions" ) );

connect( QgsMapLayerActionRegistry::instance(), SIGNAL(changed()), this, SLOT(reloadActions()) );

reloadActions();
}

const QgsFeature* QgsActionMenu::feature()
{
if ( !mFeature )
{
QgsFeature* feat = new QgsFeature();
if ( mActions->layer()->getFeatures( QgsFeatureRequest( mFeatureId ) ).nextFeature( *feat ) )
{
mFeature = feat;
mOwnsFeature = true;
}
else
{
delete feat;
}
}

return mFeature;
}

QgsActionMenu::~QgsActionMenu()
{
delete mActions;

if ( mOwnsFeature )
delete mFeature;
}

void QgsActionMenu::setFeature( QgsFeature* feature )
{
if ( mOwnsFeature )
delete mFeature;
mOwnsFeature = false;
mFeature = feature;
}

void QgsActionMenu::triggerAttributeAction( int index )
{
if ( feature() )
{
mActions->doAction( index, *feature() );
}
else
{
QgsDebugMsg( QString( "Trying to run an action on a non-existing feature with fid %1" ).arg( mFeatureId ) );
}
}

void QgsActionMenu::triggerMapLayerAction( int index )
{
if ( feature() )
{
QgsMapLayerAction* action = QgsMapLayerActionRegistry::instance()->mapLayerActions( mLayer ).at( index );

action->triggerForFeature( mLayer, feature() );
}
}

void QgsActionMenu::reloadActions()
{
delete mAttributeActionSignalMapper;
mAttributeActionSignalMapper = new QSignalMapper( this );
delete mMapLayerActionSignalMapper;
mMapLayerActionSignalMapper = new QSignalMapper( this );

connect( mAttributeActionSignalMapper, SIGNAL(mapped(int)), this, SLOT(triggerAttributeAction(int)) );
connect( mMapLayerActionSignalMapper, SIGNAL(mapped(int)), this, SLOT(triggerMapLayerAction(int)) );

delete mActions;
mActions = new QgsAttributeAction( *mLayer->actions() );

for( int idx = 0; idx < mActions->size(); ++idx )
{
const QgsAction& qaction( mActions->at( idx ) );

QAction* action = new QAction( qaction.name(), this );

// Only enable items on supported platforms
if ( !qaction.runable() )
{
action->setEnabled( false );
action->setToolTip( tr( "Not supported on your platform" ) );
}
else
{
action->setToolTip( qaction.action() );
}

mAttributeActionSignalMapper->setMapping( action, idx );

connect( action, SIGNAL(triggered()), mAttributeActionSignalMapper, SLOT(map()) );

addAction( action );
}

QList<QgsMapLayerAction*> mapLayerActions = QgsMapLayerActionRegistry::instance()->mapLayerActions( mLayer );

if ( mapLayerActions.size() > 0 )
{
//add a separator between user defined and standard actions
addSeparator();

for ( int i = 0; i < mapLayerActions.size(); ++i )
{
QgsMapLayerAction* qaction = mapLayerActions.at( i );
QAction* action = new QAction( qaction->text(), this );
mMapLayerActionSignalMapper->setMapping( action, i );
addAction( action );
connect( action, SIGNAL(triggered()), mMapLayerActionSignalMapper, SLOT(map()) );
}
}

emit reinit();
}

93 changes: 93 additions & 0 deletions src/gui/qgsactionmenu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/***************************************************************************
qgsactionmenu.h
--------------------------------------
Date : 11.8.2014
Copyright : (C) 2014 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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. *
* *
***************************************************************************/

#ifndef QGSACTIONMENU_H
#define QGSACTIONMENU_H

#include <QMenu>
#include <QSignalMapper>

#include "qgsattributeaction.h"
#include "qgsmaplayeractionregistry.h"

/**
* This class is a menu that is populated automatically with the actions defined for a given layer.
*/

class QgsActionMenu : public QMenu
{
Q_OBJECT
public:
/**
* Constructs a new QgsActionMenu
*
* @param layer The layer that this action will be run upon.
* @param feature The feature that this action will be run upon. Make sure that this feature is available
* for the lifetime of this object.
* @param parent The usual QWidget parent.
*/
explicit QgsActionMenu( QgsVectorLayer* layer, const QgsFeature* feature, QWidget* parent = 0 );

/**
* Constructs a new QgsActionMenu
*
* @param layer The layer that this action will be run upon.
* @param fid The feature id of the feature for which this action will be run.
* @param parent The usual QWidget parent.
*/
explicit QgsActionMenu( QgsVectorLayer* layer, const QgsFeatureId fid, QWidget* parent = 0 );

/**
* Destructor
*/
~QgsActionMenu();

/**
* Change the feature on which actions are performed
*
* @param feature A feature. Will not take ownership. It's the callers responsibility to keep the feature
* as long as the menu is displayed and the action is running.
*/
void setFeature( QgsFeature* feature );

/**
* @brief setFeature
* @param feature
*/
void setFeature( QgsFeatureId feature );

private slots:
void triggerAttributeAction( int index );
void triggerMapLayerAction( int index );
void reloadActions();

signals:
void reinit();

private:
void init();
const QgsFeature* feature();

QgsVectorLayer* mLayer;
QSignalMapper* mAttributeActionSignalMapper;
QSignalMapper* mMapLayerActionSignalMapper;
QgsAttributeAction* mActions;
const QgsFeature* mFeature;
QgsFeatureId mFeatureId;
bool mOwnsFeature;
};


#endif // QGSACTIONMENU_H
Loading

0 comments on commit ba7f0a3

Please sign in to comment.