mirror of
https://github.com/qgis/QGIS.git
synced 2025-06-18 00:04:02 -04:00
[feature] New configuration options for attribute table
* Allow reordering the attribute table columns * Allow adding a new column to trigger an action to the attribute table
This commit is contained in:
parent
aa9010e8ed
commit
dd88fa99f3
@ -22,6 +22,7 @@
|
||||
%Include qgsaction.sip
|
||||
%Include qgsactionmanager.sip
|
||||
%Include qgsattributeaction.sip
|
||||
%Include qgsattributetableconfig.sip
|
||||
%Include qgsbrowsermodel.sip
|
||||
%Include qgsclipper.sip
|
||||
%Include qgscolorscheme.sip
|
||||
|
78
python/core/qgsattributetableconfig.sip
Normal file
78
python/core/qgsattributetableconfig.sip
Normal file
@ -0,0 +1,78 @@
|
||||
/***************************************************************************
|
||||
qgsattributetableconfig.h - QgsAttributeTableConfig
|
||||
|
||||
---------------------
|
||||
begin : 27.4.2016
|
||||
copyright : (C) 2016 by Matthias Kuhn
|
||||
email : matthias@opengis.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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* This is a container for configuration of the attribute table.
|
||||
* The configuration is specific for one vector layer.
|
||||
*/
|
||||
|
||||
class QgsAttributeTableConfig
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsattributetableconfig.h>
|
||||
%End
|
||||
public:
|
||||
/**
|
||||
* The type of an attribute table column.
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
Field, //!< This column represents a field
|
||||
Action //!< This column represents an action widget
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the configuration of a column in the attribute table.
|
||||
*/
|
||||
struct ColumnConfig
|
||||
{
|
||||
QgsAttributeTableConfig::Type mType; //!< The type of this column.
|
||||
QString mName; //!< The name of the attribute if this column represents a field
|
||||
bool mHidden; //!< Flag that controls if the column is hidden
|
||||
};
|
||||
|
||||
QgsAttributeTableConfig();
|
||||
|
||||
/**
|
||||
* Get the list with all columns and their configuration.
|
||||
* The list order defines the order of appearance.
|
||||
*/
|
||||
QVector<QgsAttributeTableConfig::ColumnConfig> columns() const;
|
||||
|
||||
/**
|
||||
* Set the list of columns visible in the attribute table.
|
||||
* The list order defines the order of appearance.
|
||||
*/
|
||||
void setColumns( const QVector<QgsAttributeTableConfig::ColumnConfig>& columns );
|
||||
|
||||
/**
|
||||
* Update the configuration with the given fields.
|
||||
* Any field which is present in the configuration but not present in the
|
||||
* parameter fields will be removed. Any field which is in the parameter
|
||||
* fields but not in the configuration will be appended.
|
||||
*/
|
||||
void update( const QgsFields& fields );
|
||||
|
||||
/**
|
||||
* Serialize to XML on layer save
|
||||
*/
|
||||
void writeXml( QDomNode& node ) const;
|
||||
|
||||
/**
|
||||
* Deserialize to XML on layer load
|
||||
*/
|
||||
void readXml( const QDomNode& node );
|
||||
};
|
@ -1321,6 +1321,18 @@ class QgsVectorLayer : QgsMapLayer
|
||||
*/
|
||||
QgsConditionalLayerStyles *conditionalStyles() const;
|
||||
|
||||
/**
|
||||
* Get the attribute table configuration object.
|
||||
* This defines the appearance of the attribute table.
|
||||
*/
|
||||
QgsAttributeTableConfig attributeTableConfig() const;
|
||||
|
||||
/**
|
||||
* Set the attribute table configuration object.
|
||||
* This defines the appearance of the attribute table.
|
||||
*/
|
||||
void setAttributeTableConfig( const QgsAttributeTableConfig& attributeTableConfig );
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Select feature by its ID
|
||||
|
@ -13,6 +13,18 @@ class QgsAttributeTableFilterModel: QSortFilterProxyModel, QgsFeatureModel
|
||||
ShowEdited
|
||||
};
|
||||
|
||||
enum ColumnType
|
||||
{
|
||||
ColumnTypeField, //!< This column shows a field
|
||||
ColumnTypeActionButton //!< This column shows action buttons
|
||||
};
|
||||
|
||||
enum Role
|
||||
{
|
||||
TypeRole = QgsAttributeTableModel::UserRole //!< The type of a given column
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Make sure, the master model is already loaded, so the selection will get synchronized.
|
||||
@ -99,6 +111,25 @@ class QgsAttributeTableFilterModel: QSortFilterProxyModel, QgsFeatureModel
|
||||
/** Returns the map canvas*/
|
||||
QgsMapCanvas* mapCanvas() const;
|
||||
|
||||
virtual QVariant data( const QModelIndex& index, int role ) const;
|
||||
|
||||
QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
|
||||
|
||||
/**
|
||||
* Get the index of the first column that contains an action widget.
|
||||
* Returns -1 if none is defined.
|
||||
*/
|
||||
int actionColumnIndex() const;
|
||||
|
||||
int columnCount( const QModelIndex &parent ) const;
|
||||
|
||||
/**
|
||||
* Set the attribute table configuration to control which fields are shown,
|
||||
* in which order they are shown as well as if and where an action column
|
||||
* is shown.
|
||||
*/
|
||||
void setAttributeTableConfig( const QgsAttributeTableConfig& config );
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Returns true if the source row will be accepted
|
||||
|
@ -19,7 +19,7 @@ class QgsAttributeTableView : QTableView
|
||||
/**
|
||||
* This event filter is installed on the verticalHeader to intercept mouse press and release
|
||||
* events. These are used to disable / enable live synchronisation with the map canvas selection
|
||||
* which can be slow due to recurring canvas repaints. Updating the
|
||||
* which can be slow due to recurring canvas repaints.
|
||||
*
|
||||
* @param object The object which is the target of the event.
|
||||
* @param event The intercepted event
|
||||
|
@ -65,6 +65,11 @@ class QgsDualView : QStackedWidget
|
||||
*/
|
||||
void setFilterMode( QgsAttributeTableFilterModel::FilterMode filterMode );
|
||||
|
||||
/**
|
||||
* Get the filter mode
|
||||
*
|
||||
* @return the filter mode
|
||||
*/
|
||||
QgsAttributeTableFilterModel::FilterMode filterMode();
|
||||
|
||||
/**
|
||||
@ -98,6 +103,9 @@ class QgsDualView : QStackedWidget
|
||||
*/
|
||||
void setFilteredFeatures( const QgsFeatureIds& filteredFeatures );
|
||||
|
||||
/**
|
||||
* Get a list of currently visible feature ids.
|
||||
*/
|
||||
QgsFeatureIds filteredFeatures();
|
||||
|
||||
/**
|
||||
@ -112,6 +120,11 @@ class QgsDualView : QStackedWidget
|
||||
void setFeatureSelectionManager( QgsIFeatureSelectionManager* featureSelectionManager );
|
||||
|
||||
QgsAttributeTableView* tableView();
|
||||
/**
|
||||
* Set the attribute table config which should be used to control
|
||||
* the appearance of the attribute table.
|
||||
*/
|
||||
void setAttributeTableConfig( const QgsAttributeTableConfig& config );
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -8,16 +8,19 @@ class QgsOrganizeTableColumnsDialog : QDialog
|
||||
/**
|
||||
* Constructor
|
||||
* @param vl The concerned vector layer
|
||||
* @param visible the cuurent list of visible fields name
|
||||
* @param visible the current list of visible fields name
|
||||
* @param parent parent object
|
||||
* @param flags window flags
|
||||
*/
|
||||
QgsOrganizeTableColumnsDialog( const QgsVectorLayer* vl, QStringList visible, QWidget *parent /TransferThis/ = nullptr, Qt::WindowFlags flags = Qt::Window );
|
||||
QgsOrganizeTableColumnsDialog(const QgsVectorLayer* vl, QWidget* parent = nullptr, Qt::WindowFlags flags = Qt::Window );
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~QgsOrganizeTableColumnsDialog();
|
||||
|
||||
/**
|
||||
* Get the selected fields name
|
||||
* @return The selected fields name
|
||||
* Get the updated configuration
|
||||
*/
|
||||
QStringList selectedFields();
|
||||
QgsAttributeTableConfig config() const;
|
||||
};
|
||||
|
@ -125,6 +125,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
|
||||
|
||||
// Initialize dual view
|
||||
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, context );
|
||||
mMainView->setAttributeTableConfig( mLayer->attributeTableConfig() );
|
||||
|
||||
// Initialize filter gui elements
|
||||
mFilterActionMapper = new QSignalMapper( this );
|
||||
@ -776,17 +777,12 @@ void QgsAttributeTableDialog::on_mFilterTableFields_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
QgsOrganizeTableColumnsDialog dialog( mLayer, mVisibleFields );
|
||||
QgsOrganizeTableColumnsDialog dialog( mLayer );
|
||||
if ( dialog.exec() == QDialog::Accepted )
|
||||
{
|
||||
mVisibleFields = dialog.selectedFields();
|
||||
|
||||
const QgsFields layerAttributes = mLayer->fields();
|
||||
for ( int idx = 0; idx < layerAttributes.count(); ++idx )
|
||||
{
|
||||
mMainView->tableView()->setColumnHidden(
|
||||
idx, !mVisibleFields.contains( layerAttributes[idx].name() ) );
|
||||
}
|
||||
QgsAttributeTableConfig config = dialog.config();
|
||||
mLayer->setAttributeTableConfig( config );
|
||||
mMainView->setAttributeTableConfig( config );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,7 @@ SET(QGIS_CORE_SRCS
|
||||
qgsapplication.cpp
|
||||
qgsaction.cpp
|
||||
qgsactionmanager.cpp
|
||||
qgsattributetableconfig.cpp
|
||||
qgsbrowsermodel.cpp
|
||||
qgscachedfeatureiterator.cpp
|
||||
qgscacheindex.cpp
|
||||
@ -591,7 +592,7 @@ SET(QGIS_CORE_HDRS
|
||||
|
||||
qgis.h
|
||||
qgsaction.h
|
||||
qgsactionmanager.h
|
||||
qgsattributetableconfig.h
|
||||
qgsattributeaction.h
|
||||
qgscachedfeatureiterator.h
|
||||
qgscacheindex.h
|
||||
|
@ -23,7 +23,6 @@ email : marco.hugentobler at sourcepole dot com
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QgsCoordinateTransform;
|
||||
class QgsMapToPixel;
|
||||
class QgsCurveV2;
|
||||
class QgsMultiCurveV2;
|
||||
|
150
src/core/qgsattributetableconfig.cpp
Normal file
150
src/core/qgsattributetableconfig.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/***************************************************************************
|
||||
qgsattributetableconfig.cpp - QgsAttributeTableConfig
|
||||
|
||||
---------------------
|
||||
begin : 27.4.2016
|
||||
copyright : (C) 2016 by mku
|
||||
email : [your-email-here]
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgsattributetableconfig.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
QgsAttributeTableConfig::QgsAttributeTableConfig()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVector<QgsAttributeTableConfig::ColumnConfig> QgsAttributeTableConfig::columns() const
|
||||
{
|
||||
return mColumns;
|
||||
}
|
||||
|
||||
void QgsAttributeTableConfig::setColumns( const QVector<ColumnConfig>& columns )
|
||||
{
|
||||
mColumns = columns;
|
||||
}
|
||||
|
||||
void QgsAttributeTableConfig::update( const QgsFields& fields )
|
||||
{
|
||||
QStringList columns;
|
||||
|
||||
bool containsActionColumn = false;
|
||||
|
||||
for ( int i = mColumns.count() - 1; i >= 0; --i )
|
||||
{
|
||||
const ColumnConfig& column = mColumns.at( i );
|
||||
if ( column.mType == Field )
|
||||
{
|
||||
if ( fields.fieldNameIndex( column.mName ) == -1 )
|
||||
{
|
||||
mColumns.remove( i );
|
||||
}
|
||||
else
|
||||
{
|
||||
columns.append( column.mName );
|
||||
}
|
||||
}
|
||||
else if ( column.mType == Action )
|
||||
{
|
||||
containsActionColumn = true;
|
||||
}
|
||||
}
|
||||
|
||||
Q_FOREACH ( const QgsField& field, fields )
|
||||
{
|
||||
if ( !columns.contains( field.name() ) )
|
||||
{
|
||||
ColumnConfig newColumn;
|
||||
newColumn.mHidden = false;
|
||||
newColumn.mType = Field;
|
||||
newColumn.mName = field.name();
|
||||
|
||||
mColumns.append( newColumn );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !containsActionColumn )
|
||||
{
|
||||
ColumnConfig actionConfig;
|
||||
|
||||
actionConfig.mType = Action;
|
||||
actionConfig.mHidden = true;
|
||||
|
||||
mColumns.append( actionConfig );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QgsAttributeTableConfig::readXml( const QDomNode& node )
|
||||
{
|
||||
mColumns.clear();
|
||||
|
||||
QDomNode configNode = node.namedItem( "attributetableconfig" );
|
||||
if ( !configNode.isNull() )
|
||||
{
|
||||
QDomNode columnsNode = configNode.toElement().namedItem( "columns" );
|
||||
|
||||
QDomNodeList columns = columnsNode.childNodes();
|
||||
|
||||
for ( int i = 0; i < columns.size(); ++i )
|
||||
{
|
||||
QDomElement columnElement = columns.at( i ).toElement();
|
||||
|
||||
ColumnConfig column;
|
||||
|
||||
if ( columnElement.attribute( "type" ) == "actions" )
|
||||
{
|
||||
column.mType = Action;
|
||||
}
|
||||
else
|
||||
{
|
||||
column.mType = Field;
|
||||
column.mName = columnElement.attribute( "name" );
|
||||
}
|
||||
|
||||
column.mHidden = columnElement.attribute( "hidden" ) == "1";
|
||||
|
||||
mColumns.append( column );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAttributeTableConfig::writeXml( QDomNode& node ) const
|
||||
{
|
||||
QDomDocument doc( node.ownerDocument() );
|
||||
|
||||
QDomElement configElement = doc.createElement( "attributetableconfig" );
|
||||
|
||||
QDomElement columnsElement = doc.createElement( "columns" );
|
||||
|
||||
Q_FOREACH ( const ColumnConfig& column, mColumns )
|
||||
{
|
||||
QDomElement columnElement = doc.createElement( "column" );
|
||||
|
||||
if ( column.mType == Action )
|
||||
{
|
||||
columnElement.setAttribute( "type", "actions" );
|
||||
}
|
||||
else
|
||||
{
|
||||
columnElement.setAttribute( "type", "field" );
|
||||
columnElement.setAttribute( "name", column.mName );
|
||||
}
|
||||
|
||||
columnElement.setAttribute( "hidden", column.mHidden );
|
||||
|
||||
columnsElement.appendChild( columnElement );
|
||||
}
|
||||
|
||||
configElement.appendChild( columnsElement );
|
||||
|
||||
node.appendChild( configElement );
|
||||
}
|
90
src/core/qgsattributetableconfig.h
Normal file
90
src/core/qgsattributetableconfig.h
Normal file
@ -0,0 +1,90 @@
|
||||
/***************************************************************************
|
||||
qgsattributetableconfig.h - QgsAttributeTableConfig
|
||||
|
||||
---------------------
|
||||
begin : 27.4.2016
|
||||
copyright : (C) 2016 by Matthias Kuhn
|
||||
email : matthias@opengis.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 QGSATTRIBUTETABLECONFIG_H
|
||||
#define QGSATTRIBUTETABLECONFIG_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QDomNode>
|
||||
|
||||
#include "qgsfield.h"
|
||||
|
||||
/**
|
||||
* This is a container for configuration of the attribute table.
|
||||
* The configuration is specific for one vector layer.
|
||||
*/
|
||||
|
||||
class CORE_EXPORT QgsAttributeTableConfig
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The type of an attribute table column.
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
Field, //!< This column represents a field
|
||||
Action //!< This column represents an action widget
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the configuration of a column in the attribute table.
|
||||
*/
|
||||
struct ColumnConfig
|
||||
{
|
||||
Type mType; //!< The type of this column.
|
||||
QString mName; //!< The name of the attribute if this column represents a field
|
||||
bool mHidden; //!< Flag that controls if the column is hidden
|
||||
};
|
||||
|
||||
QgsAttributeTableConfig();
|
||||
|
||||
/**
|
||||
* Get the list with all columns and their configuration.
|
||||
* The list order defines the order of appearance.
|
||||
*/
|
||||
QVector<ColumnConfig> columns() const;
|
||||
|
||||
/**
|
||||
* Set the list of columns visible in the attribute table.
|
||||
* The list order defines the order of appearance.
|
||||
*/
|
||||
void setColumns( const QVector<ColumnConfig>& columns );
|
||||
|
||||
/**
|
||||
* Update the configuration with the given fields.
|
||||
* Any field which is present in the configuration but not present in the
|
||||
* parameter fields will be removed. Any field which is in the parameter
|
||||
* fields but not in the configuration will be appended.
|
||||
*/
|
||||
void update( const QgsFields& fields );
|
||||
|
||||
/**
|
||||
* Serialize to XML on layer save
|
||||
*/
|
||||
void writeXml( QDomNode& node ) const;
|
||||
|
||||
/**
|
||||
* Deserialize to XML on layer load
|
||||
*/
|
||||
void readXml( const QDomNode& node );
|
||||
|
||||
private:
|
||||
QVector<ColumnConfig> mColumns;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE( QgsAttributeTableConfig::ColumnConfig )
|
||||
|
||||
#endif // QGSATTRIBUTETABLECONFIG_H
|
@ -42,7 +42,6 @@ class CORE_EXPORT QgsCoordinateTransformCache
|
||||
void invalidateCrs( const QString& crsAuthId );
|
||||
|
||||
private:
|
||||
static QgsCoordinateTransformCache* mInstance;
|
||||
QMultiHash< QPair< QString, QString >, QgsCoordinateTransform* > mTransforms; //same auth_id pairs might have different datum transformations
|
||||
|
||||
QgsCoordinateTransformCache();
|
||||
|
@ -1926,8 +1926,6 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
|
||||
// process the attribute actions
|
||||
mActions->readXML( node );
|
||||
|
||||
mEditFormConfig->readXml( node );
|
||||
|
||||
QDomNode annotationFormNode = node.namedItem( "annotationform" );
|
||||
if ( !annotationFormNode.isNull() )
|
||||
{
|
||||
@ -1988,6 +1986,8 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
|
||||
|
||||
mEditFormConfig->readXml( node );
|
||||
|
||||
mAttributeTableConfig.readXml( node );
|
||||
|
||||
mConditionalStyles->readXml( node );
|
||||
|
||||
return true;
|
||||
@ -2154,6 +2154,8 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
|
||||
|
||||
mEditFormConfig->writeXml( node );
|
||||
|
||||
mAttributeTableConfig.writeXml( node );
|
||||
|
||||
mConditionalStyles->writeXml( node, doc );
|
||||
|
||||
return true;
|
||||
@ -2266,11 +2268,11 @@ void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString
|
||||
QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
|
||||
{
|
||||
if ( attributeIndex < 0 || attributeIndex >= fields().count() )
|
||||
return "";
|
||||
return QString();
|
||||
|
||||
QString name = fields().at( attributeIndex ).name();
|
||||
|
||||
return mAttributeAliasMap.value( name, "" );
|
||||
return mAttributeAliasMap.value( name, QString() );
|
||||
}
|
||||
|
||||
QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
|
||||
@ -3591,6 +3593,16 @@ void QgsVectorLayer::readSldLabeling( const QDomNode& node )
|
||||
}
|
||||
}
|
||||
|
||||
QgsAttributeTableConfig QgsVectorLayer::attributeTableConfig() const
|
||||
{
|
||||
return mAttributeTableConfig;
|
||||
}
|
||||
|
||||
void QgsVectorLayer::setAttributeTableConfig( const QgsAttributeTableConfig& attributeTableConfig )
|
||||
{
|
||||
mAttributeTableConfig = attributeTableConfig;
|
||||
}
|
||||
|
||||
void QgsVectorLayer::setDiagramLayerSettings( const QgsDiagramLayerSettings& s )
|
||||
{
|
||||
if ( !mDiagramLayerSettings )
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "qgssnapper.h"
|
||||
#include "qgsvectorsimplifymethod.h"
|
||||
#include "qgseditformconfig.h"
|
||||
#include "qgsattributetableconfig.h"
|
||||
|
||||
class QPainter;
|
||||
class QImage;
|
||||
@ -631,7 +632,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
* The pointer which is returned directly points to the actions object
|
||||
* which is used by the layer, so any changes are immediately applied.
|
||||
*/
|
||||
QgsActionManager *actions() { return mActions; }
|
||||
QgsActionManager* actions() { return mActions; }
|
||||
|
||||
/**
|
||||
* The number of features that are selected in this layer
|
||||
@ -1321,7 +1322,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
*/
|
||||
void clearAttributeEditorWidgets() { mEditFormConfig->clearTabs(); }
|
||||
|
||||
/** Returns the alias of an attribute name or an empty string if there is no alias */
|
||||
/**
|
||||
* Returns the alias of an attribute name or a null string if there is no alias.
|
||||
*
|
||||
* @see {@attributeDisplayName( int attributeIndex )} which returns the field name
|
||||
* if no alias is defined.
|
||||
*/
|
||||
QString attributeAlias( int attributeIndex ) const;
|
||||
|
||||
/** Convenience function that returns the attribute alias if defined or the field name else */
|
||||
@ -1686,6 +1692,18 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
*/
|
||||
QgsConditionalLayerStyles *conditionalStyles() const;
|
||||
|
||||
/**
|
||||
* Get the attribute table configuration object.
|
||||
* This defines the appearance of the attribute table.
|
||||
*/
|
||||
QgsAttributeTableConfig attributeTableConfig() const;
|
||||
|
||||
/**
|
||||
* Set the attribute table configuration object.
|
||||
* This defines the appearance of the attribute table.
|
||||
*/
|
||||
void setAttributeTableConfig( const QgsAttributeTableConfig& attributeTableConfig );
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Select feature by its ID
|
||||
@ -2088,6 +2106,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
|
||||
QgsFeatureIds mDeletedFids;
|
||||
|
||||
QgsAttributeTableConfig mAttributeTableConfig;
|
||||
|
||||
friend class QgsVectorLayerFeatureSource;
|
||||
};
|
||||
|
||||
|
@ -118,29 +118,36 @@ void QgsAttributeTableDelegate::setFeatureSelectionModel( QgsFeatureSelectionMod
|
||||
mFeatureSelectionModel = featureSelectionModel;
|
||||
}
|
||||
|
||||
void QgsAttributeTableDelegate::setActionWidgetImage( const QImage& image )
|
||||
{
|
||||
mActionWidgetImage = image;
|
||||
}
|
||||
|
||||
|
||||
void QgsAttributeTableDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
QgsFeatureId fid = index.model()->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong();
|
||||
QgsAttributeTableFilterModel::ColumnType columnType = static_cast<QgsAttributeTableFilterModel::ColumnType>( index.model()->data( index, QgsAttributeTableFilterModel::TypeRole ).toInt() );
|
||||
|
||||
QStyleOptionViewItem myOpt = option;
|
||||
|
||||
if ( index.model()->data( index, Qt::EditRole ).isNull() )
|
||||
if ( columnType == QgsAttributeTableFilterModel::ColumnTypeActionButton )
|
||||
{
|
||||
myOpt.font.setItalic( true );
|
||||
myOpt.palette.setColor( QPalette::Text, QColor( "gray" ) );
|
||||
}
|
||||
|
||||
if ( mFeatureSelectionModel && mFeatureSelectionModel->isSelected( fid ) )
|
||||
myOpt.state |= QStyle::State_Selected;
|
||||
|
||||
|
||||
if ( index.column() == 0 )
|
||||
{
|
||||
painter->drawImage( QPoint( 0, 0 ), mActionButtonImage );
|
||||
QRect r = option.rect.adjusted( -1, 0, 0, 0 );
|
||||
painter->drawImage( r.x(), r.y(), mActionWidgetImage );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsFeatureId fid = index.model()->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong();
|
||||
|
||||
QStyleOptionViewItem myOpt = option;
|
||||
|
||||
if ( index.model()->data( index, Qt::EditRole ).isNull() )
|
||||
{
|
||||
myOpt.font.setItalic( true );
|
||||
myOpt.palette.setColor( QPalette::Text, QColor( "gray" ) );
|
||||
}
|
||||
|
||||
if ( mFeatureSelectionModel && mFeatureSelectionModel->isSelected( fid ) )
|
||||
myOpt.state |= QStyle::State_Selected;
|
||||
|
||||
QItemDelegate::paint( painter, myOpt, index );
|
||||
|
||||
if ( option.state & QStyle::State_HasFocus )
|
||||
|
@ -46,7 +46,6 @@ class GUI_EXPORT QgsAttributeTableDelegate : public QItemDelegate
|
||||
: QItemDelegate( parent )
|
||||
, mLayer( nullptr )
|
||||
, mFeatureSelectionModel( nullptr )
|
||||
, mActionButtonWidget( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
@ -80,13 +79,15 @@ class GUI_EXPORT QgsAttributeTableDelegate : public QItemDelegate
|
||||
|
||||
void setFeatureSelectionModel( QgsFeatureSelectionModel* featureSelectionModel );
|
||||
|
||||
private:
|
||||
QWidget* createActionWidget( QWidget* parent, QgsVectorLayer* layer ) const;
|
||||
/**
|
||||
* Set an image that represents an action widget
|
||||
*/
|
||||
void setActionWidgetImage( const QImage& image );
|
||||
|
||||
private:
|
||||
QgsVectorLayer* mLayer;
|
||||
QgsFeatureSelectionModel* mFeatureSelectionModel;
|
||||
QWidget* mActionButtonWidget;
|
||||
QImage mActionButtonImage;
|
||||
QImage mActionWidgetImage;
|
||||
};
|
||||
|
||||
#endif //QGSATTRIBUTETABLEDELEGATE_H
|
||||
|
@ -69,13 +69,93 @@ void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
|
||||
|
||||
QVariant QgsAttributeTableFilterModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
if ( index.column() == 0 )
|
||||
return "Wow";
|
||||
else
|
||||
if ( mColumnMapping.at( index.column() ) == -1 ) // actions
|
||||
{
|
||||
QModelIndex sourceIndex = QSortFilterProxyModel::index( index.row(), index.column() - 1, index.parent() );
|
||||
return QSortFilterProxyModel::data( sourceIndex, role );
|
||||
if ( role == TypeRole )
|
||||
return ColumnTypeActionButton;
|
||||
else if ( role == QgsAttributeTableModel::FeatureIdRole )
|
||||
{
|
||||
QModelIndex fieldIndex = QSortFilterProxyModel::mapToSource( QSortFilterProxyModel::index( index.row(), 0, index.parent() ) );
|
||||
return sourceModel()->data( fieldIndex, QgsAttributeTableModel::FeatureIdRole );
|
||||
}
|
||||
}
|
||||
else if ( role == TypeRole )
|
||||
return ColumnTypeField;
|
||||
|
||||
return QSortFilterProxyModel::data( index, role );
|
||||
}
|
||||
|
||||
QVariant QgsAttributeTableFilterModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||
{
|
||||
if ( orientation == Qt::Horizontal )
|
||||
{
|
||||
if ( mColumnMapping.at( section ) == -1 && role == Qt::DisplayRole )
|
||||
return tr( "Actions" );
|
||||
else
|
||||
return QSortFilterProxyModel::headerData( section, orientation, role );
|
||||
}
|
||||
else
|
||||
return QSortFilterProxyModel::headerData( section, orientation, role );
|
||||
}
|
||||
|
||||
int QgsAttributeTableFilterModel::actionColumnIndex() const
|
||||
{
|
||||
return mColumnMapping.indexOf( -1 );
|
||||
}
|
||||
|
||||
int QgsAttributeTableFilterModel::columnCount( const QModelIndex& parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
return mColumnMapping.count();
|
||||
}
|
||||
|
||||
void QgsAttributeTableFilterModel::setAttributeTableConfig( const QgsAttributeTableConfig& config )
|
||||
{
|
||||
int columnIndex = 0;
|
||||
int configIndex = 0;
|
||||
bool resetModel = false;
|
||||
|
||||
for ( ; configIndex < config.columns().size(); ++configIndex )
|
||||
{
|
||||
const QgsAttributeTableConfig::ColumnConfig& columnConfig = config.columns().at( configIndex );
|
||||
|
||||
// Hidden? No reason for further checks
|
||||
if ( columnConfig.mHidden )
|
||||
continue;
|
||||
|
||||
// Do the previous and current definition match?
|
||||
if ( mColumnMapping.size() > columnIndex )
|
||||
{
|
||||
if (( columnConfig.mType == QgsAttributeTableConfig::Action && mColumnMapping.at( columnIndex ) == -1 ) ||
|
||||
( columnConfig.mType == QgsAttributeTableConfig::Field && mColumnMapping.at( columnIndex ) == layer()->fieldNameIndex( columnConfig.mName ) ) )
|
||||
{
|
||||
++columnIndex;
|
||||
continue;
|
||||
}
|
||||
else // There is a mismatch between previous and current configuration: remove all remaining columns, they will be readded
|
||||
{
|
||||
mColumnMapping.remove( columnIndex, mColumnMapping.count() - columnIndex );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! resetModel )
|
||||
{
|
||||
beginResetModel();
|
||||
resetModel = true;
|
||||
}
|
||||
|
||||
|
||||
// New column? append
|
||||
Q_ASSERT( mColumnMapping.size() == columnIndex );
|
||||
if ( columnConfig.mType == QgsAttributeTableConfig::Action )
|
||||
mColumnMapping.append( -1 );
|
||||
else
|
||||
mColumnMapping.append( layer()->fieldNameIndex( columnConfig.mName ) );
|
||||
|
||||
++columnIndex;
|
||||
}
|
||||
if ( resetModel )
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void QgsAttributeTableFilterModel::setSelectedOnTop( bool selectedOnTop )
|
||||
@ -96,6 +176,12 @@ void QgsAttributeTableFilterModel::setSourceModel( QgsAttributeTableModel* sourc
|
||||
{
|
||||
mTableModel = sourceModel;
|
||||
|
||||
mColumnMapping.append( -1 ); // -1 for actions column
|
||||
for ( int i = 0; i < mTableModel->columnCount(); ++i )
|
||||
{
|
||||
mColumnMapping.append( i );
|
||||
}
|
||||
|
||||
QSortFilterProxyModel::setSourceModel( sourceModel );
|
||||
}
|
||||
|
||||
@ -310,14 +396,23 @@ QModelIndexList QgsAttributeTableFilterModel::fidToIndexList( QgsFeatureId fid )
|
||||
return indexes;
|
||||
}
|
||||
|
||||
QModelIndex QgsAttributeTableFilterModel::mapToMaster( const QModelIndex &proxyIndex ) const
|
||||
QModelIndex QgsAttributeTableFilterModel::mapToSource( const QModelIndex& proxyIndex ) const
|
||||
{
|
||||
// Master is source
|
||||
return mapToSource( proxyIndex );
|
||||
if ( !proxyIndex.isValid() )
|
||||
return QModelIndex();
|
||||
|
||||
int sourceColumn = mColumnMapping.at( proxyIndex.column() );
|
||||
|
||||
// For the action column there is no matching column in the source model: invalid
|
||||
if ( sourceColumn == -1 )
|
||||
return QModelIndex();
|
||||
|
||||
return QSortFilterProxyModel::mapToSource( index( proxyIndex.row(), mColumnMapping.at( proxyIndex.column() ), proxyIndex.parent() ) );
|
||||
}
|
||||
|
||||
QModelIndex QgsAttributeTableFilterModel::mapFromMaster( const QModelIndex &sourceIndex ) const
|
||||
QModelIndex QgsAttributeTableFilterModel::mapFromSource( const QModelIndex& sourceIndex ) const
|
||||
{
|
||||
// Master is source
|
||||
return mapFromSource( sourceIndex );
|
||||
QModelIndex proxyIndex = QSortFilterProxyModel::mapFromSource( sourceIndex );
|
||||
|
||||
return index( proxyIndex.row(), mColumnMapping.indexOf( proxyIndex.column() ), proxyIndex.parent() );
|
||||
}
|
||||
|
@ -42,6 +42,17 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
|
||||
ShowEdited
|
||||
};
|
||||
|
||||
enum ColumnType
|
||||
{
|
||||
ColumnTypeField, //!< This column shows a field
|
||||
ColumnTypeActionButton //!< This column shows action buttons
|
||||
};
|
||||
|
||||
enum Role
|
||||
{
|
||||
TypeRole = QgsAttributeTableModel::UserRole //!< The type of a given column
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@ -137,11 +148,16 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
|
||||
QgsFeatureId rowToId( const QModelIndex& row );
|
||||
|
||||
QModelIndex fidToIndex( QgsFeatureId fid ) override;
|
||||
|
||||
QModelIndexList fidToIndexList( QgsFeatureId fid );
|
||||
|
||||
virtual QModelIndex mapToMaster( const QModelIndex &proxyIndex ) const;
|
||||
inline QModelIndex mapToMaster( const QModelIndex& proxyIndex ) const { return mapToSource( proxyIndex ); }
|
||||
|
||||
virtual QModelIndex mapFromMaster( const QModelIndex &sourceIndex ) const;
|
||||
inline QModelIndex mapFromMaster( const QModelIndex& sourceIndex ) const { return mapFromSource( sourceIndex ); }
|
||||
|
||||
virtual QModelIndex mapToSource( const QModelIndex& proxyIndex ) const override;
|
||||
|
||||
virtual QModelIndex mapFromSource( const QModelIndex& sourceIndex ) const override;
|
||||
|
||||
/**
|
||||
* Sort by the given column using the given order.
|
||||
@ -157,6 +173,23 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
|
||||
|
||||
virtual QVariant data( const QModelIndex& index, int role ) const override;
|
||||
|
||||
QVariant headerData( int section, Qt::Orientation orientation, int role ) const override;
|
||||
|
||||
/**
|
||||
* Get the index of the first column that contains an action widget.
|
||||
* Returns -1 if none is defined.
|
||||
*/
|
||||
int actionColumnIndex() const;
|
||||
|
||||
int columnCount( const QModelIndex &parent ) const override;
|
||||
|
||||
/**
|
||||
* Set the attribute table configuration to control which fields are shown,
|
||||
* in which order they are shown as well as if and where an action column
|
||||
* is shown.
|
||||
*/
|
||||
void setAttributeTableConfig( const QgsAttributeTableConfig& config );
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Returns true if the source row will be accepted
|
||||
@ -195,6 +228,8 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
|
||||
FilterMode mFilterMode;
|
||||
bool mSelectedOnTop;
|
||||
QgsAttributeTableModel* mTableModel;
|
||||
|
||||
QVector<int> mColumnMapping;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -51,9 +51,10 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
|
||||
public:
|
||||
enum Role
|
||||
{
|
||||
SortRole = Qt::UserRole + 1,
|
||||
FeatureIdRole = Qt::UserRole + 2,
|
||||
FieldIndexRole = Qt::UserRole + 3
|
||||
SortRole = Qt::UserRole + 1, //!< Role used for sorting
|
||||
FeatureIdRole, //!< Get the feature id of the feature in this row
|
||||
FieldIndexRole, //!< Get the field index of this column
|
||||
UserRole //!< Start further roles starting from this role
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -64,14 +64,10 @@ QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
|
||||
|
||||
connect( verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( selectRow( int ) ) );
|
||||
connect( verticalHeader(), SIGNAL( sectionEntered( int ) ), this, SLOT( _q_selectRow( int ) ) );
|
||||
connect( horizontalHeader(), SIGNAL( sectionResized( int, int, int ) ), this, SLOT( columnSizeChanged( int, int, int ) ) );
|
||||
connect( horizontalHeader(), SIGNAL( sortIndicatorChanged( int, Qt::SortOrder ) ), this, SLOT( showHorizontalSortIndicator() ) );
|
||||
}
|
||||
|
||||
QgsAttributeTableView::~QgsAttributeTableView()
|
||||
{
|
||||
delete mActionPopup;
|
||||
}
|
||||
|
||||
bool QgsAttributeTableView::eventFilter( QObject *object, QEvent *event )
|
||||
{
|
||||
if ( object == verticalHeader()->viewport() )
|
||||
@ -123,6 +119,9 @@ void QgsAttributeTableView::setModel( QgsAttributeTableFilterModel* filterModel
|
||||
connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
|
||||
connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
|
||||
}
|
||||
|
||||
mActionWidget = createActionWidget( 0 );
|
||||
mActionWidget->setVisible( false );
|
||||
}
|
||||
|
||||
void QgsAttributeTableView::setFeatureSelectionManager( QgsIFeatureSelectionManager* featureSelectionManager )
|
||||
@ -136,19 +135,35 @@ void QgsAttributeTableView::setFeatureSelectionManager( QgsIFeatureSelectionMana
|
||||
mFeatureSelectionModel->setFeatureSelectionManager( mFeatureSelectionManager );
|
||||
}
|
||||
|
||||
QWidget* QgsAttributeTableView::createActionWidget()
|
||||
QWidget* QgsAttributeTableView::createActionWidget( QgsFeatureId fid )
|
||||
{
|
||||
QToolButton* toolButton = new QToolButton( this );
|
||||
toolButton->setPopupMode( QToolButton::MenuButtonPopup );
|
||||
|
||||
for ( int i = 0; i < mFilterModel->layer()->actions()->size(); ++i )
|
||||
QgsActionManager* actions = mFilterModel->layer()->actions();
|
||||
|
||||
for ( int i = 0; i < actions->size(); ++i )
|
||||
{
|
||||
const QgsAction& action = mFilterModel->layer()->actions()->at( i );
|
||||
const QgsAction& action = actions->at( i );
|
||||
|
||||
QAction* act = new QAction( action.icon(), action.shortTitle(), toolButton );
|
||||
QAction* act = new QAction( action.icon(), action.shortTitle().isEmpty() ? action.name() : action.shortTitle(), toolButton );
|
||||
act->setToolTip( action.name() );
|
||||
act->setData( i );
|
||||
act->setProperty( "fid", fid );
|
||||
|
||||
connect( act, SIGNAL( triggered( bool ) ), this, SLOT( actionTriggered() ) );
|
||||
|
||||
toolButton->addAction( act );
|
||||
|
||||
if ( actions->defaultAction() == i )
|
||||
toolButton->setDefaultAction( act );
|
||||
}
|
||||
|
||||
if ( !toolButton->actions().isEmpty() && actions->defaultAction() == -1 )
|
||||
toolButton->setDefaultAction( toolButton->actions().first() );
|
||||
|
||||
updateActionImage( toolButton );
|
||||
|
||||
return toolButton;
|
||||
}
|
||||
|
||||
@ -176,12 +191,12 @@ void QgsAttributeTableView::mouseReleaseEvent( QMouseEvent *event )
|
||||
void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event )
|
||||
{
|
||||
QModelIndex index = indexAt( event->pos() );
|
||||
if ( index.column() == 0 )
|
||||
if ( index.data( QgsAttributeTableFilterModel::TypeRole ) == QgsAttributeTableFilterModel::ColumnTypeActionButton )
|
||||
{
|
||||
Q_ASSERT( index.isValid() );
|
||||
|
||||
if ( !indexWidget( index ) )
|
||||
setIndexWidget( index, createActionWidget() );
|
||||
setIndexWidget( index, createActionWidget( mFilterModel->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong() ) );
|
||||
}
|
||||
|
||||
setSelectionMode( QAbstractItemView::NoSelection );
|
||||
@ -246,7 +261,7 @@ void QgsAttributeTableView::contextMenuEvent( QContextMenuEvent* event )
|
||||
if ( !vlayer )
|
||||
return;
|
||||
|
||||
mActionPopup = new QMenu();
|
||||
mActionPopup = new QMenu( this );
|
||||
|
||||
mActionPopup->addAction( tr( "Select All" ), this, SLOT( selectAll() ), QKeySequence::SelectAll );
|
||||
|
||||
@ -318,3 +333,32 @@ void QgsAttributeTableView::showHorizontalSortIndicator()
|
||||
{
|
||||
horizontalHeader()->setSortIndicatorShown( true );
|
||||
}
|
||||
|
||||
void QgsAttributeTableView::actionTriggered()
|
||||
{
|
||||
QAction* action = qobject_cast<QAction*>( sender() );
|
||||
QgsFeatureId fid = action->property( "fid" ).toLongLong();
|
||||
|
||||
QgsFeature f;
|
||||
mFilterModel->layerCache()->getFeatures( QgsFeatureRequest( fid ) ).nextFeature( f );
|
||||
|
||||
mFilterModel->layer()->actions()->doAction( action->data().toInt(), f );
|
||||
}
|
||||
|
||||
void QgsAttributeTableView::columnSizeChanged( int index, int oldWidth, int newWidth )
|
||||
{
|
||||
Q_UNUSED( oldWidth )
|
||||
if ( mFilterModel->actionColumnIndex() == index )
|
||||
{
|
||||
mActionWidget->resize( newWidth, mActionWidget->height() );
|
||||
updateActionImage( mActionWidget );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAttributeTableView::updateActionImage( QWidget* widget )
|
||||
{
|
||||
QImage image( widget->size(), QImage::Format_ARGB32_Premultiplied );
|
||||
QPainter painter( &image );
|
||||
widget->render( &painter );
|
||||
mTableDelegate->setActionWidgetImage( image );
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
|
||||
|
||||
public:
|
||||
QgsAttributeTableView( QWidget* parent = nullptr );
|
||||
virtual ~QgsAttributeTableView();
|
||||
|
||||
virtual void setModel( QgsAttributeTableFilterModel* filterModel );
|
||||
|
||||
@ -140,9 +139,12 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
|
||||
private slots:
|
||||
void modelDeleted();
|
||||
void showHorizontalSortIndicator();
|
||||
void actionTriggered();
|
||||
void columnSizeChanged( int index, int oldWidth, int newWidth );
|
||||
|
||||
private:
|
||||
QWidget* createActionWidget();
|
||||
void updateActionImage( QWidget* widget );
|
||||
QWidget* createActionWidget( QgsFeatureId fid );
|
||||
|
||||
void selectRow( int row, bool anchor );
|
||||
QgsAttributeTableModel* mMasterModel;
|
||||
@ -154,6 +156,7 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
|
||||
QMenu *mActionPopup;
|
||||
int mRowSectionAnchor;
|
||||
QItemSelectionModel::SelectionFlag mCtrlDragSelectionFlag;
|
||||
QWidget* mActionWidget;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -464,6 +464,11 @@ void QgsDualView::setFeatureSelectionManager( QgsIFeatureSelectionManager* featu
|
||||
mFeatureSelectionManager = featureSelectionManager;
|
||||
}
|
||||
|
||||
void QgsDualView::setAttributeTableConfig( const QgsAttributeTableConfig& config )
|
||||
{
|
||||
mFilterModel->setAttributeTableConfig( config );
|
||||
}
|
||||
|
||||
void QgsDualView::progress( int i, bool& cancel )
|
||||
{
|
||||
if ( !mProgressDlg )
|
||||
|
@ -141,6 +141,9 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
|
||||
*/
|
||||
void setFilteredFeatures( const QgsFeatureIds& filteredFeatures );
|
||||
|
||||
/**
|
||||
* Get a list of currently visible feature ids.
|
||||
*/
|
||||
QgsFeatureIds filteredFeatures() { return mFilterModel->filteredFeatures(); }
|
||||
|
||||
/**
|
||||
@ -169,7 +172,13 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
|
||||
*
|
||||
* @return The table view
|
||||
*/
|
||||
QgsAttributeTableView* tableView() { return mTableView; };
|
||||
QgsAttributeTableView* tableView() { return mTableView; }
|
||||
|
||||
/**
|
||||
* Set the attribute table config which should be used to control
|
||||
* the appearance of the attribute table.
|
||||
*/
|
||||
void setAttributeTableConfig( const QgsAttributeTableConfig& config );
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -41,57 +41,76 @@
|
||||
#include "qgseditorwidgetregistry.h"
|
||||
|
||||
|
||||
QgsOrganizeTableColumnsDialog::QgsOrganizeTableColumnsDialog( const QgsVectorLayer* vl, const QStringList visble, QWidget *parent, Qt::WindowFlags flags )
|
||||
QgsOrganizeTableColumnsDialog::QgsOrganizeTableColumnsDialog( const QgsVectorLayer* vl, QWidget* parent, Qt::WindowFlags flags )
|
||||
: QDialog( parent, flags )
|
||||
{
|
||||
setupUi( this );
|
||||
if ( vl )
|
||||
{
|
||||
QgsAttributeTableConfig config = vl->attributeTableConfig();
|
||||
config.update( vl->fields() );
|
||||
|
||||
mFieldsList->clear();
|
||||
const QgsFields& layerAttributes = vl->fields();
|
||||
for ( int idx = 0; idx < layerAttributes.count(); ++idx )
|
||||
|
||||
Q_FOREACH ( const QgsAttributeTableConfig::ColumnConfig& columnConfig, config.columns() )
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem( layerAttributes[idx].name(), mFieldsList );
|
||||
item->setCheckState( visble.contains( layerAttributes[idx].name() ) ? Qt::Checked : Qt::Unchecked );
|
||||
switch ( vl->fields().fieldOrigin( idx ) )
|
||||
QListWidgetItem* item;
|
||||
if ( columnConfig.mType == QgsAttributeTableConfig::Action )
|
||||
{
|
||||
case QgsFields::OriginExpression:
|
||||
item->setIcon( QgsApplication::getThemeIcon( "/mIconExpression.svg" ) );
|
||||
break;
|
||||
item = new QListWidgetItem( tr( "[Action Widget]" ), mFieldsList );
|
||||
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/action.svg" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
int idx = vl->fieldNameIndex( columnConfig.mName );
|
||||
item = new QListWidgetItem( vl->attributeDisplayName( idx ), mFieldsList );
|
||||
|
||||
case QgsFields::OriginJoin:
|
||||
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/join.png" ) );
|
||||
break;
|
||||
switch ( vl->fields().fieldOrigin( idx ) )
|
||||
{
|
||||
case QgsFields::OriginExpression:
|
||||
item->setIcon( QgsApplication::getThemeIcon( "/mIconExpression.svg" ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/attributes.png" ) );
|
||||
break;
|
||||
case QgsFields::OriginJoin:
|
||||
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/join.png" ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/attributes.png" ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
item->setData( Qt::UserRole, idx );
|
||||
item->setCheckState( columnConfig.mHidden ? Qt::Unchecked : Qt::Checked );
|
||||
item->setData( Qt::UserRole, QVariant::fromValue( columnConfig ) );
|
||||
}
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
restoreGeometry( settings.value( "/Windows/QgsFilterTableFieldsDialog/geometry" ).toByteArray() );
|
||||
restoreGeometry( settings.value( "/Windows/QgsOrganizeTableColumnsDialog/geometry" ).toByteArray() );
|
||||
}
|
||||
|
||||
QgsOrganizeTableColumnsDialog::~QgsOrganizeTableColumnsDialog()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.setValue( "/Windows/QgsFilterTableFieldsDialog/geometry", saveGeometry() );
|
||||
settings.setValue( "/Windows/QgsOrganizeTableColumnsDialog/geometry", saveGeometry() );
|
||||
}
|
||||
|
||||
QStringList QgsOrganizeTableColumnsDialog::selectedFields() const
|
||||
QgsAttributeTableConfig QgsOrganizeTableColumnsDialog::config() const
|
||||
{
|
||||
QStringList selectionList;
|
||||
QVector<QgsAttributeTableConfig::ColumnConfig> columns;
|
||||
|
||||
for ( int i = 0 ; i < mFieldsList->count() ; i++ )
|
||||
{
|
||||
const QListWidgetItem* item = mFieldsList->item( i );
|
||||
if ( item->checkState() == Qt::Checked )
|
||||
{
|
||||
selectionList.push_back( item->text() );
|
||||
}
|
||||
QgsAttributeTableConfig::ColumnConfig columnConfig = item->data( Qt::UserRole ).value<QgsAttributeTableConfig::ColumnConfig>();
|
||||
|
||||
columnConfig.mHidden = item->checkState() == Qt::Unchecked;
|
||||
|
||||
columns.append( columnConfig );
|
||||
}
|
||||
return selectionList;
|
||||
|
||||
QgsAttributeTableConfig config;
|
||||
config.setColumns( columns );
|
||||
return config;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include "ui_qgsorganizetablecolumnsdialog.h"
|
||||
|
||||
#include "qgsattributetableconfig.h"
|
||||
|
||||
class QgsVectorLayer;
|
||||
|
||||
class GUI_EXPORT QgsOrganizeTableColumnsDialog : public QDialog, private Ui::QgsOrganizeTableColumnsDialog
|
||||
@ -35,17 +37,17 @@ class GUI_EXPORT QgsOrganizeTableColumnsDialog : public QDialog, private Ui::Qgs
|
||||
* @param parent parent object
|
||||
* @param flags window flags
|
||||
*/
|
||||
QgsOrganizeTableColumnsDialog( const QgsVectorLayer* vl, QStringList visible, QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::Window );
|
||||
QgsOrganizeTableColumnsDialog( const QgsVectorLayer* vl, QWidget* parent = nullptr, Qt::WindowFlags flags = Qt::Window );
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~QgsOrganizeTableColumnsDialog();
|
||||
|
||||
/**
|
||||
* Get the selected fields name
|
||||
* @return The selected fields name
|
||||
* Get the updated configuration
|
||||
*/
|
||||
QStringList selectedFields() const;
|
||||
QgsAttributeTableConfig config() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>240</width>
|
||||
<height>219</height>
|
||||
<width>392</width>
|
||||
<height>357</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -15,7 +15,14 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="mFieldsList"/>
|
||||
<widget class="QListWidget" name="mFieldsList">
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
|
Loading…
x
Reference in New Issue
Block a user