mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-09 00:04:30 -05: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 qgsaction.sip
|
||||||
%Include qgsactionmanager.sip
|
%Include qgsactionmanager.sip
|
||||||
%Include qgsattributeaction.sip
|
%Include qgsattributeaction.sip
|
||||||
|
%Include qgsattributetableconfig.sip
|
||||||
%Include qgsbrowsermodel.sip
|
%Include qgsbrowsermodel.sip
|
||||||
%Include qgsclipper.sip
|
%Include qgsclipper.sip
|
||||||
%Include qgscolorscheme.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;
|
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:
|
public slots:
|
||||||
/**
|
/**
|
||||||
* Select feature by its ID
|
* Select feature by its ID
|
||||||
|
|||||||
@ -13,6 +13,18 @@ class QgsAttributeTableFilterModel: QSortFilterProxyModel, QgsFeatureModel
|
|||||||
ShowEdited
|
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.
|
* 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*/
|
/** Returns the map canvas*/
|
||||||
QgsMapCanvas* mapCanvas() const;
|
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:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Returns true if the source row will be accepted
|
* 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
|
* 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
|
* 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 object The object which is the target of the event.
|
||||||
* @param event The intercepted event
|
* @param event The intercepted event
|
||||||
|
|||||||
@ -65,6 +65,11 @@ class QgsDualView : QStackedWidget
|
|||||||
*/
|
*/
|
||||||
void setFilterMode( QgsAttributeTableFilterModel::FilterMode filterMode );
|
void setFilterMode( QgsAttributeTableFilterModel::FilterMode filterMode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the filter mode
|
||||||
|
*
|
||||||
|
* @return the filter mode
|
||||||
|
*/
|
||||||
QgsAttributeTableFilterModel::FilterMode filterMode();
|
QgsAttributeTableFilterModel::FilterMode filterMode();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,6 +103,9 @@ class QgsDualView : QStackedWidget
|
|||||||
*/
|
*/
|
||||||
void setFilteredFeatures( const QgsFeatureIds& filteredFeatures );
|
void setFilteredFeatures( const QgsFeatureIds& filteredFeatures );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of currently visible feature ids.
|
||||||
|
*/
|
||||||
QgsFeatureIds filteredFeatures();
|
QgsFeatureIds filteredFeatures();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,6 +120,11 @@ class QgsDualView : QStackedWidget
|
|||||||
void setFeatureSelectionManager( QgsIFeatureSelectionManager* featureSelectionManager );
|
void setFeatureSelectionManager( QgsIFeatureSelectionManager* featureSelectionManager );
|
||||||
|
|
||||||
QgsAttributeTableView* tableView();
|
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:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -8,16 +8,19 @@ class QgsOrganizeTableColumnsDialog : QDialog
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param vl The concerned vector layer
|
* @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 parent parent object
|
||||||
* @param flags window flags
|
* @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();
|
~QgsOrganizeTableColumnsDialog();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the selected fields name
|
* Get the updated configuration
|
||||||
* @return The selected fields name
|
|
||||||
*/
|
*/
|
||||||
QStringList selectedFields();
|
QgsAttributeTableConfig config() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -125,6 +125,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
|
|||||||
|
|
||||||
// Initialize dual view
|
// Initialize dual view
|
||||||
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, context );
|
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, context );
|
||||||
|
mMainView->setAttributeTableConfig( mLayer->attributeTableConfig() );
|
||||||
|
|
||||||
// Initialize filter gui elements
|
// Initialize filter gui elements
|
||||||
mFilterActionMapper = new QSignalMapper( this );
|
mFilterActionMapper = new QSignalMapper( this );
|
||||||
@ -776,17 +777,12 @@ void QgsAttributeTableDialog::on_mFilterTableFields_clicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsOrganizeTableColumnsDialog dialog( mLayer, mVisibleFields );
|
QgsOrganizeTableColumnsDialog dialog( mLayer );
|
||||||
if ( dialog.exec() == QDialog::Accepted )
|
if ( dialog.exec() == QDialog::Accepted )
|
||||||
{
|
{
|
||||||
mVisibleFields = dialog.selectedFields();
|
QgsAttributeTableConfig config = dialog.config();
|
||||||
|
mLayer->setAttributeTableConfig( config );
|
||||||
const QgsFields layerAttributes = mLayer->fields();
|
mMainView->setAttributeTableConfig( config );
|
||||||
for ( int idx = 0; idx < layerAttributes.count(); ++idx )
|
|
||||||
{
|
|
||||||
mMainView->tableView()->setColumnHidden(
|
|
||||||
idx, !mVisibleFields.contains( layerAttributes[idx].name() ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -79,6 +79,7 @@ SET(QGIS_CORE_SRCS
|
|||||||
qgsapplication.cpp
|
qgsapplication.cpp
|
||||||
qgsaction.cpp
|
qgsaction.cpp
|
||||||
qgsactionmanager.cpp
|
qgsactionmanager.cpp
|
||||||
|
qgsattributetableconfig.cpp
|
||||||
qgsbrowsermodel.cpp
|
qgsbrowsermodel.cpp
|
||||||
qgscachedfeatureiterator.cpp
|
qgscachedfeatureiterator.cpp
|
||||||
qgscacheindex.cpp
|
qgscacheindex.cpp
|
||||||
@ -591,7 +592,7 @@ SET(QGIS_CORE_HDRS
|
|||||||
|
|
||||||
qgis.h
|
qgis.h
|
||||||
qgsaction.h
|
qgsaction.h
|
||||||
qgsactionmanager.h
|
qgsattributetableconfig.h
|
||||||
qgsattributeaction.h
|
qgsattributeaction.h
|
||||||
qgscachedfeatureiterator.h
|
qgscachedfeatureiterator.h
|
||||||
qgscacheindex.h
|
qgscacheindex.h
|
||||||
|
|||||||
@ -23,7 +23,6 @@ email : marco.hugentobler at sourcepole dot com
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class QgsCoordinateTransform;
|
|
||||||
class QgsMapToPixel;
|
class QgsMapToPixel;
|
||||||
class QgsCurveV2;
|
class QgsCurveV2;
|
||||||
class QgsMultiCurveV2;
|
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 );
|
void invalidateCrs( const QString& crsAuthId );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QgsCoordinateTransformCache* mInstance;
|
|
||||||
QMultiHash< QPair< QString, QString >, QgsCoordinateTransform* > mTransforms; //same auth_id pairs might have different datum transformations
|
QMultiHash< QPair< QString, QString >, QgsCoordinateTransform* > mTransforms; //same auth_id pairs might have different datum transformations
|
||||||
|
|
||||||
QgsCoordinateTransformCache();
|
QgsCoordinateTransformCache();
|
||||||
|
|||||||
@ -1926,8 +1926,6 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
|
|||||||
// process the attribute actions
|
// process the attribute actions
|
||||||
mActions->readXML( node );
|
mActions->readXML( node );
|
||||||
|
|
||||||
mEditFormConfig->readXml( node );
|
|
||||||
|
|
||||||
QDomNode annotationFormNode = node.namedItem( "annotationform" );
|
QDomNode annotationFormNode = node.namedItem( "annotationform" );
|
||||||
if ( !annotationFormNode.isNull() )
|
if ( !annotationFormNode.isNull() )
|
||||||
{
|
{
|
||||||
@ -1988,6 +1986,8 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
|
|||||||
|
|
||||||
mEditFormConfig->readXml( node );
|
mEditFormConfig->readXml( node );
|
||||||
|
|
||||||
|
mAttributeTableConfig.readXml( node );
|
||||||
|
|
||||||
mConditionalStyles->readXml( node );
|
mConditionalStyles->readXml( node );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2154,6 +2154,8 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
|
|||||||
|
|
||||||
mEditFormConfig->writeXml( node );
|
mEditFormConfig->writeXml( node );
|
||||||
|
|
||||||
|
mAttributeTableConfig.writeXml( node );
|
||||||
|
|
||||||
mConditionalStyles->writeXml( node, doc );
|
mConditionalStyles->writeXml( node, doc );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2266,11 +2268,11 @@ void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString
|
|||||||
QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
|
QString QgsVectorLayer::attributeAlias( int attributeIndex ) const
|
||||||
{
|
{
|
||||||
if ( attributeIndex < 0 || attributeIndex >= fields().count() )
|
if ( attributeIndex < 0 || attributeIndex >= fields().count() )
|
||||||
return "";
|
return QString();
|
||||||
|
|
||||||
QString name = fields().at( attributeIndex ).name();
|
QString name = fields().at( attributeIndex ).name();
|
||||||
|
|
||||||
return mAttributeAliasMap.value( name, "" );
|
return mAttributeAliasMap.value( name, QString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsVectorLayer::attributeDisplayName( int attributeIndex ) const
|
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 )
|
void QgsVectorLayer::setDiagramLayerSettings( const QgsDiagramLayerSettings& s )
|
||||||
{
|
{
|
||||||
if ( !mDiagramLayerSettings )
|
if ( !mDiagramLayerSettings )
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
#include "qgssnapper.h"
|
#include "qgssnapper.h"
|
||||||
#include "qgsvectorsimplifymethod.h"
|
#include "qgsvectorsimplifymethod.h"
|
||||||
#include "qgseditformconfig.h"
|
#include "qgseditformconfig.h"
|
||||||
|
#include "qgsattributetableconfig.h"
|
||||||
|
|
||||||
class QPainter;
|
class QPainter;
|
||||||
class QImage;
|
class QImage;
|
||||||
@ -631,7 +632,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
|||||||
* The pointer which is returned directly points to the actions object
|
* The pointer which is returned directly points to the actions object
|
||||||
* which is used by the layer, so any changes are immediately applied.
|
* 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
|
* The number of features that are selected in this layer
|
||||||
@ -1321,7 +1322,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
|||||||
*/
|
*/
|
||||||
void clearAttributeEditorWidgets() { mEditFormConfig->clearTabs(); }
|
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;
|
QString attributeAlias( int attributeIndex ) const;
|
||||||
|
|
||||||
/** Convenience function that returns the attribute alias if defined or the field name else */
|
/** 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;
|
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:
|
public slots:
|
||||||
/**
|
/**
|
||||||
* Select feature by its ID
|
* Select feature by its ID
|
||||||
@ -2088,6 +2106,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
|||||||
|
|
||||||
QgsFeatureIds mDeletedFids;
|
QgsFeatureIds mDeletedFids;
|
||||||
|
|
||||||
|
QgsAttributeTableConfig mAttributeTableConfig;
|
||||||
|
|
||||||
friend class QgsVectorLayerFeatureSource;
|
friend class QgsVectorLayerFeatureSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -118,9 +118,23 @@ void QgsAttributeTableDelegate::setFeatureSelectionModel( QgsFeatureSelectionMod
|
|||||||
mFeatureSelectionModel = featureSelectionModel;
|
mFeatureSelectionModel = featureSelectionModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTableDelegate::setActionWidgetImage( const QImage& image )
|
||||||
|
{
|
||||||
|
mActionWidgetImage = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsAttributeTableDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
void QgsAttributeTableDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||||
{
|
{
|
||||||
|
QgsAttributeTableFilterModel::ColumnType columnType = static_cast<QgsAttributeTableFilterModel::ColumnType>( index.model()->data( index, QgsAttributeTableFilterModel::TypeRole ).toInt() );
|
||||||
|
|
||||||
|
if ( columnType == QgsAttributeTableFilterModel::ColumnTypeActionButton )
|
||||||
|
{
|
||||||
|
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();
|
QgsFeatureId fid = index.model()->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong();
|
||||||
|
|
||||||
QStyleOptionViewItem myOpt = option;
|
QStyleOptionViewItem myOpt = option;
|
||||||
@ -134,13 +148,6 @@ void QgsAttributeTableDelegate::paint( QPainter* painter, const QStyleOptionView
|
|||||||
if ( mFeatureSelectionModel && mFeatureSelectionModel->isSelected( fid ) )
|
if ( mFeatureSelectionModel && mFeatureSelectionModel->isSelected( fid ) )
|
||||||
myOpt.state |= QStyle::State_Selected;
|
myOpt.state |= QStyle::State_Selected;
|
||||||
|
|
||||||
|
|
||||||
if ( index.column() == 0 )
|
|
||||||
{
|
|
||||||
painter->drawImage( QPoint( 0, 0 ), mActionButtonImage );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QItemDelegate::paint( painter, myOpt, index );
|
QItemDelegate::paint( painter, myOpt, index );
|
||||||
|
|
||||||
if ( option.state & QStyle::State_HasFocus )
|
if ( option.state & QStyle::State_HasFocus )
|
||||||
|
|||||||
@ -46,7 +46,6 @@ class GUI_EXPORT QgsAttributeTableDelegate : public QItemDelegate
|
|||||||
: QItemDelegate( parent )
|
: QItemDelegate( parent )
|
||||||
, mLayer( nullptr )
|
, mLayer( nullptr )
|
||||||
, mFeatureSelectionModel( nullptr )
|
, mFeatureSelectionModel( nullptr )
|
||||||
, mActionButtonWidget( nullptr )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,13 +79,15 @@ class GUI_EXPORT QgsAttributeTableDelegate : public QItemDelegate
|
|||||||
|
|
||||||
void setFeatureSelectionModel( QgsFeatureSelectionModel* featureSelectionModel );
|
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;
|
QgsVectorLayer* mLayer;
|
||||||
QgsFeatureSelectionModel* mFeatureSelectionModel;
|
QgsFeatureSelectionModel* mFeatureSelectionModel;
|
||||||
QWidget* mActionButtonWidget;
|
QImage mActionWidgetImage;
|
||||||
QImage mActionButtonImage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //QGSATTRIBUTETABLEDELEGATE_H
|
#endif //QGSATTRIBUTETABLEDELEGATE_H
|
||||||
|
|||||||
@ -69,13 +69,93 @@ void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
|
|||||||
|
|
||||||
QVariant QgsAttributeTableFilterModel::data( const QModelIndex& index, int role ) const
|
QVariant QgsAttributeTableFilterModel::data( const QModelIndex& index, int role ) const
|
||||||
{
|
{
|
||||||
if ( index.column() == 0 )
|
if ( mColumnMapping.at( index.column() ) == -1 ) // actions
|
||||||
return "Wow";
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
QModelIndex sourceIndex = QSortFilterProxyModel::index( index.row(), index.column() - 1, index.parent() );
|
if ( role == TypeRole )
|
||||||
return QSortFilterProxyModel::data( sourceIndex, role );
|
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 )
|
void QgsAttributeTableFilterModel::setSelectedOnTop( bool selectedOnTop )
|
||||||
@ -96,6 +176,12 @@ void QgsAttributeTableFilterModel::setSourceModel( QgsAttributeTableModel* sourc
|
|||||||
{
|
{
|
||||||
mTableModel = sourceModel;
|
mTableModel = sourceModel;
|
||||||
|
|
||||||
|
mColumnMapping.append( -1 ); // -1 for actions column
|
||||||
|
for ( int i = 0; i < mTableModel->columnCount(); ++i )
|
||||||
|
{
|
||||||
|
mColumnMapping.append( i );
|
||||||
|
}
|
||||||
|
|
||||||
QSortFilterProxyModel::setSourceModel( sourceModel );
|
QSortFilterProxyModel::setSourceModel( sourceModel );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,14 +396,23 @@ QModelIndexList QgsAttributeTableFilterModel::fidToIndexList( QgsFeatureId fid )
|
|||||||
return indexes;
|
return indexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex QgsAttributeTableFilterModel::mapToMaster( const QModelIndex &proxyIndex ) const
|
QModelIndex QgsAttributeTableFilterModel::mapToSource( const QModelIndex& proxyIndex ) const
|
||||||
{
|
{
|
||||||
// Master is source
|
if ( !proxyIndex.isValid() )
|
||||||
return mapToSource( proxyIndex );
|
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
|
QModelIndex proxyIndex = QSortFilterProxyModel::mapFromSource( sourceIndex );
|
||||||
return mapFromSource( sourceIndex );
|
|
||||||
|
return index( proxyIndex.row(), mColumnMapping.indexOf( proxyIndex.column() ), proxyIndex.parent() );
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,17 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
|
|||||||
ShowEdited
|
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 );
|
QgsFeatureId rowToId( const QModelIndex& row );
|
||||||
|
|
||||||
QModelIndex fidToIndex( QgsFeatureId fid ) override;
|
QModelIndex fidToIndex( QgsFeatureId fid ) override;
|
||||||
|
|
||||||
QModelIndexList fidToIndexList( QgsFeatureId fid );
|
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.
|
* 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;
|
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:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Returns true if the source row will be accepted
|
* Returns true if the source row will be accepted
|
||||||
@ -195,6 +228,8 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
|
|||||||
FilterMode mFilterMode;
|
FilterMode mFilterMode;
|
||||||
bool mSelectedOnTop;
|
bool mSelectedOnTop;
|
||||||
QgsAttributeTableModel* mTableModel;
|
QgsAttributeTableModel* mTableModel;
|
||||||
|
|
||||||
|
QVector<int> mColumnMapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -51,9 +51,10 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
|
|||||||
public:
|
public:
|
||||||
enum Role
|
enum Role
|
||||||
{
|
{
|
||||||
SortRole = Qt::UserRole + 1,
|
SortRole = Qt::UserRole + 1, //!< Role used for sorting
|
||||||
FeatureIdRole = Qt::UserRole + 2,
|
FeatureIdRole, //!< Get the feature id of the feature in this row
|
||||||
FieldIndexRole = Qt::UserRole + 3
|
FieldIndexRole, //!< Get the field index of this column
|
||||||
|
UserRole //!< Start further roles starting from this role
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -64,14 +64,10 @@ QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
|
|||||||
|
|
||||||
connect( verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( selectRow( int ) ) );
|
connect( verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( selectRow( int ) ) );
|
||||||
connect( verticalHeader(), SIGNAL( sectionEntered( int ) ), this, SLOT( _q_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() ) );
|
connect( horizontalHeader(), SIGNAL( sortIndicatorChanged( int, Qt::SortOrder ) ), this, SLOT( showHorizontalSortIndicator() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsAttributeTableView::~QgsAttributeTableView()
|
|
||||||
{
|
|
||||||
delete mActionPopup;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QgsAttributeTableView::eventFilter( QObject *object, QEvent *event )
|
bool QgsAttributeTableView::eventFilter( QObject *object, QEvent *event )
|
||||||
{
|
{
|
||||||
if ( object == verticalHeader()->viewport() )
|
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( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
|
||||||
connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
|
connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mActionWidget = createActionWidget( 0 );
|
||||||
|
mActionWidget->setVisible( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableView::setFeatureSelectionManager( QgsIFeatureSelectionManager* featureSelectionManager )
|
void QgsAttributeTableView::setFeatureSelectionManager( QgsIFeatureSelectionManager* featureSelectionManager )
|
||||||
@ -136,19 +135,35 @@ void QgsAttributeTableView::setFeatureSelectionManager( QgsIFeatureSelectionMana
|
|||||||
mFeatureSelectionModel->setFeatureSelectionManager( mFeatureSelectionManager );
|
mFeatureSelectionModel->setFeatureSelectionManager( mFeatureSelectionManager );
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* QgsAttributeTableView::createActionWidget()
|
QWidget* QgsAttributeTableView::createActionWidget( QgsFeatureId fid )
|
||||||
{
|
{
|
||||||
QToolButton* toolButton = new QToolButton( this );
|
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 );
|
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;
|
return toolButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,12 +191,12 @@ void QgsAttributeTableView::mouseReleaseEvent( QMouseEvent *event )
|
|||||||
void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event )
|
void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event )
|
||||||
{
|
{
|
||||||
QModelIndex index = indexAt( event->pos() );
|
QModelIndex index = indexAt( event->pos() );
|
||||||
if ( index.column() == 0 )
|
if ( index.data( QgsAttributeTableFilterModel::TypeRole ) == QgsAttributeTableFilterModel::ColumnTypeActionButton )
|
||||||
{
|
{
|
||||||
Q_ASSERT( index.isValid() );
|
Q_ASSERT( index.isValid() );
|
||||||
|
|
||||||
if ( !indexWidget( index ) )
|
if ( !indexWidget( index ) )
|
||||||
setIndexWidget( index, createActionWidget() );
|
setIndexWidget( index, createActionWidget( mFilterModel->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectionMode( QAbstractItemView::NoSelection );
|
setSelectionMode( QAbstractItemView::NoSelection );
|
||||||
@ -246,7 +261,7 @@ void QgsAttributeTableView::contextMenuEvent( QContextMenuEvent* event )
|
|||||||
if ( !vlayer )
|
if ( !vlayer )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mActionPopup = new QMenu();
|
mActionPopup = new QMenu( this );
|
||||||
|
|
||||||
mActionPopup->addAction( tr( "Select All" ), this, SLOT( selectAll() ), QKeySequence::SelectAll );
|
mActionPopup->addAction( tr( "Select All" ), this, SLOT( selectAll() ), QKeySequence::SelectAll );
|
||||||
|
|
||||||
@ -318,3 +333,32 @@ void QgsAttributeTableView::showHorizontalSortIndicator()
|
|||||||
{
|
{
|
||||||
horizontalHeader()->setSortIndicatorShown( true );
|
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:
|
public:
|
||||||
QgsAttributeTableView( QWidget* parent = nullptr );
|
QgsAttributeTableView( QWidget* parent = nullptr );
|
||||||
virtual ~QgsAttributeTableView();
|
|
||||||
|
|
||||||
virtual void setModel( QgsAttributeTableFilterModel* filterModel );
|
virtual void setModel( QgsAttributeTableFilterModel* filterModel );
|
||||||
|
|
||||||
@ -140,9 +139,12 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
|
|||||||
private slots:
|
private slots:
|
||||||
void modelDeleted();
|
void modelDeleted();
|
||||||
void showHorizontalSortIndicator();
|
void showHorizontalSortIndicator();
|
||||||
|
void actionTriggered();
|
||||||
|
void columnSizeChanged( int index, int oldWidth, int newWidth );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget* createActionWidget();
|
void updateActionImage( QWidget* widget );
|
||||||
|
QWidget* createActionWidget( QgsFeatureId fid );
|
||||||
|
|
||||||
void selectRow( int row, bool anchor );
|
void selectRow( int row, bool anchor );
|
||||||
QgsAttributeTableModel* mMasterModel;
|
QgsAttributeTableModel* mMasterModel;
|
||||||
@ -154,6 +156,7 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
|
|||||||
QMenu *mActionPopup;
|
QMenu *mActionPopup;
|
||||||
int mRowSectionAnchor;
|
int mRowSectionAnchor;
|
||||||
QItemSelectionModel::SelectionFlag mCtrlDragSelectionFlag;
|
QItemSelectionModel::SelectionFlag mCtrlDragSelectionFlag;
|
||||||
|
QWidget* mActionWidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -464,6 +464,11 @@ void QgsDualView::setFeatureSelectionManager( QgsIFeatureSelectionManager* featu
|
|||||||
mFeatureSelectionManager = featureSelectionManager;
|
mFeatureSelectionManager = featureSelectionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsDualView::setAttributeTableConfig( const QgsAttributeTableConfig& config )
|
||||||
|
{
|
||||||
|
mFilterModel->setAttributeTableConfig( config );
|
||||||
|
}
|
||||||
|
|
||||||
void QgsDualView::progress( int i, bool& cancel )
|
void QgsDualView::progress( int i, bool& cancel )
|
||||||
{
|
{
|
||||||
if ( !mProgressDlg )
|
if ( !mProgressDlg )
|
||||||
|
|||||||
@ -141,6 +141,9 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
|
|||||||
*/
|
*/
|
||||||
void setFilteredFeatures( const QgsFeatureIds& filteredFeatures );
|
void setFilteredFeatures( const QgsFeatureIds& filteredFeatures );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of currently visible feature ids.
|
||||||
|
*/
|
||||||
QgsFeatureIds filteredFeatures() { return mFilterModel->filteredFeatures(); }
|
QgsFeatureIds filteredFeatures() { return mFilterModel->filteredFeatures(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,7 +172,13 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
|
|||||||
*
|
*
|
||||||
* @return The table view
|
* @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:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -41,18 +41,30 @@
|
|||||||
#include "qgseditorwidgetregistry.h"
|
#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 )
|
: QDialog( parent, flags )
|
||||||
{
|
{
|
||||||
setupUi( this );
|
setupUi( this );
|
||||||
if ( vl )
|
if ( vl )
|
||||||
{
|
{
|
||||||
|
QgsAttributeTableConfig config = vl->attributeTableConfig();
|
||||||
|
config.update( vl->fields() );
|
||||||
|
|
||||||
mFieldsList->clear();
|
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 );
|
QListWidgetItem* item;
|
||||||
item->setCheckState( visble.contains( layerAttributes[idx].name() ) ? Qt::Checked : Qt::Unchecked );
|
if ( columnConfig.mType == QgsAttributeTableConfig::Action )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
|
||||||
switch ( vl->fields().fieldOrigin( idx ) )
|
switch ( vl->fields().fieldOrigin( idx ) )
|
||||||
{
|
{
|
||||||
case QgsFields::OriginExpression:
|
case QgsFields::OriginExpression:
|
||||||
@ -67,31 +79,38 @@ QgsOrganizeTableColumnsDialog::QgsOrganizeTableColumnsDialog( const QgsVectorLay
|
|||||||
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/attributes.png" ) );
|
item->setIcon( QgsApplication::getThemeIcon( "/propertyicons/attributes.png" ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
item->setData( Qt::UserRole, idx );
|
item->setCheckState( columnConfig.mHidden ? Qt::Unchecked : Qt::Checked );
|
||||||
|
item->setData( Qt::UserRole, QVariant::fromValue( columnConfig ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
restoreGeometry( settings.value( "/Windows/QgsFilterTableFieldsDialog/geometry" ).toByteArray() );
|
restoreGeometry( settings.value( "/Windows/QgsOrganizeTableColumnsDialog/geometry" ).toByteArray() );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsOrganizeTableColumnsDialog::~QgsOrganizeTableColumnsDialog()
|
QgsOrganizeTableColumnsDialog::~QgsOrganizeTableColumnsDialog()
|
||||||
{
|
{
|
||||||
QSettings settings;
|
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++ )
|
for ( int i = 0 ; i < mFieldsList->count() ; i++ )
|
||||||
{
|
{
|
||||||
const QListWidgetItem* item = mFieldsList->item( i );
|
const QListWidgetItem* item = mFieldsList->item( i );
|
||||||
if ( item->checkState() == Qt::Checked )
|
QgsAttributeTableConfig::ColumnConfig columnConfig = item->data( Qt::UserRole ).value<QgsAttributeTableConfig::ColumnConfig>();
|
||||||
{
|
|
||||||
selectionList.push_back( item->text() );
|
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 "ui_qgsorganizetablecolumnsdialog.h"
|
||||||
|
|
||||||
|
#include "qgsattributetableconfig.h"
|
||||||
|
|
||||||
class QgsVectorLayer;
|
class QgsVectorLayer;
|
||||||
|
|
||||||
class GUI_EXPORT QgsOrganizeTableColumnsDialog : public QDialog, private Ui::QgsOrganizeTableColumnsDialog
|
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 parent parent object
|
||||||
* @param flags window flags
|
* @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
|
* Destructor
|
||||||
*/
|
*/
|
||||||
~QgsOrganizeTableColumnsDialog();
|
~QgsOrganizeTableColumnsDialog();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the selected fields name
|
* Get the updated configuration
|
||||||
* @return The selected fields name
|
|
||||||
*/
|
*/
|
||||||
QStringList selectedFields() const;
|
QgsAttributeTableConfig config() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>240</width>
|
<width>392</width>
|
||||||
<height>219</height>
|
<height>357</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -15,7 +15,14 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<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>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user